about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/child_by_source.rs14
-rw-r--r--crates/hir-def/src/item_scope.rs16
-rw-r--r--crates/hir-def/src/nameres/collector.rs13
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs4
-rw-r--r--crates/hir-def/src/resolver.rs9
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/hir/src/symbols.rs12
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_macros.html7
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs7
9 files changed, 57 insertions, 27 deletions
diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs
index b1337ecc242..5b1435e8f44 100644
--- a/crates/hir-def/src/child_by_source.rs
+++ b/crates/hir-def/src/child_by_source.rs
@@ -102,13 +102,15 @@ impl ChildBySource for ItemScope {
                 res[keys::ATTR_MACRO_CALL].insert(ast_id.to_node(db.upcast()), call_id);
             },
         );
-        self.legacy_macros().for_each(|(_, id)| {
-            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);
+        self.legacy_macros().for_each(|(_, ids)| {
+            ids.iter().for_each(|&id| {
+                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);
+                    }
                 }
-            }
+            })
         });
         self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
             |(ast_id, calls)| {
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index ddccbbfef9c..609943ac244 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -61,7 +61,7 @@ pub struct ItemScope {
     /// Module scoped macros will be inserted into `items` instead of here.
     // 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, MacroId>,
+    legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
     /// The derive macro invocations in this scope.
     attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
     /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
@@ -129,13 +129,13 @@ impl ItemScope {
     }
 
     /// Iterate over all module scoped macros
-    pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
+    pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
         self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
     }
 
     /// Iterate over all legacy textual scoped macros visible at the end of the module
-    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroId)> + 'a {
-        self.legacy_macros.iter().map(|(name, def)| (name, *def))
+    pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
+        self.legacy_macros.iter().map(|(name, def)| (name, &**def))
     }
 
     /// Get a name from current module scope, legacy macros are not included
@@ -180,8 +180,8 @@ impl ItemScope {
         self.declarations.push(def)
     }
 
-    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroId> {
-        self.legacy_macros.get(name).copied()
+    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<&[MacroId]> {
+        self.legacy_macros.get(name).map(|it| &**it)
     }
 
     pub(crate) fn define_impl(&mut self, imp: ImplId) {
@@ -193,7 +193,7 @@ impl ItemScope {
     }
 
     pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
-        self.legacy_macros.insert(name, mac);
+        self.legacy_macros.entry(name).or_default().push(mac);
     }
 
     pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
@@ -322,7 +322,7 @@ impl ItemScope {
         )
     }
 
-    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroId> {
+    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, SmallVec<[MacroId; 1]>> {
         self.legacy_macros.clone()
     }
 
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index ca0cb99b371..02f0d37dd82 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1809,7 +1809,9 @@ impl ModCollector<'_, '_> {
         let res = modules.alloc(ModuleData::new(origin, vis));
         modules[res].parent = Some(self.module_id);
         for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
-            modules[res].scope.define_legacy_macro(name, mac)
+            for &mac in &mac {
+                modules[res].scope.define_legacy_macro(name.clone(), mac);
+            }
         }
         modules[self.module_id].children.insert(name.clone(), res);
 
@@ -2027,7 +2029,8 @@ impl ModCollector<'_, '_> {
                             map[module]
                                 .scope
                                 .get_legacy_macro(name)
-                                .map(|it| macro_id_to_def_id(self.def_collector.db, it.into()))
+                                .and_then(|it| it.last())
+                                .map(|&it| macro_id_to_def_id(self.def_collector.db, it.into()))
                         },
                     )
                 })
@@ -2080,8 +2083,10 @@ impl ModCollector<'_, '_> {
 
     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
         let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
-        for (name, macro_) in macros {
-            self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
+        for (name, macs) in macros {
+            macs.last().map(|&mac| {
+                self.def_collector.define_legacy_macro(self.module_id, name.clone(), mac)
+            });
         }
     }
 
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index cc5fc0a52a1..c579bc9194c 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -381,7 +381,9 @@ impl DefMap {
         let from_legacy_macro = self[module]
             .scope
             .get_legacy_macro(name)
-            .map_or_else(PerNs::none, |m| PerNs::macros(m.into(), Visibility::Public));
+            // FIXME: shadowing
+            .and_then(|it| it.last())
+            .map_or_else(PerNs::none, |&m| PerNs::macros(m.into(), Visibility::Public));
         let from_scope = self[module].scope.get(name);
         let from_builtin = match self.block {
             Some(_) => {
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index f3dcdcfa4a1..c8d3052102f 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -508,8 +508,13 @@ impl Scope {
                 m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
                     acc.add_per_ns(name, def);
                 });
-                m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, mac)| {
-                    acc.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))));
+                m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macs)| {
+                    macs.iter().for_each(|&mac| {
+                        acc.add(
+                            name,
+                            ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))),
+                        );
+                    })
                 });
                 m.def_map.extern_prelude().for_each(|(name, &def)| {
                     acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def)));
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ef17f2a75e1..42b8d3ca202 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -559,7 +559,7 @@ impl Module {
     pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
         let def_map = self.id.def_map(db.upcast());
         let scope = &def_map[self.id.local_id].scope;
-        scope.legacy_macros().map(|(_, it)| MacroId::from(it).into()).collect()
+        scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
     }
 
     pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index bdb8c7552d3..3b84877dd36 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -176,11 +176,13 @@ impl<'a> SymbolCollector<'a> {
         }
 
         for (_, id) in scope.legacy_macros() {
-            if id.module(self.db.upcast()) == module_id {
-                match id {
-                    MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
-                    MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
-                    MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
+            for &id in id {
+                if id.module(self.db.upcast()) == module_id {
+                    match id {
+                        MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
+                        MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
+                        MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
+                    }
                 }
             }
         }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index b725c80565e..54d4279525d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -68,6 +68,13 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
+<span class="comment documentation">/// textually shadow previous definition</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+        <span class="punctuation">$</span>expr
+    <span class="brace">}</span>
+<span class="brace">}</span>
+
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
 <span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 83bdca295da..6ba6153178d 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -63,6 +63,13 @@ macro_rules! noop {
     }
 }
 
+/// textually shadow previous definition
+macro_rules! noop {
+    ($expr:expr) => {
+        $expr
+    }
+}
+
 macro_rules! keyword_frag {
     ($type:ty) => ($type)
 }