aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs58
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs29
2 files changed, 52 insertions, 35 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index dbd687236..5d1c42926 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -166,6 +166,33 @@ where
166 self.global_macro_scope.insert(name, macro_id); 166 self.global_macro_scope.insert(name, macro_id);
167 } 167 }
168 168
169 /// Import macros from `#[macro_use] extern crate`.
170 ///
171 /// They are non-scoped, and will only be inserted into mutable `global_macro_scope`.
172 fn import_macros_from_extern_crate(&mut self, import: &raw::ImportData) {
173 log::debug!(
174 "importing macros from extern crate: {:?} ({:?})",
175 import,
176 self.def_map.edition,
177 );
178
179 let res = self.def_map.resolve_name_in_extern_prelude(
180 &import
181 .path
182 .as_ident()
183 .expect("extern crate should have been desugared to one-element path"),
184 );
185
186 if let Some(ModuleDef::Module(m)) = res.take_types() {
187 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
188
189 let item_map = self.db.crate_def_map(m.krate);
190 for (name, &macro_id) in &item_map.exported_macros {
191 self.global_macro_scope.insert(name.clone(), macro_id);
192 }
193 }
194 }
195
169 fn resolve_imports(&mut self) -> ReachedFixedPoint { 196 fn resolve_imports(&mut self) -> ReachedFixedPoint {
170 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 197 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
171 let mut resolved = Vec::new(); 198 let mut resolved = Vec::new();
@@ -299,21 +326,6 @@ where
299 } 326 }
300 } 327 }
301 328
302 // `#[macro_use] extern crate` glob imports all macros exported,
303 // ignoring their scopes
304 if import.is_extern_crate && import.is_macro_use {
305 if let Some(ModuleDef::Module(m)) =
306 def.a().and_then(|item| item.take_types())
307 {
308 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
309
310 let item_map = self.db.crate_def_map(m.krate);
311 for (name, &macro_id) in &item_map.exported_macros {
312 self.define_macro(module_id, name.clone(), macro_id, false);
313 }
314 }
315 }
316
317 let resolution = match def { 329 let resolution = match def {
318 Either::A(item) => { 330 Either::A(item) => {
319 Either::A(Resolution { def: item, import: Some(import_id) }) 331 Either::A(Resolution { def: item, import: Some(import_id) })
@@ -513,11 +525,17 @@ where
513 for item in items { 525 for item in items {
514 match *item { 526 match *item {
515 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), 527 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]),
516 raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push(( 528 raw::RawItem::Import(import_id) => {
517 self.module_id, 529 let import = self.raw_items[import_id].clone();
518 import, 530 // This should be processed eagerly instead of deferred to resolving.
519 self.raw_items[import].clone(), 531 // Otherwise, since it will only mutate `global_macro_scope`
520 )), 532 // without `update` names in `mod`s, unresolved macros cannot be expanded.
533 if import.is_extern_crate && import.is_macro_use {
534 self.def_collector.import_macros_from_extern_crate(&import);
535 }
536
537 self.def_collector.unresolved_imports.push((self.module_id, import_id, import));
538 }
521 raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), 539 raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]),
522 raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 540 raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
523 } 541 }
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index cfddf3029..ff762ee30 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -147,25 +147,31 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
147 #[macro_use] 147 #[macro_use]
148 extern crate foo; 148 extern crate foo;
149 149
150 structs!(Foo, Bar) 150 structs!(Foo);
151 structs_priv!(Bar);
152 structs_not_exported!(MacroNotResolved1);
153 crates::structs!(MacroNotResolved2);
151 154
152 mod bar; 155 mod bar;
153 156
154 //- /bar.rs 157 //- /bar.rs
155 use crate::*; 158 structs!(Baz);
159 crates::structs!(MacroNotResolved3);
156 160
157 //- /lib.rs 161 //- /lib.rs
158 #[macro_export] 162 #[macro_export]
159 macro_rules! structs { 163 macro_rules! structs {
160 ($($i:ident),*) => { 164 ($i:ident) => { struct $i; }
161 $(struct $i { field: u32 } )* 165 }
162 } 166
167 macro_rules! structs_not_exported {
168 ($i:ident) => { struct $i; }
163 } 169 }
164 170
165 mod priv_mod { 171 mod priv_mod {
166 #[macro_export] 172 #[macro_export]
167 macro_rules! baz { 173 macro_rules! structs_priv {
168 () => {}; 174 ($i:ident) => { struct $i; }
169 } 175 }
170 } 176 }
171 ", 177 ",
@@ -179,16 +185,9 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
179 ⋮Bar: t v 185 ⋮Bar: t v
180 ⋮Foo: t v 186 ⋮Foo: t v
181 ⋮bar: t 187 ⋮bar: t
182 ⋮baz: m
183 ⋮foo: t 188 ⋮foo: t
184 ⋮structs: m
185 189
186 ⋮crate::bar 190 ⋮crate::bar
187 ⋮Bar: t v 191 ⋮Baz: t v
188 ⋮Foo: t v
189 ⋮bar: t
190 ⋮baz: m
191 ⋮foo: t
192 ⋮structs: m
193 "###); 192 "###);
194} 193}