]> git.lizzy.rs Git - rust.git/commitdiff
Handle attribute macros in `descend_into_macros`
authorJonas Schievink <jonasschievink@gmail.com>
Sun, 6 Jun 2021 13:51:05 +0000 (15:51 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Sun, 6 Jun 2021 15:03:37 +0000 (17:03 +0200)
crates/hir/src/semantics.rs
crates/hir/src/semantics/source_to_def.rs
crates/hir_def/src/child_by_source.rs
crates/hir_def/src/item_scope.rs
crates/hir_def/src/keys.rs
crates/hir_def/src/nameres/collector.rs

index c7f2c02e4c4a09a00423f4bed2bc0a6e4d58ec2a..0d55e4a3e0b7306f638f0abc0d126715b43aa319 100644 (file)
@@ -362,25 +362,57 @@ fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
 
         let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
             self.db.unwind_if_cancelled();
-            let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?;
-            let tt = macro_call.token_tree()?;
-            if !tt.syntax().text_range().contains_range(token.value.text_range()) {
-                return None;
-            }
-            let file_id = sa.expand(self.db, token.with_value(&macro_call))?;
-            let token = self
-                .expansion_info_cache
-                .borrow_mut()
-                .entry(file_id)
-                .or_insert_with(|| file_id.expansion_info(self.db.upcast()))
-                .as_ref()?
-                .map_token_down(token.as_ref())?;
-
-            if let Some(parent) = token.value.parent() {
-                self.cache(find_root(&parent), token.file_id);
+
+            for node in token.value.ancestors() {
+                match_ast! {
+                    match node {
+                        ast::MacroCall(macro_call) => {
+                            let tt = macro_call.token_tree()?;
+                            if !tt.syntax().text_range().contains_range(token.value.text_range()) {
+                                return None;
+                            }
+                            let file_id = sa.expand(self.db, token.with_value(&macro_call))?;
+                            let token = self
+                                .expansion_info_cache
+                                .borrow_mut()
+                                .entry(file_id)
+                                .or_insert_with(|| file_id.expansion_info(self.db.upcast()))
+                                .as_ref()?
+                                .map_token_down(token.as_ref())?;
+
+                            if let Some(parent) = token.value.parent() {
+                                self.cache(find_root(&parent), token.file_id);
+                            }
+
+                            return Some(token);
+                        },
+                        ast::Item(item) => {
+                            match self.with_ctx(|ctx| ctx.item_to_macro_call(token.with_value(item))) {
+                                Some(call_id) => {
+                                    let file_id = call_id.as_file();
+                                    let token = self
+                                        .expansion_info_cache
+                                        .borrow_mut()
+                                        .entry(file_id)
+                                        .or_insert_with(|| file_id.expansion_info(self.db.upcast()))
+                                        .as_ref()?
+                                        .map_token_down(token.as_ref())?;
+
+                                    if let Some(parent) = token.value.parent() {
+                                        self.cache(find_root(&parent), token.file_id);
+                                    }
+
+                                    return Some(token);
+                                }
+                                None => {}
+                            }
+                        },
+                        _ => {}
+                    }
+                }
             }
 
-            Some(token)
+            None
         })
         .last()
         .unwrap();
index 9a5a2255fa8412a46313bd14ba418dd307ebe5ed..22e196196ded02fc80bff4367e9cfb5b41506286 100644 (file)
@@ -10,7 +10,7 @@
     ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
     UnionId, VariantId,
 };
-use hir_expand::{name::AsName, AstId, MacroDefKind};
+use hir_expand::{name::AsName, AstId, MacroCallId, MacroDefKind};
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use stdx::impl_from;
@@ -145,16 +145,25 @@ pub(super) fn label_to_def(
         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].get(&src).copied()
