diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-05 04:35:13 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-09-05 04:46:00 +0100 |
commit | 0d23286caf35a7cd8aed6e20fab3a2a3ed91ae8f (patch) | |
tree | df01037e66b345a13ba00c197ab3d6dd24d8050e /crates/ra_hir/src/nameres/collector.rs | |
parent | a66214b34effe1ad7f4351a1b920cf3a8f98d3c0 (diff) |
Let `macro_use` bypass module scope
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 58 |
1 files changed, 38 insertions, 20 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, ¯o_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, ¯o_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 | } |