aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs48
1 files changed, 43 insertions, 5 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 7da2dcdff..5d1c42926 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -157,11 +157,42 @@ where
157 // crate root, even if the parent modules is **not** visible. 157 // crate root, even if the parent modules is **not** visible.
158 if export { 158 if export {
159 self.update(self.def_map.root, None, &[(name.clone(), def.clone())]); 159 self.update(self.def_map.root, None, &[(name.clone(), def.clone())]);
160
161 // Exported macros are collected in crate level ready for
162 // glob import with `#[macro_use]`.
163 self.def_map.exported_macros.insert(name.clone(), macro_id);
160 } 164 }
161 self.update(module_id, None, &[(name.clone(), def)]); 165 self.update(module_id, None, &[(name.clone(), def)]);
162 self.global_macro_scope.insert(name, macro_id); 166 self.global_macro_scope.insert(name, macro_id);
163 } 167 }
164 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
165 fn resolve_imports(&mut self) -> ReachedFixedPoint { 196 fn resolve_imports(&mut self) -> ReachedFixedPoint {
166 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());
167 let mut resolved = Vec::new(); 198 let mut resolved = Vec::new();
@@ -494,11 +525,17 @@ where
494 for item in items { 525 for item in items {
495 match *item { 526 match *item {
496 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), 527 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]),
497 raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push(( 528 raw::RawItem::Import(import_id) => {
498 self.module_id, 529 let import = self.raw_items[import_id].clone();
499 import, 530 // This should be processed eagerly instead of deferred to resolving.
500 self.raw_items[import].clone(), 531 // Otherwise, since it will only mutate `global_macro_scope`
501 )), 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 }
502 raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), 539 raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]),
503 raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 540 raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
504 } 541 }
@@ -860,6 +897,7 @@ mod tests {
860 root, 897 root,
861 modules, 898 modules,
862 poison_macros: FxHashSet::default(), 899 poison_macros: FxHashSet::default(),
900 exported_macros: FxHashMap::default(),
863 diagnostics: Vec::new(), 901 diagnostics: Vec::new(),
864 } 902 }
865 }; 903 };