+    }
+
     fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
         &mut self,
         src: InFile<Ast>,
         key: Key<Ast, ID>,
     ) -> Option<ID> {
-        let container = self.find_container(src.as_ref().map(|it| it.syntax()))?;
+        self.dyn_map(src.as_ref())?[key].get(&src).copied()
+    }
+
+    fn dyn_map<Ast: AstNode + 'static>(&mut self, src: InFile<&Ast>) -> Option<&DynMap> {
+        let container = self.find_container(src.map(|it| it.syntax()))?;
         let db = self.db;
         let dyn_map =
             &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
-        dyn_map[key].get(&src).copied()
+        Some(dyn_map)
     }
 
     pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
index f2e809ca9cebfae1821314a6748f7da7ad948db0..f22383e221d9bb8abcfbbc4862842c2da00223cb 100644 (file)
@@ -85,6 +85,10 @@ fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
             res[keys::CONST].insert(src, konst);
         });
         self.impls().for_each(|imp| add_impl(db, res, imp));
+        self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
+            let item = ast_id.with_value(ast_id.to_node(db.upcast()));
+            res[keys::ATTR_MACRO].insert(item, call_id);
+        });
 
         fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
             match item {
index 9014468ea04f11fe5d4a261584f8da194d90c2bb..0f74f050da627251bd0063fb0015a91509e6ddec 100644 (file)
@@ -4,11 +4,11 @@
 use std::collections::hash_map::Entry;
 
 use base_db::CrateId;
-use hir_expand::name::Name;
-use hir_expand::MacroDefKind;
+use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind};
 use once_cell::sync::Lazy;
 use rustc_hash::{FxHashMap, FxHashSet};
 use stdx::format_to;
+use syntax::ast;
 
 use crate::{
     db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
@@ -53,6 +53,7 @@ pub struct ItemScope {
     // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
     // be all resolved to the last one defined if shadowing happens.
     legacy_macros: FxHashMap<Name, MacroDefId>,
+    attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
 }
 
 pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
@@ -169,6 +170,16 @@ pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
         self.legacy_macros.insert(name, mac);
     }
 
+    pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
+        self.attr_macros.insert(item, call);
+    }
+
+    pub(crate) fn attr_macro_invocs(
+        &self,
+    ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
+        self.attr_macros.iter().map(|(k, v)| (*k, *v))
+    }
+
     pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
         self.unnamed_trait_imports.get(&tr).copied()
     }
@@ -307,6 +318,7 @@ pub(crate) fn shrink_to_fit(&mut self) {
             unnamed_consts,
             unnamed_trait_imports,
             legacy_macros,
+            attr_macros,
         } = self;
         types.shrink_to_fit();
         values.shrink_to_fit();
@@ -317,6 +329,7 @@ pub(crate) fn shrink_to_fit(&mut self) {
         unnamed_consts.shrink_to_fit();
         unnamed_trait_imports.shrink_to_fit();
         legacy_macros.shrink_to_fit();
+        attr_macros.shrink_to_fit();
     }
 }
 
index 89b3ed8686439563280420c62521783b56643911..688cd9fcff6a55cf2be3a2ae6b4ff685267b10c2 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::marker::PhantomData;
 
-use hir_expand::{InFile, MacroDefId};
+use hir_expand::{InFile, MacroCallId, MacroDefId};
 use rustc_hash::FxHashMap;
 use syntax::{ast, AstNode, AstPtr};
 
@@ -32,6 +32,7 @@
 pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
 
 pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
+pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
 
 /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
 /// equal if they point to exactly the same object.
index d0b1db5d1071d3b74e7dd2f21553be75dc974d8c..d019ba3a9626c45afbe7f46e8c5d32ed727440d5 100644 (file)
@@ -1112,6 +1112,11 @@ fn resolve_macros(&mut self) -> ReachedFixedPoint {
                                     return false;
                                 }
                             }
+
+                            self.def_map.modules[directive.module_id]
+                                .scope
+                                .add_attr_macro_invoc(ast_id.ast_id, call_id);
+
                             resolved.push((directive.module_id, call_id, directive.depth));
                             res = ReachedFixedPoint::No;
                             return false;