mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Try caching macro calls more aggressively
This commit is contained in:
parent
f28f15ac6e
commit
97b58f2846
11 changed files with 382 additions and 300 deletions
|
@ -67,6 +67,10 @@ impl BuiltinFnLikeExpander {
|
|||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
self.expander()(db, id, tt, span)
|
||||
}
|
||||
|
||||
pub fn is_asm(&self) -> bool {
|
||||
matches!(self, Self::Asm | Self::GlobalAsm)
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerExpander {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
//! Things to wrap other things in file ids.
|
||||
use std::iter;
|
||||
|
||||
use either::Either;
|
||||
use span::{
|
||||
AstIdNode, ErasedFileAstId, FileAstId, FileId, FileRange, HirFileId, HirFileIdRepr,
|
||||
|
@ -150,27 +148,16 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
|
||||
// unfortunately `syntax` collides with the impl above, because `&_` is fundamental
|
||||
pub fn syntax_ref(&self) -> InFileWrapper<FileId, &SyntaxNode> {
|
||||
self.with_value(self.value.syntax())
|
||||
}
|
||||
}
|
||||
|
||||
// region:specific impls
|
||||
|
||||
impl InFile<&SyntaxNode> {
|
||||
/// Traverse up macro calls and skips the macro invocation node
|
||||
pub fn ancestors_with_macros(
|
||||
self,
|
||||
db: &dyn db::ExpandDatabase,
|
||||
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
|
||||
let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
|
||||
Some(parent) => Some(node.with_value(parent)),
|
||||
None => db
|
||||
.lookup_intern_macro_call(node.file_id.macro_file()?.macro_call_id)
|
||||
.to_node_item(db)
|
||||
.syntax()
|
||||
.cloned()
|
||||
.map(|node| node.parent())
|
||||
.transpose(),
|
||||
};
|
||||
iter::successors(succ(&self.cloned()), succ)
|
||||
}
|
||||
|
||||
/// Falls back to the macro call range if the node cannot be mapped up fully.
|
||||
///
|
||||
/// For attributes and derives, this will point back to the attribute only.
|
||||
|
|
|
@ -47,7 +47,7 @@ use crate::{
|
|||
builtin_attr_macro::BuiltinAttrExpander,
|
||||
builtin_derive_macro::BuiltinDeriveExpander,
|
||||
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
|
||||
db::{ExpandDatabase, TokenExpander},
|
||||
db::ExpandDatabase,
|
||||
mod_path::ModPath,
|
||||
proc_macro::{CustomProcMacroExpander, ProcMacroKind},
|
||||
span_map::{ExpansionSpanMap, SpanMap},
|
||||
|
@ -253,9 +253,6 @@ pub trait HirFileIdExt {
|
|||
/// If this is a macro call, returns the syntax node of the very first macro call this file resides in.
|
||||
fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>>;
|
||||
|
||||
/// Return expansion information if it is a macro-expansion file
|
||||
fn expansion_info(self, db: &dyn ExpandDatabase) -> Option<ExpansionInfo>;
|
||||
|
||||
fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option<InFile<ast::Attr>>;
|
||||
}
|
||||
|
||||
|
@ -309,11 +306,6 @@ impl HirFileIdExt for HirFileId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return expansion information if it is a macro-expansion file
|
||||
fn expansion_info(self, db: &dyn ExpandDatabase) -> Option<ExpansionInfo> {
|
||||
Some(ExpansionInfo::new(db, self.macro_file()?))
|
||||
}
|
||||
|
||||
fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option<InFile<ast::Attr>> {
|
||||
let macro_file = self.macro_file()?;
|
||||
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
|
||||
|
@ -417,8 +409,10 @@ impl MacroFileIdExt for MacroFileId {
|
|||
}
|
||||
|
||||
fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
|
||||
let loc = db.lookup_intern_macro_call(self.macro_call_id);
|
||||
matches!(loc.kind, MacroCallKind::Attr { .. })
|
||||
matches!(
|
||||
db.lookup_intern_macro_call(self.macro_call_id).def.kind,
|
||||
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _)
|
||||
)
|
||||
}
|
||||
|
||||
fn is_derive_attr_pseudo_expansion(&self, db: &dyn ExpandDatabase) -> bool {
|
||||
|
@ -703,16 +697,12 @@ impl MacroCallKind {
|
|||
// simpler function calls if the map is only used once
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ExpansionInfo {
|
||||
pub expanded: InMacroFile<SyntaxNode>,
|
||||
expanded: InMacroFile<SyntaxNode>,
|
||||
/// The argument TokenTree or item for attributes
|
||||
arg: InFile<Option<SyntaxNode>>,
|
||||
/// The `macro_rules!` or attribute input.
|
||||
attr_input_or_mac_def: Option<InFile<ast::TokenTree>>,
|
||||
|
||||
macro_def: TokenExpander,
|
||||
macro_arg: Arc<tt::Subtree>,
|
||||
pub exp_map: Arc<ExpansionSpanMap>,
|
||||
exp_map: Arc<ExpansionSpanMap>,
|
||||
arg_map: SpanMap,
|
||||
loc: MacroCallLoc,
|
||||
}
|
||||
|
||||
impl ExpansionInfo {
|
||||
|
@ -720,14 +710,21 @@ impl ExpansionInfo {
|
|||
self.expanded.clone()
|
||||
}
|
||||
|
||||
pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
|
||||
Some(self.arg.with_value(self.arg.value.as_ref()?.parent()?))
|
||||
pub fn call_node(&self) -> InFile<Option<SyntaxNode>> {
|
||||
self.arg.with_value(self.arg.value.as_ref().and_then(SyntaxNode::parent))
|
||||
}
|
||||
|
||||
pub fn call_file(&self) -> HirFileId {
|
||||
self.arg.file_id
|
||||
}
|
||||
|
||||
pub fn is_attr(&self) -> bool {
|
||||
matches!(
|
||||
self.loc.def.kind,
|
||||
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _)
|
||||
)
|
||||
}
|
||||
|
||||
/// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
|
||||
///
|
||||
/// Note this does a linear search through the entire backing vector of the spanmap.
|
||||
|
@ -812,49 +809,15 @@ impl ExpansionInfo {
|
|||
}
|
||||
|
||||
pub fn new(db: &dyn ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo {
|
||||
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
|
||||
let loc = db.lookup_intern_macro_call(macro_file.macro_call_id);
|
||||
|
||||
let arg_tt = loc.kind.arg(db);
|
||||
let arg_map = db.span_map(arg_tt.file_id);
|
||||
|
||||
let macro_def = db.macro_expander(loc.def);
|
||||
let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
|
||||
let expanded = InMacroFile { file_id: macro_file, value: parse.syntax_node() };
|
||||
|
||||
let (macro_arg, _, _) =
|
||||
db.macro_arg_considering_derives(macro_file.macro_call_id, &loc.kind);
|
||||
|
||||
let def = loc.def.ast_id().left().and_then(|id| {
|
||||
let def_tt = match id.to_node(db) {
|
||||
ast::Macro::MacroRules(mac) => mac.token_tree()?,
|
||||
ast::Macro::MacroDef(_) if matches!(macro_def, TokenExpander::BuiltInAttr(_)) => {
|
||||
return None
|
||||
}
|
||||
ast::Macro::MacroDef(mac) => mac.body()?,
|
||||
};
|
||||
Some(InFile::new(id.file_id, def_tt))
|
||||
});
|
||||
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
|
||||
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
||||
// FIXME: handle `cfg_attr`
|
||||
let tt = collect_attrs(&ast_id.to_node(db))
|
||||
.nth(invoc_attr_index.ast_index())
|
||||
.and_then(|x| Either::left(x.1))?
|
||||
.token_tree()?;
|
||||
Some(InFile::new(ast_id.file_id, tt))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
ExpansionInfo {
|
||||
expanded,
|
||||
arg: arg_tt,
|
||||
attr_input_or_mac_def,
|
||||
macro_arg,
|
||||
macro_def,
|
||||
exp_map,
|
||||
arg_map,
|
||||
}
|
||||
ExpansionInfo { expanded, loc, arg: arg_tt, exp_map, arg_map }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue