mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Refactor and simpfily
This commit is contained in:
parent
62ed93db13
commit
d01e0abdb5
5 changed files with 43 additions and 90 deletions
|
@ -8,22 +8,10 @@ use ra_prof::profile;
|
||||||
use ra_syntax::{AstNode, Parse, SyntaxNode};
|
use ra_syntax::{AstNode, Parse, SyntaxNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_id_map::AstIdMap, ExpansionInfo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc,
|
ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
|
||||||
MacroDefId, MacroFile, MacroFileKind,
|
MacroFile, MacroFileKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
||||||
pub struct ParseMacroWithInfo {
|
|
||||||
pub parsed: Parse<SyntaxNode>,
|
|
||||||
pub expansion_info: Arc<ExpansionInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
||||||
pub struct MacroExpandInfo {
|
|
||||||
pub arg_map: Arc<mbe::TokenMap>,
|
|
||||||
pub def_map: Arc<mbe::TokenMap>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: rename to ExpandDatabase
|
// FIXME: rename to ExpandDatabase
|
||||||
#[salsa::query_group(AstDatabaseStorage)]
|
#[salsa::query_group(AstDatabaseStorage)]
|
||||||
pub trait AstDatabase: SourceDatabase {
|
pub trait AstDatabase: SourceDatabase {
|
||||||
|
@ -36,14 +24,11 @@ pub trait AstDatabase: SourceDatabase {
|
||||||
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
|
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
|
||||||
fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>;
|
fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>;
|
||||||
fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>;
|
fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>;
|
||||||
fn parse_macro(&self, macro_file: MacroFile) -> Option<Parse<SyntaxNode>>;
|
fn parse_macro(
|
||||||
fn parse_macro_with_info(&self, macro_file: MacroFile) -> Option<ParseMacroWithInfo>;
|
|
||||||
fn macro_expand(
|
|
||||||
&self,
|
&self,
|
||||||
macro_call: MacroCallId,
|
macro_file: MacroFile,
|
||||||
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String>;
|
) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)>;
|
||||||
|
fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>;
|
||||||
fn macro_expansion_info(&self, macro_file: MacroFile) -> Option<Arc<ExpansionInfo>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
|
pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
|
||||||
|
@ -83,7 +68,7 @@ pub(crate) fn macro_arg(
|
||||||
pub(crate) fn macro_expand(
|
pub(crate) fn macro_expand(
|
||||||
db: &dyn AstDatabase,
|
db: &dyn AstDatabase,
|
||||||
id: MacroCallId,
|
id: MacroCallId,
|
||||||
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String> {
|
) -> Result<Arc<tt::Subtree>, String> {
|
||||||
let loc = db.lookup_intern_macro(id);
|
let loc = db.lookup_intern_macro(id);
|
||||||
let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
|
let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
|
||||||
|
|
||||||
|
@ -94,18 +79,14 @@ pub(crate) fn macro_expand(
|
||||||
if count > 65536 {
|
if count > 65536 {
|
||||||
return Err(format!("Total tokens count exceed limit : count = {}", count));
|
return Err(format!("Total tokens count exceed limit : count = {}", count));
|
||||||
}
|
}
|
||||||
|
Ok(Arc::new(tt))
|
||||||
Ok((
|
|
||||||
Arc::new(tt),
|
|
||||||
MacroExpandInfo { arg_map: macro_arg.1.clone(), def_map: macro_rules.1.clone() },
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
|
pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
|
||||||
match file_id.0 {
|
match file_id.0 {
|
||||||
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
|
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
|
||||||
HirFileIdRepr::MacroFile(macro_file) => {
|
HirFileIdRepr::MacroFile(macro_file) => {
|
||||||
db.parse_macro(macro_file).map(|it| it.syntax_node())
|
db.parse_macro(macro_file).map(|(it, _)| it.syntax_node())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,15 +94,9 @@ pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Optio
|
||||||
pub(crate) fn parse_macro(
|
pub(crate) fn parse_macro(
|
||||||
db: &dyn AstDatabase,
|
db: &dyn AstDatabase,
|
||||||
macro_file: MacroFile,
|
macro_file: MacroFile,
|
||||||
) -> Option<Parse<SyntaxNode>> {
|
) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)> {
|
||||||
let _p = profile("parse_macro_query");
|
let _p = profile("parse_macro_query");
|
||||||
db.parse_macro_with_info(macro_file).map(|r| r.parsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn parse_macro_with_info(
|
|
||||||
db: &dyn AstDatabase,
|
|
||||||
macro_file: MacroFile,
|
|
||||||
) -> Option<ParseMacroWithInfo> {
|
|
||||||
let macro_call_id = macro_file.macro_call_id;
|
let macro_call_id = macro_file.macro_call_id;
|
||||||
let tt = db
|
let tt = db
|
||||||
.macro_expand(macro_call_id)
|
.macro_expand(macro_call_id)
|
||||||
|
@ -133,39 +108,12 @@ pub(crate) fn parse_macro_with_info(
|
||||||
})
|
})
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
let (parsed, exp_map) = match macro_file.macro_file_kind {
|
match macro_file.macro_file_kind {
|
||||||
MacroFileKind::Items => {
|
MacroFileKind::Items => {
|
||||||
mbe::token_tree_to_items(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()?
|
mbe::token_tree_to_items(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
|
||||||
}
|
}
|
||||||
MacroFileKind::Expr => {
|
MacroFileKind::Expr => {
|
||||||
mbe::token_tree_to_expr(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()?
|
mbe::token_tree_to_expr(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
let expand_info = tt.1;
|
|
||||||
let loc: MacroCallLoc = db.lookup_intern_macro(macro_call_id);
|
|
||||||
|
|
||||||
let arg_tt = loc.ast_id.to_node(db).token_tree();
|
|
||||||
let def_tt = loc.def.ast_id.to_node(db).token_tree();
|
|
||||||
|
|
||||||
let arg_range = arg_tt.map(|t| t.syntax().text_range());
|
|
||||||
let def_range = def_tt.map(|t| t.syntax().text_range());
|
|
||||||
|
|
||||||
let shift = db.macro_def(loc.def)?.0.shift();
|
|
||||||
|
|
||||||
let arg_map =
|
|
||||||
arg_range.map(|it| exp_map.map_ranges(&expand_info.arg_map, it, shift)).unwrap_or_default();
|
|
||||||
let def_map =
|
|
||||||
def_range.map(|it| exp_map.map_ranges(&expand_info.def_map, it, 0)).unwrap_or_default();
|
|
||||||
|
|
||||||
let info = ExpansionInfo { arg_map, def_map };
|
|
||||||
|
|
||||||
Some(ParseMacroWithInfo { parsed, expansion_info: Arc::new(info) })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn macro_expansion_info(
|
|
||||||
db: &dyn AstDatabase,
|
|
||||||
macro_file: MacroFile,
|
|
||||||
) -> Option<Arc<ExpansionInfo>> {
|
|
||||||
db.parse_macro_with_info(macro_file).map(|res| res.expansion_info.clone())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast_id_map::FileAstId;
|
use crate::ast_id_map::FileAstId;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
/// Input to the analyzer is a set of files, where each file is identified by
|
/// Input to the analyzer is a set of files, where each file is identified by
|
||||||
/// `FileId` and contains source code. However, another source of source code in
|
/// `FileId` and contains source code. However, another source of source code in
|
||||||
|
@ -69,19 +68,29 @@ impl HirFileId {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return expansion information if it is a macro-expansion file
|
/// Return expansion information if it is a macro-expansion file
|
||||||
pub fn parent_expansion(
|
pub fn parent_expansion(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
|
||||||
self,
|
|
||||||
db: &dyn db::AstDatabase,
|
|
||||||
) -> Option<((HirFileId, HirFileId), Arc<ExpansionInfo>)> {
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
HirFileIdRepr::FileId(_) => None,
|
HirFileIdRepr::FileId(_) => None,
|
||||||
HirFileIdRepr::MacroFile(macro_file) => {
|
HirFileIdRepr::MacroFile(macro_file) => {
|
||||||
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
|
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
|
||||||
|
|
||||||
let def_file = loc.def.ast_id.file_id;
|
let arg_range = loc.ast_id.to_node(db).token_tree()?.syntax().text_range();
|
||||||
let arg_file = loc.ast_id.file_id;
|
let def_range = loc.def.ast_id.to_node(db).token_tree()?.syntax().text_range();
|
||||||
|
|
||||||
db.macro_expansion_info(macro_file).map(|ex| ((arg_file, def_file), ex))
|
let macro_def = db.macro_def(loc.def)?;
|
||||||
|
let shift = macro_def.0.shift();
|
||||||
|
let rev_map = db.parse_macro(macro_file)?.1;
|
||||||
|
|
||||||
|
let arg_token_map = db.macro_arg(macro_file.macro_call_id)?.1;
|
||||||
|
let def_token_map = macro_def.1;
|
||||||
|
|
||||||
|
let arg_map = rev_map.map_ranges(&arg_token_map, arg_range, shift);
|
||||||
|
let def_map = rev_map.map_ranges(&def_token_map, def_range, 0);
|
||||||
|
|
||||||
|
let arg_file = loc.ast_id.file_id;
|
||||||
|
let def_file = loc.def.ast_id.file_id;
|
||||||
|
|
||||||
|
Some(ExpansionInfo { arg_file, def_file, arg_map, def_map })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,25 +143,24 @@ impl MacroCallId {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
/// ExpansionInfo mainly describes how to map text range between src and expanded macro
|
/// ExpansionInfo mainly describes how to map text range between src and expanded macro
|
||||||
pub struct ExpansionInfo {
|
pub struct ExpansionInfo {
|
||||||
pub arg_map: Vec<(TextRange, TextRange)>,
|
pub(crate) arg_file: HirFileId,
|
||||||
pub def_map: Vec<(TextRange, TextRange)>,
|
pub(crate) def_file: HirFileId,
|
||||||
|
|
||||||
|
pub(crate) arg_map: Vec<(TextRange, TextRange)>,
|
||||||
|
pub(crate) def_map: Vec<(TextRange, TextRange)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpansionInfo {
|
impl ExpansionInfo {
|
||||||
pub fn find_range(
|
pub fn find_range(&self, from: TextRange) -> Option<(HirFileId, TextRange)> {
|
||||||
&self,
|
|
||||||
from: TextRange,
|
|
||||||
(arg_file_id, def_file_id): (HirFileId, HirFileId),
|
|
||||||
) -> Option<(HirFileId, TextRange)> {
|
|
||||||
for (src, dest) in &self.arg_map {
|
for (src, dest) in &self.arg_map {
|
||||||
if src.is_subrange(&from) {
|
if src.is_subrange(&from) {
|
||||||
return Some((arg_file_id, *dest));
|
return Some((self.arg_file, *dest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (src, dest) in &self.def_map {
|
for (src, dest) in &self.def_map {
|
||||||
if src.is_subrange(&from) {
|
if src.is_subrange(&from) {
|
||||||
return Some((def_file_id, *dest));
|
return Some((self.def_file, *dest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn find_range_from_node(
|
||||||
let text_range = node.text_range();
|
let text_range = node.text_range();
|
||||||
let (file_id, text_range) = src
|
let (file_id, text_range) = src
|
||||||
.parent_expansion(db)
|
.parent_expansion(db)
|
||||||
.and_then(|(files, expansion_info)| expansion_info.find_range(text_range, files))
|
.and_then(|expansion_info| expansion_info.find_range(text_range))
|
||||||
.unwrap_or((src, text_range));
|
.unwrap_or((src, text_range));
|
||||||
|
|
||||||
// FIXME: handle recursive macro generated macro
|
// FIXME: handle recursive macro generated macro
|
||||||
|
@ -139,7 +139,6 @@ impl NavigationTarget {
|
||||||
pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
|
pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
|
||||||
let src = module.definition_source(db);
|
let src = module.definition_source(db);
|
||||||
let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
|
let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
|
||||||
|
|
||||||
match src.ast {
|
match src.ast {
|
||||||
ModuleSource::SourceFile(node) => {
|
ModuleSource::SourceFile(node) => {
|
||||||
let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());
|
let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());
|
||||||
|
@ -324,9 +323,7 @@ impl NavigationTarget {
|
||||||
) -> NavigationTarget {
|
) -> NavigationTarget {
|
||||||
//FIXME: use `_` instead of empty string
|
//FIXME: use `_` instead of empty string
|
||||||
let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
|
let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
|
||||||
|
|
||||||
let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1);
|
let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1);
|
||||||
|
|
||||||
let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax());
|
let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax());
|
||||||
|
|
||||||
NavigationTarget::from_syntax(
|
NavigationTarget::from_syntax(
|
||||||
|
|
|
@ -94,10 +94,10 @@ impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<TableEntry<MacroFile, Option<Parse<SyntaxNode>>>> for SyntaxTreeStats {
|
impl<M> FromIterator<TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>> for SyntaxTreeStats {
|
||||||
fn from_iter<T>(iter: T) -> SyntaxTreeStats
|
fn from_iter<T>(iter: T) -> SyntaxTreeStats
|
||||||
where
|
where
|
||||||
T: IntoIterator<Item = TableEntry<MacroFile, Option<Parse<SyntaxNode>>>>,
|
T: IntoIterator<Item = TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>>,
|
||||||
{
|
{
|
||||||
let mut res = SyntaxTreeStats::default();
|
let mut res = SyntaxTreeStats::default();
|
||||||
for entry in iter {
|
for entry in iter {
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub enum ExpandError {
|
||||||
|
|
||||||
pub use crate::syntax_bridge::{
|
pub use crate::syntax_bridge::{
|
||||||
ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
|
ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
|
||||||
token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, TokenMap,
|
token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, RevTokenMap, TokenMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This struct contains AST for a single `macro_rules` definition. What might
|
/// This struct contains AST for a single `macro_rules` definition. What might
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue