mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +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 crate::{
|
||||
ast_id_map::AstIdMap, ExpansionInfo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc,
|
||||
MacroDefId, MacroFile, MacroFileKind,
|
||||
ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
|
||||
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
|
||||
#[salsa::query_group(AstDatabaseStorage)]
|
||||
pub trait AstDatabase: SourceDatabase {
|
||||
|
@ -36,14 +24,11 @@ pub trait AstDatabase: SourceDatabase {
|
|||
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
|
||||
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 parse_macro(&self, macro_file: MacroFile) -> Option<Parse<SyntaxNode>>;
|
||||
fn parse_macro_with_info(&self, macro_file: MacroFile) -> Option<ParseMacroWithInfo>;
|
||||
fn macro_expand(
|
||||
fn parse_macro(
|
||||
&self,
|
||||
macro_call: MacroCallId,
|
||||
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String>;
|
||||
|
||||
fn macro_expansion_info(&self, macro_file: MacroFile) -> Option<Arc<ExpansionInfo>>;
|
||||
macro_file: MacroFile,
|
||||
) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)>;
|
||||
fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>;
|
||||
}
|
||||
|
||||
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(
|
||||
db: &dyn AstDatabase,
|
||||
id: MacroCallId,
|
||||
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String> {
|
||||
) -> Result<Arc<tt::Subtree>, String> {
|
||||
let loc = db.lookup_intern_macro(id);
|
||||
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 {
|
||||
return Err(format!("Total tokens count exceed limit : count = {}", count));
|
||||
}
|
||||
|
||||
Ok((
|
||||
Arc::new(tt),
|
||||
MacroExpandInfo { arg_map: macro_arg.1.clone(), def_map: macro_rules.1.clone() },
|
||||
))
|
||||
Ok(Arc::new(tt))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
|
||||
match file_id.0 {
|
||||
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
|
||||
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(
|
||||
db: &dyn AstDatabase,
|
||||
macro_file: MacroFile,
|
||||
) -> Option<Parse<SyntaxNode>> {
|
||||
) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)> {
|
||||
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 tt = db
|
||||
.macro_expand(macro_call_id)
|
||||
|
@ -133,39 +108,12 @@ pub(crate) fn parse_macro_with_info(
|
|||
})
|
||||
.ok()?;
|
||||
|
||||
let (parsed, exp_map) = match macro_file.macro_file_kind {
|
||||
match macro_file.macro_file_kind {
|
||||
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 => {
|
||||
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 std::sync::Arc;
|
||||
|
||||
/// 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
|
||||
|
@ -69,19 +68,29 @@ impl HirFileId {
|
|||
}
|
||||
|
||||
/// Return expansion information if it is a macro-expansion file
|
||||
pub fn parent_expansion(
|
||||
self,
|
||||
db: &dyn db::AstDatabase,
|
||||
) -> Option<((HirFileId, HirFileId), Arc<ExpansionInfo>)> {
|
||||
pub fn parent_expansion(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
|
||||
match self.0 {
|
||||
HirFileIdRepr::FileId(_) => None,
|
||||
HirFileIdRepr::MacroFile(macro_file) => {
|
||||
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
|
||||
|
||||
let def_file = loc.def.ast_id.file_id;
|
||||
let arg_file = loc.ast_id.file_id;
|
||||
let arg_range = loc.ast_id.to_node(db).token_tree()?.syntax().text_range();
|
||||
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)]
|
||||
/// ExpansionInfo mainly describes how to map text range between src and expanded macro
|
||||
pub struct ExpansionInfo {
|
||||
pub arg_map: Vec<(TextRange, TextRange)>,
|
||||
pub def_map: Vec<(TextRange, TextRange)>,
|
||||
pub(crate) arg_file: HirFileId,
|
||||
pub(crate) def_file: HirFileId,
|
||||
|
||||
pub(crate) arg_map: Vec<(TextRange, TextRange)>,
|
||||
pub(crate) def_map: Vec<(TextRange, TextRange)>,
|
||||
}
|
||||
|
||||
impl ExpansionInfo {
|
||||
pub fn find_range(
|
||||
&self,
|
||||
from: TextRange,
|
||||
(arg_file_id, def_file_id): (HirFileId, HirFileId),
|
||||
) -> Option<(HirFileId, TextRange)> {
|
||||
pub fn find_range(&self, from: TextRange) -> Option<(HirFileId, TextRange)> {
|
||||
for (src, dest) in &self.arg_map {
|
||||
if src.is_subrange(&from) {
|
||||
return Some((arg_file_id, *dest));
|
||||
return Some((self.arg_file, *dest));
|
||||
}
|
||||
}
|
||||
|
||||
for (src, dest) in &self.def_map {
|
||||
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 (file_id, text_range) = src
|
||||
.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));
|
||||
|
||||
// FIXME: handle recursive macro generated macro
|
||||
|
@ -139,7 +139,6 @@ impl NavigationTarget {
|
|||
pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
|
||||
let src = module.definition_source(db);
|
||||
let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
|
||||
|
||||
match src.ast {
|
||||
ModuleSource::SourceFile(node) => {
|
||||
let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());
|
||||
|
@ -324,9 +323,7 @@ impl NavigationTarget {
|
|||
) -> NavigationTarget {
|
||||
//FIXME: use `_` instead of empty string
|
||||
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 (file_id, full_range) = find_range_from_node(db, file_id, node.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
|
||||
where
|
||||
T: IntoIterator<Item = TableEntry<MacroFile, Option<Parse<SyntaxNode>>>>,
|
||||
T: IntoIterator<Item = TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>>,
|
||||
{
|
||||
let mut res = SyntaxTreeStats::default();
|
||||
for entry in iter {
|
||||
|
|
|
@ -32,7 +32,7 @@ pub enum ExpandError {
|
|||
|
||||
pub use crate::syntax_bridge::{
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue