diff options
19 files changed, 476 insertions, 361 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index d2f4d7b7e56..a796ef33c60 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -395,6 +395,12 @@ impl BodySourceMap { self.expr_map.get(&src).copied() } + pub fn expansions( + &self, + ) -> impl Iterator<Item = (&InFile<AstPtr<ast::MacroCall>>, &MacroFileId)> { + self.expansions.iter() + } + pub fn implicit_format_args( &self, node: InFile<&ast::FormatArgsExpr>, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index c6d9ba6cfe4..5a5a8d302b5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -12,6 +12,7 @@ use intern::Interned; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::AstIdMap; +use stdx::never; use syntax::{ ast::{ self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName, @@ -480,7 +481,8 @@ impl ExprCollector<'_> { } else if e.const_token().is_some() { Mutability::Shared } else { - unreachable!("parser only remaps to raw_token() if matching mutability token follows") + never!("parser only remaps to raw_token() if matching mutability token follows"); + Mutability::Shared } } else { Mutability::from_mutable(e.mut_token().is_some()) @@ -1006,9 +1008,9 @@ impl ExprCollector<'_> { Some((mark, expansion)) => { // Keep collecting even with expansion errors so we can provide completions and // other services in incomplete macro expressions. - self.source_map - .expansions - .insert(macro_call_ptr, self.expander.current_file_id().macro_file().unwrap()); + if let Some(macro_file) = self.expander.current_file_id().macro_file() { + self.source_map.expansions.insert(macro_call_ptr, macro_file); + } let prev_ast_id_map = mem::replace( &mut self.ast_id_map, self.db.ast_id_map(self.expander.current_file_id()), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs index 0b41984bdd8..106109eb184 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs @@ -6,7 +6,7 @@ use either::Either; use hir_expand::{attrs::collect_attrs, HirFileId}; -use syntax::ast; +use syntax::{ast, AstPtr}; use crate::{ db::DefDatabase, @@ -38,7 +38,7 @@ impl ChildBySource for TraitId { data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id); + res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id); }, ); data.items.iter().for_each(|&(_, item)| { @@ -50,9 +50,10 @@ impl ChildBySource for TraitId { impl ChildBySource for ImplId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { let data = db.impl_data(*self); + // FIXME: Macro calls data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id); + res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id); }, ); data.items.iter().for_each(|&item| { @@ -80,7 +81,7 @@ impl ChildBySource for ItemScope { .for_each(|konst| insert_item_loc(db, res, file_id, konst, keys::CONST)); self.attr_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each( |(ast_id, call_id)| { - res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id); + res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id); }, ); self.legacy_macros().for_each(|(_, ids)| { @@ -88,7 +89,7 @@ impl ChildBySource for ItemScope { if let MacroId::MacroRulesId(id) = id { let loc = id.lookup(db); if loc.id.file_id() == file_id { - res[keys::MACRO_RULES].insert(loc.source(db).value, id); + res[keys::MACRO_RULES].insert(loc.ast_ptr(db).value, id); } } }) @@ -100,12 +101,18 @@ impl ChildBySource for ItemScope { if let Some((_, Either::Left(attr))) = collect_attrs(&adt).nth(attr_id.ast_index()) { - res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into())); + res[keys::DERIVE_MACRO_CALL] + .insert(AstPtr::new(&attr), (attr_id, call_id, calls.into())); } }); }, ); - + self.iter_macro_invoc().filter(|(id, _)| id.file_id == file_id).for_each( + |(ast_id, &call)| { + let ast = ast_id.to_ptr(db.upcast()); + res[keys::MACRO_CALL].insert(ast, call); + }, + ); fn add_module_def( db: &dyn DefDatabase, map: &mut DynMap, @@ -155,8 +162,8 @@ impl ChildBySource for VariantId { for (local_id, source) in arena_map.value.iter() { let id = FieldId { parent, local_id }; match source.clone() { - Either::Left(source) => res[keys::TUPLE_FIELD].insert(source, id), - Either::Right(source) => res[keys::RECORD_FIELD].insert(source, id), + Either::Left(source) => res[keys::TUPLE_FIELD].insert(AstPtr::new(&source), id), + Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id), } } } @@ -171,29 +178,30 @@ impl ChildBySource for EnumId { let tree = loc.id.item_tree(db); let ast_id_map = db.ast_id_map(loc.id.file_id()); - let root = db.parse_or_expand(loc.id.file_id()); db.enum_data(*self).variants.iter().for_each(|&(variant, _)| { - res[keys::ENUM_VARIANT].insert( - ast_id_map.get(tree[variant.lookup(db).id.value].ast_id).to_node(&root), - variant, - ); + res[keys::ENUM_VARIANT] + .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); }); } } impl ChildBySource for DefWithBodyId { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { - let body = db.body(*self); + let (body, sm) = db.body_with_source_map(*self); if let &DefWithBodyId::VariantId(v) = self { VariantId::EnumVariantId(v).child_by_source_to(db, res, file_id) } + sm.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(|(ast, &exp_id)| { + res[keys::MACRO_CALL].insert(ast.value, exp_id.macro_call_id); + }); + for (block, def_map) in body.blocks(db) { // All block expressions are merged into the same map, because they logically all add // inner items to the containing `DefWithBodyId`. def_map[DefMap::ROOT].scope.child_by_source_to(db, res, file_id); - res[keys::BLOCK].insert(block.lookup(db).ast_id.to_node(db.upcast()), block); + res[keys::BLOCK].insert(block.lookup(db).ast_id.to_ptr(db.upcast()), block); } } } @@ -220,13 +228,17 @@ impl ChildBySource for GenericDefId { { let id = TypeOrConstParamId { parent: *self, local_id }; match ast_param { - ast::TypeOrConstParam::Type(a) => res[keys::TYPE_PARAM].insert(a, id), - ast::TypeOrConstParam::Const(a) => res[keys::CONST_PARAM].insert(a, id), + ast::TypeOrConstParam::Type(a) => { + res[keys::TYPE_PARAM].insert(AstPtr::new(&a), id) + } + ast::TypeOrConstParam::Const(a) => { + res[keys::CONST_PARAM].insert(AstPtr::new(&a), id) + } } } for (local_id, ast_param) in lts_idx_iter.zip(generic_params_list.lifetime_params()) { let id = LifetimeParamId { parent: *self, local_id }; - res[keys::LIFETIME_PARAM].insert(ast_param, id); + res[keys::LIFETIME_PARAM].insert(AstPtr::new(&ast_param), id); } } } @@ -246,7 +258,7 @@ fn insert_item_loc<ID, N, Data>( { let loc = id.lookup(db); if loc.item_tree_id().file_id() == file_id { - res[key].insert(loc.source(db).value, id) + res[key].insert(loc.ast_ptr(db).value, id) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs index f83ab1e1a05..9d330a7bf1c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs @@ -13,7 +13,7 @@ use crate::{ TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, }; -pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>; +pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>; pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new(); pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new(); @@ -39,6 +39,7 @@ pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new(); pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new(); pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new(); pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new(); +pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new(); pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new(); pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> = Key::new(); @@ -54,18 +55,16 @@ pub struct AstPtrPolicy<AST, ID> { } impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> { - type K = AST; + type K = AstPtr<AST>; type V = ID; - fn insert(map: &mut DynMap, key: AST, value: ID) { - let key = AstPtr::new(&key); + fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) { map.map .entry::<FxHashMap<AstPtr<AST>, ID>>() .or_insert_with(Default::default) .insert(key, value); } - fn get<'a>(map: &'a DynMap, key: &AST) -> Option<&'a ID> { - let key = AstPtr::new(key); - map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(&key) + fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> { + map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key) } fn is_empty(map: &DynMap) -> bool { map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty()) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index ba96ab6cc2f..02fd431e4e7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -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 { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 1ba85c5c7ea..743fac50f4e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -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. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index b34649d972f..a586b543c84 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -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,16 @@ 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 _p = tracing::span!(tracing::Level::INFO, "ExpansionInfo::new").entered(); + 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 } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 79321df6b6a..64d08c7364e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2755,6 +2755,12 @@ impl Macro { } } + pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool { + matches!(self.id, MacroId::Macro2Id(it) if { + matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm()) + }) + } + pub fn is_attr(&self, db: &dyn HirDatabase) -> bool { matches!(self.kind(db), MacroKind::Attr) } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 0cde3f000a5..c8f61a34cb5 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -19,8 +19,8 @@ use hir_def::{ AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId, }; use hir_expand::{ - attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, ExpansionInfo, - InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, + attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, InMacroFile, + MacroCallId, MacroFileId, MacroFileIdExt, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -132,9 +132,9 @@ pub struct SemanticsImpl<'db> { s2d_cache: RefCell<SourceToDefCache>, /// Rootnode to HirFileId cache root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, - // These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens - // So we might wanna move them out into something specific for semantic highlighting - expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>, + /// 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 macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>, } @@ -295,7 +295,7 @@ impl<'db> SemanticsImpl<'db> { db, s2d_cache: Default::default(), root_to_file_cache: Default::default(), - expansion_info_cache: Default::default(), + parse_cache: Default::default(), macro_call_cache: Default::default(), } } @@ -307,6 +307,9 @@ impl<'db> SemanticsImpl<'db> { } 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); self.cache(node.clone(), file_id); node @@ -314,7 +317,16 @@ impl<'db> SemanticsImpl<'db> { pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { let sa = self.analyze_no_infer(macro_call.syntax())?; - let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?; + + let macro_call = InFile::new(sa.file_id, macro_call); + let file_id = if let Some(call) = + <ast::MacroCall as crate::semantics::ToDef>::to_def(self, macro_call) + { + call.as_macro_file() + } else { + sa.expand(self.db, macro_call)? + }; + let node = self.parse_or_expand(file_id.into()); Some(node) } @@ -322,7 +334,7 @@ impl<'db> SemanticsImpl<'db> { /// If `item` has an attribute macro attached to it, expands it. pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { let src = self.wrap_node_infile(item.clone()); - let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?; + let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src.as_ref()))?; Some(self.parse_or_expand(macro_call_id.as_file())) } @@ -341,9 +353,7 @@ impl<'db> SemanticsImpl<'db> { Some( calls .into_iter() - .map(|call| { - macro_call_to_macro_id(ctx, self.db.upcast(), call?).map(|id| Macro { id }) - }) + .map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id })) .collect(), ) }) @@ -403,7 +413,7 @@ impl<'db> SemanticsImpl<'db> { pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool { let file_id = self.find_file(item.syntax()).file_id; - let src = InFile::new(file_id, item.clone()); + let src = InFile::new(file_id, item); self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some()) } @@ -453,7 +463,7 @@ impl<'db> SemanticsImpl<'db> { token_to_map: SyntaxToken, ) -> Option<(SyntaxNode, SyntaxToken)> { let macro_call = self.wrap_node_infile(actual_macro_call.clone()); - let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(macro_call))?; + let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(macro_call.as_ref()))?; hir_expand::db::expand_speculative( self.db.upcast(), macro_call_id, @@ -705,8 +715,6 @@ impl<'db> SemanticsImpl<'db> { let parent = token.parent()?; let file_id = self.find_file(&parent).file_id.file_id()?; - let mut cache = self.expansion_info_cache.borrow_mut(); - // iterate related crates and find all include! invocations that include_file_id matches for (invoc, _) in self .db @@ -716,18 +724,32 @@ impl<'db> SemanticsImpl<'db> { .filter(|&(_, include_file_id)| include_file_id == file_id) { let macro_file = invoc.as_macro_file(); - let expansion_info = cache.entry(macro_file).or_insert_with(|| { - let exp_info = macro_file.expansion_info(self.db.upcast()); - - let InMacroFile { file_id, value } = exp_info.expanded(); - self.cache(value, file_id.into()); + let expansion_info = { + self.with_ctx(|ctx| { + ctx.cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| { + let exp_info = macro_file.expansion_info(self.db.upcast()); + + let InMacroFile { file_id, value } = exp_info.expanded(); + if let InFile { file_id, value: Some(value) } = exp_info.call_node() { + self.cache(value.ancestors().last().unwrap(), file_id); + } + self.cache(value, file_id.into()); - exp_info - }); + exp_info + }) + .clone() + }) + }; // FIXME: uncached parse // Create the source analyzer for the macro call scope - let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file())) + let Some(sa) = expansion_info + .call_node() + .value + .and_then(|it| self.analyze_no_infer(&it.ancestors().last().unwrap())) else { continue; }; @@ -785,23 +807,28 @@ impl<'db> SemanticsImpl<'db> { } }; - let mut cache = self.expansion_info_cache.borrow_mut(); - let mut mcache = self.macro_call_cache.borrow_mut(); + let mut m_cache = self.macro_call_cache.borrow_mut(); let def_map = sa.resolver.def_map(); let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(file_id, smallvec![token])]; - let mut process_expansion_for_token = |stack: &mut Vec<_>, macro_file| { - let exp_info = cache.entry(macro_file).or_insert_with(|| { - let exp_info = macro_file.expansion_info(self.db.upcast()); - - let InMacroFile { file_id, value } = exp_info.expanded(); - self.cache(value, file_id.into()); - - exp_info - }); - - let InMacroFile { file_id, value: mapped_tokens } = exp_info.map_range_down(span)?; - let mapped_tokens: SmallVec<[_; 2]> = mapped_tokens.collect(); + let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| { + let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| { + Some( + ctx.cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| { + let exp_info = macro_file.expansion_info(self.db.upcast()); + + let InMacroFile { file_id, value } = exp_info.expanded(); + self.cache(value, file_id.into()); + + exp_info + }) + .map_range_down(span)? + .map(SmallVec::<[_; 2]>::from_iter), + ) + })?; // we have found a mapping for the token if the vec is non-empty let res = mapped_tokens.is_empty().not().then_some(()); @@ -818,10 +845,7 @@ impl<'db> SemanticsImpl<'db> { token.parent_ancestors().filter_map(ast::Item::cast).find_map(|item| { // Don't force populate the dyn cache for items that don't have an attribute anyways item.attrs().next()?; - Some(( - ctx.item_to_macro_call(InFile::new(file_id, item.clone()))?, - item, - )) + Some((ctx.item_to_macro_call(InFile::new(file_id, &item))?, item)) }) }); if let Some((call_id, item)) = containing_attribute_macro_call { @@ -874,13 +898,20 @@ impl<'db> SemanticsImpl<'db> { return None; } let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?; - let mcall: hir_expand::files::InFileWrapper<HirFileId, ast::MacroCall> = - InFile::new(file_id, macro_call); - let file_id = match mcache.get(&mcall) { + let mcall = InFile::new(file_id, macro_call); + let file_id = match m_cache.get(&mcall) { Some(&it) => it, None => { - let it = sa.expand(self.db, mcall.as_ref())?; - mcache.insert(mcall, it); + let it = if let Some(call) = + <ast::MacroCall as crate::semantics::ToDef>::to_def( + self, + mcall.as_ref(), + ) { + call.as_macro_file() + } else { + sa.expand(self.db, mcall.as_ref())? + }; + m_cache.insert(mcall, it); it } }; @@ -953,6 +984,13 @@ impl<'db> SemanticsImpl<'db> { let helpers = 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; for (.., derive) in helpers.iter().filter(|(helper, ..)| *helper == attr_name) @@ -1056,16 +1094,20 @@ impl<'db> SemanticsImpl<'db> { node: SyntaxNode, ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ { let node = self.find_file(&node); - let db = self.db.upcast(); iter::successors(Some(node.cloned()), move |&InFile { file_id, ref value }| { match value.parent() { Some(parent) => Some(InFile::new(file_id, parent)), None => { - let call_node = file_id.macro_file()?.call_node(db); - // cache the node - // FIXME: uncached parse - self.parse_or_expand(call_node.file_id); - Some(call_node) + let macro_file = file_id.macro_file()?; + + self.with_ctx(|ctx| { + let expansion_info = ctx + .cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(self.db.upcast())); + expansion_info.call_node().transpose() + }) } } }) @@ -1090,7 +1132,7 @@ impl<'db> SemanticsImpl<'db> { .find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()).as_ref() == Some(&text)) })?; let src = self.wrap_node_infile(lifetime_param); - ToDef::to_def(self, src) + ToDef::to_def(self, src.as_ref()) } pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> { @@ -1112,7 +1154,7 @@ impl<'db> SemanticsImpl<'db> { }) })?; let src = self.wrap_node_infile(label); - ToDef::to_def(self, src) + ToDef::to_def(self, src.as_ref()) } pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> { @@ -1275,9 +1317,15 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> { - let sa = self.analyze(macro_call.syntax())?; let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); - sa.resolve_macro_call(self.db, macro_call) + self.with_ctx(|ctx| { + ctx.macro_call_to_macro_call(macro_call) + .and_then(|call| macro_call_to_macro_id(ctx, call)) + .map(Into::into) + }) + .or_else(|| { + self.analyze(macro_call.value.syntax())?.resolve_macro_call(self.db, macro_call) + }) } pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool { @@ -1297,19 +1345,24 @@ impl<'db> SemanticsImpl<'db> { } pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { - let sa = match self.analyze(macro_call.syntax()) { - Some(it) => it, - None => return false, - }; + let Some(mac) = self.resolve_macro_call(macro_call) else { return false }; + if mac.is_asm_or_global_asm(self.db) { + return true; + } + + let Some(sa) = self.analyze(macro_call.syntax()) else { return false }; let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); - sa.is_unsafe_macro_call(self.db, macro_call) + match macro_call.map(|it| it.syntax().parent().and_then(ast::MacroExpr::cast)).transpose() { + Some(it) => sa.is_unsafe_macro_call_expr(self.db, it.as_ref()), + None => false, + } } pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<Macro> { let item_in_file = self.wrap_node_infile(item.clone()); let id = self.with_ctx(|ctx| { - let macro_call_id = ctx.item_to_macro_call(item_in_file)?; - macro_call_to_macro_id(ctx, self.db.upcast(), macro_call_id) + let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?; + macro_call_to_macro_id(ctx, macro_call_id) })?; Some(Macro { id }) } @@ -1339,18 +1392,17 @@ impl<'db> SemanticsImpl<'db> { } fn with_ctx<F: FnOnce(&mut SourceToDefCtx<'_, '_>) -> T, T>(&self, f: F) -> T { - let mut cache = self.s2d_cache.borrow_mut(); - let mut ctx = SourceToDefCtx { db: self.db, dynmap_cache: &mut cache }; + let mut ctx = SourceToDefCtx { db: self.db, cache: &mut self.s2d_cache.borrow_mut() }; f(&mut ctx) } pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { - let src = self.find_file(src.syntax()).with_value(src).cloned(); + let src = self.find_file(src.syntax()).with_value(src); T::to_def(self, src) } fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> { - self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from) + self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from) } pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> { @@ -1380,6 +1432,7 @@ impl<'db> SemanticsImpl<'db> { where Def::Ast: AstNode, { + // FIXME: source call should go through the parse cache let res = def.source(self.db)?; self.cache(find_root(res.value.syntax()), res.file_id); Some(res) @@ -1437,8 +1490,9 @@ impl<'db> SemanticsImpl<'db> { fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { assert!(root_node.parent().is_none()); let mut cache = self.root_to_file_cache.borrow_mut(); - let prev = cache.insert(root_node, file_id); - assert!(prev.is_none() || prev == Some(file_id)) + let prev = cache.insert(root_node.clone(), 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) { @@ -1613,27 +1667,59 @@ impl<'db> SemanticsImpl<'db> { fn macro_call_to_macro_id( ctx: &mut SourceToDefCtx<'_, '_>, - db: &dyn ExpandDatabase, macro_call_id: MacroCallId, ) -> Option<MacroId> { + use span::HirFileIdRepr; + + let db: &dyn ExpandDatabase = ctx.db.upcast(); let loc = db.lookup_intern_macro_call(macro_call_id); + match loc.def.ast_id() { - Either::Left(it) => ctx.macro_to_def(InFile::new(it.file_id, it.to_node(db))), - Either::Right(it) => ctx.proc_macro_to_def(InFile::new(it.file_id, it.to_node(db))), + Either::Left(it) => { + let node = match it.file_id.repr() { + HirFileIdRepr::FileId(file_id) => { + it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) + } + HirFileIdRepr::MacroFile(macro_file) => { + let expansion_info = ctx + .cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(ctx.db.upcast())); + it.to_ptr(db).to_node(&expansion_info.expanded().value) + } + }; + ctx.macro_to_def(InFile::new(it.file_id, &node)) + } + Either::Right(it) => { + let node = match it.file_id.repr() { + HirFileIdRepr::FileId(file_id) => { + it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) + } + HirFileIdRepr::MacroFile(macro_file) => { + let expansion_info = ctx + .cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(ctx.db.upcast())); + it.to_ptr(db).to_node(&expansion_info.expanded().value) + } + }; + ctx.proc_macro_to_def(InFile::new(it.file_id, &node)) + } } } pub trait ToDef: AstNode + Clone { type Def; - - fn to_def(sema: &SemanticsImpl<'_>, src: InFile<Self>) -> Option<Self::Def>; + fn to_def(sema: &SemanticsImpl<'_>, src: InFile<&Self>) -> Option<Self::Def>; } macro_rules! to_def_impls { ($(($def:path, $ast:path, $meth:ident)),* ,) => {$( impl ToDef for $ast { type Def = $def; - fn to_def(sema: &SemanticsImpl<'_>, src: InFile<Self>) -> Option<Self::Def> { + fn to_def(sema: &SemanticsImpl<'_>, src: InFile<&Self>) -> Option<Self::Def> { sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from) } } @@ -1666,6 +1752,7 @@ to_def_impls![ (crate::Label, ast::Label, label_to_def), (crate::Adt, ast::Adt, adt_to_def), (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def), + (MacroCallId, ast::MacroCall, macro_call_to_macro_call), ]; fn find_root(node: &SyntaxNode) -> SyntaxNode { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 77e7cdb58ab..85e7c31ddf9 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -98,56 +98,68 @@ use hir_def::{ FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId, }; -use hir_expand::{attrs::AttrId, name::AsName, HirFileId, HirFileIdExt, MacroCallId}; +use hir_expand::{ + attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, MacroCallId, +}; use rustc_hash::FxHashMap; use smallvec::SmallVec; +use span::MacroFileId; use stdx::impl_from; use syntax::{ ast::{self, HasName}, - AstNode, SyntaxNode, + AstNode, AstPtr, SyntaxNode, }; use crate::{db::HirDatabase, InFile}; -pub(super) type SourceToDefCache = FxHashMap<(ChildContainer, HirFileId), DynMap>; +#[derive(Default)] +pub(super) struct SourceToDefCache { + pub(super) dynmap_cache: FxHashMap<(ChildContainer, HirFileId), DynMap>, + pub(super) expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>, + pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>, +} -pub(super) struct SourceToDefCtx<'a, 'b> { - pub(super) db: &'b dyn HirDatabase, - pub(super) dynmap_cache: &'a mut SourceToDefCache, +pub(super) struct SourceToDefCtx<'db, 'cache> { + pub(super) db: &'db dyn HirDatabase, + pub(super) cache: &'cache mut SourceToDefCache, } impl SourceToDefCtx<'_, '_> { - pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { + pub(super) fn file_to_def(&mut self, file: FileId) -> &SmallVec<[ModuleId; 1]> { let _p = tracing::span!(tracing::Level::INFO, "SourceToDefCtx::file_to_def").entered(); - let mut mods = SmallVec::new(); - for &crate_id in self.db.relevant_crates(file).iter() { - // Note: `mod` declarations in block modules cannot be supported here - let crate_def_map = self.db.crate_def_map(crate_id); - mods.extend( - crate_def_map - .modules_for_file(file) - .map(|local_id| crate_def_map.module_id(local_id)), - ) - } - if mods.is_empty() { - // FIXME: detached file - } - mods + self.cache.file_to_def_cache.entry(file).or_insert_with(|| { + let mut mods = SmallVec::new(); + for &crate_id in self.db.relevant_crates(file).iter() { + // Note: `mod` declarations in block modules cannot be supported here + let crate_def_map = self.db.crate_def_map(crate_id); + mods.extend( + crate_def_map + .modules_for_file(file) + .map(|local_id| crate_def_map.module_id(local_id)), + ) + } + if mods.is_empty() { + // FIXME: detached file + } + mods + }) } - pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { + pub(super) fn module_to_def(&mut self, src: InFile<&ast::Module>) -> Option<ModuleId> { let _p = tracing::span!(tracing::Level::INFO, "module_to_def").entered(); - let parent_declaration = src - .syntax() - .ancestors_with_macros(self.db.upcast()) - .find_map(|it| it.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose()) + let parent_declaration = self + .ancestors_with_macros(src.syntax_ref(), |_, ancestor| { + ancestor.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose() + }) .map(|it| it.transpose()); let parent_module = match parent_declaration { Some(Either::Right(parent_block)) => self - .block_to_def(parent_block) + .block_to_def(parent_block.as_ref()) .map(|block| self.db.block_def_map(block).root_module_id()), - Some(Either::Left(parent_declaration)) => self.module_to_def(parent_declaration), + Some(Either::Left(parent_declaration)) => { + self.module_to_def(parent_declaration.as_ref()) + } None => { let file_id = src.file_id.original_file(self.db.upcast()); self.file_to_def(file_id).first().copied() @@ -160,73 +172,79 @@ impl SourceToDefCtx<'_, '_> { Some(def_map.module_id(child_id)) } - pub(super) fn source_file_to_def(&self, src: InFile<ast::SourceFile>) -> Option<ModuleId> { + pub(super) fn source_file_to_def(&mut self, src: InFile<&ast::SourceFile>) -> Option<ModuleId> { let _p = tracing::span!(tracing::Level::INFO, "source_file_to_def").entered(); let file_id = src.file_id.original_file(self.db.upcast()); self.file_to_def(file_id).first().copied() } - pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> { + pub(super) fn trait_to_def(&mut self, src: InFile<&ast::Trait>) -> Option<TraitId> { self.to_def(src, keys::TRAIT) } pub(super) fn trait_alias_to_def( &mut self, - src: InFile<ast::TraitAlias>, + src: InFile<&ast::TraitAlias>, ) -> Option<TraitAliasId> { self.to_def(src, keys::TRAIT_ALIAS) } - pub(super) fn impl_to_def(&mut self, src: InFile<ast::Impl>) -> Option<ImplId> { + pub(super) fn impl_to_def(&mut self, src: InFile<&ast::Impl>) -> Option<ImplId> { self.to_def(src, keys::IMPL) } - pub(super) fn fn_to_def(&mut self, src: InFile<ast::Fn>) -> Option<FunctionId> { + pub(super) fn fn_to_def(&mut self, src: InFile<&ast::Fn>) -> Option<FunctionId> { self.to_def(src, keys::FUNCTION) } - pub(super) fn struct_to_def(&mut self, src: InFile<ast::Struct>) -> Option<StructId> { + pub(super) fn struct_to_def(&mut self, src: InFile<&ast::Struct>) -> Option<StructId> { self.to_def(src, keys::STRUCT) } - pub(super) fn enum_to_def(&mut self, src: InFile<ast::Enum>) -> Option<EnumId> { + pub(super) fn enum_to_def(&mut self, src: InFile<&ast::Enum>) -> Option<EnumId> { self.to_def(src, keys::ENUM) } - pub(super) fn union_to_def(&mut self, src: InFile<ast::Union>) -> Option<UnionId> { + pub(super) fn union_to_def(&mut self, src: InFile<&ast::Union>) -> Option<UnionId> { self.to_def(src, keys::UNION) } - pub(super) fn static_to_def(&mut self, src: InFile<ast::Static>) -> Option<StaticId> { + pub(super) fn static_to_def(&mut self, src: InFile<&ast::Static>) -> Option<StaticId> { self.to_def(src, keys::STATIC) } - pub(super) fn const_to_def(&mut self, src: InFile<ast::Const>) -> Option<ConstId> { + pub(super) fn const_to_def(&mut self, src: InFile<&ast::Const>) -> Option<ConstId> { self.to_def(src, keys::CONST) } - pub(super) fn type_alias_to_def(&mut self, src: InFile<ast::TypeAlias>) -> Option<TypeAliasId> { + pub(super) fn type_alias_to_def( + &mut self, + src: InFile<&ast::TypeAlias>, + ) -> Option<TypeAliasId> { self.to_def(src, keys::TYPE_ALIAS) } - pub(super) fn record_field_to_def(&mut self, src: InFile<ast::RecordField>) -> Option<FieldId> { + pub(super) fn record_field_to_def( + &mut self, + src: InFile<&ast::RecordField>, + ) -> Option<FieldId> { self.to_def(src, keys::RECORD_FIELD) } - pub(super) fn tuple_field_to_def(&mut self, src: InFile<ast::TupleField>) -> Option<FieldId> { + pub(super) fn tuple_field_to_def(&mut self, src: InFile<&ast::TupleField>) -> Option<FieldId> { self.to_def(src, keys::TUPLE_FIELD) } - pub(super) fn block_to_def(&mut self, src: InFile<ast::BlockExpr>) -> Option<BlockId> { + pub(super) fn block_to_def(&mut self, src: InFile<&ast::BlockExpr>) -> Option<BlockId> { self.to_def(src, keys::BLOCK) } pub(super) fn enum_variant_to_def( &mut self, - src: InFile<ast::Variant>, + src: InFile<&ast::Variant>, ) -> Option<EnumVariantId> { self.to_def(src, keys::ENUM_VARIANT) } pub(super) fn extern_crate_to_def( &mut self, - src: InFile<ast::ExternCrate>, + src: InFile<&ast::ExternCrate>, ) -> Option<ExternCrateId> { self.to_def(src, keys::EXTERN_CRATE) } #[allow(dead_code)] - pub(super) fn use_to_def(&mut self, src: InFile<ast::Use>) -> Option<UseId> { + pub(super) fn use_to_def(&mut self, src: InFile<&ast::Use>) -> Option<UseId> { self.to_def(src, keys::USE) } pub(super) fn adt_to_def( &mut self, - InFile { file_id, value }: InFile<ast::Adt>, + InFile { file_id, value }: InFile<&ast::Adt>, ) -> Option<AdtId> { match value { ast::Adt::Enum(it) => self.enum_to_def(InFile::new(file_id, it)).map(AdtId::EnumId), @@ -238,11 +256,11 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn bind_pat_to_def( &mut self, - src: InFile<ast::IdentPat>, + src: InFile<&ast::IdentPat>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = self.find_pat_or_label_container(src.syntax())?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; let (body, source_map) = self.db.body_with_source_map(container); - let src = src.map(ast::Pat::from); + let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; // the pattern could resolve to a constant, verify that that is not the case if let crate::Pat::Bind { id, .. } = body[pat_id] { @@ -253,25 +271,33 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn self_param_to_def( &mut self, - src: InFile<ast::SelfParam>, + src: InFile<&ast::SelfParam>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = self.find_pat_or_label_container(src.syntax())?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; let body = self.db.body(container); Some((container, body.self_param?)) } pub(super) fn label_to_def( &mut self, - src: InFile<ast::Label>, + src: InFile<&ast::Label>, ) -> Option<(DefWithBodyId, LabelId)> { - let container = self.find_pat_or_label_container(src.syntax())?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; let (_body, source_map) = self.db.body_with_source_map(container); - let label_id = source_map.node_label(src.as_ref())?; + let label_id = source_map.node_label(src)?; Some((container, label_id)) } - pub(super) fn item_to_macro_call(&mut self, src: InFile<ast::Item>) -> Option<MacroCallId> { - let map = self.dyn_map(src.as_ref())?; - map[keys::ATTR_MACRO_CALL].get(&src.value).copied() + pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> { + let map = self.dyn_map(src)?; + map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied() + } + + pub(super) fn macro_call_to_macro_call( + &mut self, + src: InFile<&ast::MacroCall>, + ) -> Option<MacroCallId> { + let map = self.dyn_map(src)?; + map[keys::MACRO_CALL].get(&AstPtr::new(src.value)).copied() } /// (AttrId, derive attribute call id, derive call ids) @@ -282,7 +308,7 @@ impl SourceToDefCtx<'_, '_> { ) -> Option<(AttrId, MacroCallId, &[Option<MacroCallId>])> { let map = self.dyn_map(item)?; map[keys::DERIVE_MACRO_CALL] - .get(&src.value) + .get(&AstPtr::new(&src.value)) .map(|&(attr_id, call_id, ref ids)| (attr_id, call_id, &**ids)) } @@ -292,10 +318,10 @@ impl SourceToDefCtx<'_, '_> { fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>( &mut self, - src: InFile<Ast>, + src: InFile<&Ast>, key: Key<Ast, ID>, ) -> Option<ID> { - self.dyn_map(src.as_ref())?[key].get(&src.value).copied() + self.dyn_map(src)?[key].get(&AstPtr::new(src.value)).copied() } fn dyn_map<Ast: AstNode + 'static>(&mut self, src: InFile<&Ast>) -> Option<&DynMap> { @@ -305,38 +331,48 @@ impl SourceToDefCtx<'_, '_> { fn cache_for(&mut self, container: ChildContainer, file_id: HirFileId) -> &DynMap { let db = self.db; - self.dynmap_cache + self.cache + .dynmap_cache .entry((container, file_id)) .or_insert_with(|| container.child_by_source(db, file_id)) } - pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { - let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); + pub(super) fn type_param_to_def( + &mut self, + src: InFile<&ast::TypeParam>, + ) -> Option<TypeParamId> { + let container: ChildContainer = self.find_generic_param_container(src.syntax_ref())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(TypeParamId::from_unchecked) + dyn_map[keys::TYPE_PARAM] + .get(&AstPtr::new(src.value)) + .copied() + .map(TypeParamId::from_unchecked) } pub(super) fn lifetime_param_to_def( &mut self, - src: InFile<ast::LifetimeParam>, + src: InFile<&ast::LifetimeParam>, ) -> Option<LifetimeParamId> { - let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); + let container: ChildContainer = self.find_generic_param_container(src.syntax_ref())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::LIFETIME_PARAM].get(&src.value).copied() + dyn_map[keys::LIFETIME_PARAM].get(&AstPtr::new(src.value)).copied() } pub(super) fn const_param_to_def( &mut self, - src: InFile<ast::ConstParam>, + src: InFile<&ast::ConstParam>, ) -> Option<ConstParamId> { - let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into(); + let container: ChildContainer = self.find_generic_param_container(src.syntax_ref())?.into(); let dyn_map = self.cache_for(container, src.file_id); - dyn_map[keys::CONST_PARAM].get(&src.value).copied().map(ConstParamId::from_unchecked) + dyn_map[keys::CONST_PARAM] + .get(&AstPtr::new(src.value)) + .copied() + .map(ConstParamId::from_unchecked) } pub(super) fn generic_param_to_def( &mut self, - InFile { file_id, value }: InFile<ast::GenericParam>, + InFile { file_id, value }: InFile<&ast::GenericParam>, ) -> Option<GenericParamId> { match value { ast::GenericParam::ConstParam(it) => { @@ -351,34 +387,113 @@ impl SourceToDefCtx<'_, '_> { } } - pub(super) fn macro_to_def(&mut self, src: InFile<ast::Macro>) -> Option<MacroId> { - self.dyn_map(src.as_ref()).and_then(|it| match &src.value { + pub(super) fn macro_to_def(&mut self, src: InFile<&ast::Macro>) -> Option<MacroId> { + self.dyn_map(src).and_then(|it| match src.value { ast::Macro::MacroRules(value) => { - it[keys::MACRO_RULES].get(value).copied().map(MacroId::from) + it[keys::MACRO_RULES].get(&AstPtr::new(value)).copied().map(MacroId::from) + } + ast::Macro::MacroDef(value) => { + it[keys::MACRO2].get(&AstPtr::new(value)).copied().map(MacroId::from) } - ast::Macro::MacroDef(value) => it[keys::MACRO2].get(value).copied().map(MacroId::from), }) } - pub(super) fn proc_macro_to_def(&mut self, src: InFile<ast::Fn>) -> Option<MacroId> { - self.dyn_map(src.as_ref()) - .and_then(|it| it[keys::PROC_MACRO].get(&src.value).copied().map(MacroId::from)) + pub(super) fn proc_macro_to_def(&mut self, src: InFile<&ast::Fn>) -> Option<MacroId> { + self.dyn_map(src).and_then(|it| { + it[keys::PROC_MACRO].get(&AstPtr::new(src.value)).copied().map(MacroId::from) + }) } pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { - for container in src.ancestors_with_macros(self.db.upcast()) { - if let Some(res) = self.container_to_def(container) { - return Some(res); - } + let _p = tracing::span!(tracing::Level::INFO, "find_container").entered(); + let def = + self.ancestors_with_macros(src, |this, container| this.container_to_def(container)); + if let Some(def) = def { + return Some(def); } let def = self.file_to_def(src.file_id.original_file(self.db.upcast())).first().copied()?; Some(def.into()) } + /// Skips the attributed item that caused the macro invocation we are climbing up + fn ancestors_with_macros<T>( + &mut self, + node: InFile<&SyntaxNode>, + mut cb: impl FnMut(&mut Self, InFile<SyntaxNode>) -> Option<T>, + ) -> Option<T> { + use hir_expand::MacroFileIdExt; + let parent = |this: &mut Self, node: InFile<&SyntaxNode>| match node.value.parent() { + Some(parent) => Some(node.with_value(parent)), + None => { + let macro_file = node.file_id.macro_file()?; + + let expansion_info = this + .cache + .expansion_info_cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(this.db.upcast())); + + expansion_info.call_node().map(|node| node?.parent()).transpose() + } + }; + let mut node = node.cloned(); + while let Some(parent) = parent(self, node.as_ref()) { + if let Some(res) = cb(self, parent.clone()) { + return Some(res); + } + node = parent; + } + None + } + + fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { + self.ancestors_with_macros(src, |this, InFile { file_id, value }| { + let item = ast::Item::cast(value)?; + match &item { + ast::Item::Fn(it) => this.fn_to_def(InFile::new(file_id, it)).map(Into::into), + ast::Item::Struct(it) => { + this.struct_to_def(InFile::new(file_id, it)).map(Into::into) + } + ast::Item::Enum(it) => this.enum_to_def(InFile::new(file_id, it)).map(Into::into), + ast::Item::Trait(it) => this.trait_to_def(InFile::new(file_id, it)).map(Into::into), + ast::Item::TraitAlias(it) => { + this.trait_alias_to_def(InFile::new(file_id, it)).map(Into::into) + } + ast::Item::TypeAlias(it) => { + this.type_alias_to_def(InFile::new(file_id, it)).map(Into::into) + } + ast::Item::Impl(it) => this.impl_to_def(InFile::new(file_id, it)).map(Into::into), + _ => None, + } + }) + } + + fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> { + self.ancestors_with_macros(src, |this, InFile { file_id, value }| { + let item = match ast::Item::cast(value.clone()) { + Some(it) => it, + None => { + let variant = ast::Variant::cast(value.clone())?; + return this + .enum_variant_to_def(InFile::new(file_id, &variant)) + .map(Into::into); + } + }; + match &item { + ast::Item::Fn(it) => this.fn_to_def(InFile::new(file_id, it)).map(Into::into), + ast::Item::Const(it) => this.const_to_def(InFile::new(file_id, it)).map(Into::into), + ast::Item::Static(it) => { + this.static_to_def(InFile::new(file_id, it)).map(Into::into) + } + _ => None, + } + }) + } + fn container_to_def(&mut self, container: InFile<SyntaxNode>) -> Option<ChildContainer> { let cont = if let Some(item) = ast::Item::cast(container.value.clone()) { - match item { + match &item { ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(), ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), ast::Item::TraitAlias(it) => { @@ -413,63 +528,11 @@ impl SourceToDefCtx<'_, '_> { } } else { let it = ast::Variant::cast(container.value)?; - let def = self.enum_variant_to_def(InFile::new(container.file_id, it))?; + let def = self.enum_variant_to_def(InFile::new(container.file_id, &it))?; DefWithBodyId::from(def).into() }; Some(cont) } - - fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { - let ancestors = src.ancestors_with_macros(self.db.upcast()); - for InFile { file_id, value } in ancestors { - let item = match ast::Item::cast(value) { - Some(it) => it, - None => continue, - }; - let res: GenericDefId = match item { - ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Union(it) => self.union_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(), - ast::Item::TraitAlias(it) => { - self.trait_alias_to_def(InFile::new(file_id, it))?.into() - } - ast::Item::TypeAlias(it) => { - self.type_alias_to_def(InFile::new(file_id, it))?.into() - } - ast::Item::Impl(it) => self.impl_to_def(InFile::new(file_id, it))?.into(), - _ => continue, - }; - return Some(res); - } - None - } - - fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> { - let ancestors = src.ancestors_with_macros(self.db.upcast()); - for InFile { file_id, value } in ancestors { - let item = match ast::Item::cast(value.clone()) { - Some(it) => it, - None => { - if let Some(variant) = ast::Variant::cast(value.clone()) { - return self - .enum_variant_to_def(InFile::new(file_id, variant)) - .map(Into::into); - } - continue; - } - }; - let res: DefWithBodyId = match item { - ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Static(it) => self.static_to_def(InFile::new(file_id, it))?.into(), - ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), - _ => continue, - }; - return Some(res); - } - None - } } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -501,6 +564,7 @@ impl_from! { impl ChildContainer { fn child_by_source(self, db: &dyn HirDatabase, file_id: HirFileId) -> DynMap { + let _p = tracing::span!(tracing::Level::INFO, "ChildContainer::child_by_source").entered(); let db = db.upcast(); match self { ChildContainer::DefWithBodyId(it) => it.child_by_source(db, file_id), diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index d2295840642..7ce64b4c486 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -24,11 +24,12 @@ use hir_def::{ LocalFieldId, Lookup, ModuleDefId, TraitId, VariantId, }; use hir_expand::{ - builtin_fn_macro::BuiltinFnLikeExpander, mod_path::path, - name, - name::{AsName, Name}, HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt, + { + name, + name::{AsName, Name}, + }, }; use hir_ty::{ diagnostics::{ @@ -822,6 +823,8 @@ impl SourceAnalyzer { macro_call: InFile<&ast::MacroCall>, ) -> Option<MacroFileId> { let krate = self.resolver.krate(); + // FIXME: This causes us to parse, generally this is the wrong approach for resolving a + // macro call to a macro call id! let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { self.resolver.resolve_path_as_macro_def(db.upcast(), &path, Some(MacroSubNs::Bang)) })?; @@ -839,37 +842,13 @@ impl SourceAnalyzer { infer.variant_resolution_for_expr(expr_id) } - pub(crate) fn is_unsafe_macro_call( + pub(crate) fn is_unsafe_macro_call_expr( &self, db: &dyn HirDatabase, - macro_call: InFile<&ast::MacroCall>, + macro_expr: InFile<&ast::MacroExpr>, ) -> bool { - // check for asm/global_asm - if let Some(mac) = self.resolve_macro_call(db, macro_call) { - let ex = match mac.id { - hir_def::MacroId::Macro2Id(it) => it.lookup(db.upcast()).expander, - hir_def::MacroId::MacroRulesId(it) => it.lookup(db.upcast()).expander, - _ => hir_def::MacroExpander::Declarative, - }; - match ex { - hir_def::MacroExpander::BuiltIn(e) - if e == BuiltinFnLikeExpander::Asm || e == BuiltinFnLikeExpander::GlobalAsm => - { - return true - } - _ => (), - } - } - let macro_expr = match macro_call - .map(|it| it.syntax().parent().and_then(ast::MacroExpr::cast)) - .transpose() - { - Some(it) => it, - None => return false, - }; - if let (Some((def, body, sm)), Some(infer)) = (&self.def, &self.infer) { - if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr.as_ref()) { + if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) { let mut is_unsafe = false; unsafe_expressions( db, diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 3b784ebec3b..c73b6acb0d0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -584,6 +584,9 @@ fn highlight_method_call( if func.is_async(sema.db) { h |= HlMod::Async; } + if func.is_const(sema.db) { + h |= HlMod::Const; + } if func .as_assoc_item(sema.db) .and_then(|it| it.container_or_implemented_trait(sema.db)) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html index eed3968a906..70f2d7203e9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html @@ -48,16 +48,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>foo<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="brace">{</span> <span class="keyword">mod</span> y <span class="brace">{</span> - <span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span> + <span class="keyword">pub</span> <span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span> <span class="brace">}</span> <span class="brace">}</span><span class="semicolon">;</span> <span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> - <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span> - <span class="comment">// FIXME: IDE layer has this unresolved</span> - <span class="unresolved_reference">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> + <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span> <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">></span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span> <span class="brace">}</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html index cd6ffc2c3ae..a14f2cc88cd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html @@ -66,10 +66,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span> <span class="keyword macro">const</span> <span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="method const consuming trait">assoc_const_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">}</span> <span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span> <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> + <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="method associated const consuming declaration trait">assoc_const_method</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> <span class="keyword">impl</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html index 893e3c06751..dfad3a6605c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html @@ -49,5 +49,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="enum_variant default_library library">Some</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span> - <span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="method default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> + <span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="method const default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">}</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index 413edb6d65f..9be7c92fc79 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -218,7 +218,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="bool_literal">true</span> <span class="brace">}</span> <span class="brace">}</span> -<span class="keyword const">const</span> <span class="constant const declaration">USAGE_OF_BOOL</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="method consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> +<span class="keyword const">const</span> <span class="constant const declaration">USAGE_OF_BOOL</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="method const consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="keyword">trait</span> <span class="trait declaration">Baz</span> <span class="brace">{</span> <span class="keyword">type</span> <span class="type_alias associated declaration static trait">Qux</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 22706dea1fa..cb47fc68bc1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -165,7 +165,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span> - <span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> + <span class="macro default_library library">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> <span class="string_literal macro">"mov </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"add </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, 5"</span><span class="comma macro">,</span> <span class="none macro">out</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">o</span><span class="comma macro">,</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 901e41d27cd..08acfca2cb6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -657,10 +657,12 @@ const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const C &raw const (); const ); + ().assoc_const_method(); } trait ConstTrait { const ASSOC_CONST: () = (); const fn assoc_const_fn() {} + const fn assoc_const_method(self) {} } impl const ConstTrait for () { const ASSOC_CONST: () = (); @@ -1070,16 +1072,15 @@ fn test_block_mod_items() { macro_rules! foo { ($foo:ident) => { mod y { - struct $foo; + pub struct $foo; } }; } fn main() { foo!(Foo); mod module { - // FIXME: IDE layer has this unresolved foo!(Bar); - fn func() { + fn func(_: y::Bar) { mod inner { struct Innerest<const C: usize> { field: [(); {C}] } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 5d617780b6d..7a7661e4317 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -74,7 +74,7 @@ fn integrated_highlighting_benchmark() { host.apply_change(change); } - let _g = crate::tracing::hprof::init("*>20"); + let _g = crate::tracing::hprof::init("*>10"); { let _it = stdx::timeit("after change"); @@ -160,7 +160,7 @@ fn integrated_completion_benchmark() { analysis.completions(&config, position, None).unwrap(); } - let _g = crate::tracing::hprof::init("*"); + let _g = crate::tracing::hprof::init("*>10"); let completion_offset = { let _it = stdx::timeit("change"); |
