mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Cache parse trees in Semantics
This commit is contained in:
parent
c12f093716
commit
7d40763c88
3 changed files with 22 additions and 4 deletions
|
@ -411,7 +411,7 @@ impl MacroFileIdExt for MacroFileId {
|
||||||
fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
|
fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
db.lookup_intern_macro_call(self.macro_call_id).def.kind,
|
db.lookup_intern_macro_call(self.macro_call_id).def.kind,
|
||||||
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _)
|
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +721,7 @@ impl ExpansionInfo {
|
||||||
pub fn is_attr(&self) -> bool {
|
pub fn is_attr(&self) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self.loc.def.kind,
|
self.loc.def.kind,
|
||||||
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _)
|
MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,6 +809,7 @@ impl ExpansionInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(db: &dyn ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo {
|
pub fn new(db: &dyn ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo {
|
||||||
|
let _p = tracing::span!(tracing::Level::INFO, "ExpansionInfo::new").entered();
|
||||||
let loc = 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_tt = loc.kind.arg(db);
|
||||||
|
|
|
@ -132,6 +132,9 @@ pub struct SemanticsImpl<'db> {
|
||||||
s2d_cache: RefCell<SourceToDefCache>,
|
s2d_cache: RefCell<SourceToDefCache>,
|
||||||
/// Rootnode to HirFileId cache
|
/// Rootnode to HirFileId cache
|
||||||
root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
||||||
|
/// HirFileId to Rootnode cache (this adds a layer over the database LRU cache to prevent
|
||||||
|
/// possibly frequent invalidation)
|
||||||
|
parse_cache: RefCell<FxHashMap<HirFileId, SyntaxNode>>,
|
||||||
/// MacroCall to its expansion's MacroFileId cache
|
/// MacroCall to its expansion's MacroFileId cache
|
||||||
macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>,
|
macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>,
|
||||||
}
|
}
|
||||||
|
@ -292,6 +295,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
db,
|
db,
|
||||||
s2d_cache: Default::default(),
|
s2d_cache: Default::default(),
|
||||||
root_to_file_cache: Default::default(),
|
root_to_file_cache: Default::default(),
|
||||||
|
parse_cache: Default::default(),
|
||||||
macro_call_cache: Default::default(),
|
macro_call_cache: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,6 +307,9 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
|
pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
|
||||||
|
if let Some(root) = self.parse_cache.borrow().get(&file_id) {
|
||||||
|
return root.clone();
|
||||||
|
}
|
||||||
let node = self.db.parse_or_expand(file_id);
|
let node = self.db.parse_or_expand(file_id);
|
||||||
self.cache(node.clone(), file_id);
|
self.cache(node.clone(), file_id);
|
||||||
node
|
node
|
||||||
|
@ -977,6 +984,13 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
let helpers =
|
let helpers =
|
||||||
def_map.derive_helpers_in_scope(InFile::new(file_id, id))?;
|
def_map.derive_helpers_in_scope(InFile::new(file_id, id))?;
|
||||||
|
|
||||||
|
if !helpers.is_empty() {
|
||||||
|
let text_range = attr.syntax().text_range();
|
||||||
|
// remove any other token in this macro input, all their mappings are the
|
||||||
|
// same as this
|
||||||
|
tokens.retain(|t| !text_range.contains_range(t.text_range()));
|
||||||
|
}
|
||||||
|
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
for (.., derive) in
|
for (.., derive) in
|
||||||
helpers.iter().filter(|(helper, ..)| *helper == attr_name)
|
helpers.iter().filter(|(helper, ..)| *helper == attr_name)
|
||||||
|
@ -1407,6 +1421,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
where
|
where
|
||||||
Def::Ast: AstNode,
|
Def::Ast: AstNode,
|
||||||
{
|
{
|
||||||
|
// FIXME: source call should go through the parse cache
|
||||||
let res = def.source(self.db)?;
|
let res = def.source(self.db)?;
|
||||||
self.cache(find_root(res.value.syntax()), res.file_id);
|
self.cache(find_root(res.value.syntax()), res.file_id);
|
||||||
Some(res)
|
Some(res)
|
||||||
|
@ -1464,8 +1479,9 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
||||||
assert!(root_node.parent().is_none());
|
assert!(root_node.parent().is_none());
|
||||||
let mut cache = self.root_to_file_cache.borrow_mut();
|
let mut cache = self.root_to_file_cache.borrow_mut();
|
||||||
let prev = cache.insert(root_node, file_id);
|
let prev = cache.insert(root_node.clone(), file_id);
|
||||||
assert!(prev.is_none() || prev == Some(file_id))
|
assert!(prev.is_none() || prev == Some(file_id));
|
||||||
|
self.parse_cache.borrow_mut().insert(file_id, root_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_contains_node(&self, node: &SyntaxNode) {
|
pub fn assert_contains_node(&self, node: &SyntaxNode) {
|
||||||
|
|
|
@ -405,6 +405,7 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
|
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
|
||||||
|
let _p = tracing::span!(tracing::Level::INFO, "find_container").entered();
|
||||||
let def =
|
let def =
|
||||||
self.ancestors_with_macros(src, |this, container| this.container_to_def(container));
|
self.ancestors_with_macros(src, |this, container| this.container_to_def(container));
|
||||||
if let Some(def) = def {
|
if let Some(def) = def {
|
||||||
|
|
Loading…
Reference in a new issue