diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 63 |
2 files changed, 90 insertions, 18 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index d6c7c083d..5af26f953 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -183,11 +183,14 @@ where | |||
183 | 183 | ||
184 | if let Some(ModuleDef::Module(m)) = res.take_types() { | 184 | if let Some(ModuleDef::Module(m)) = res.take_types() { |
185 | tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); | 185 | tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); |
186 | self.import_all_macros_exported(m); | ||
187 | } | ||
188 | } | ||
186 | 189 | ||
187 | let item_map = self.db.crate_def_map(m.krate); | 190 | fn import_all_macros_exported(&mut self, module: Module) { |
188 | for (name, ¯o_id) in &item_map.exported_macros { | 191 | let item_map = self.db.crate_def_map(module.krate); |
189 | self.global_macro_scope.insert(name.clone(), macro_id); | 192 | for (name, ¯o_id) in &item_map.exported_macros { |
190 | } | 193 | self.global_macro_scope.insert(name.clone(), macro_id); |
191 | } | 194 | } |
192 | } | 195 | } |
193 | 196 | ||
@@ -520,20 +523,32 @@ where | |||
520 | DB: DefDatabase, | 523 | DB: DefDatabase, |
521 | { | 524 | { |
522 | fn collect(&mut self, items: &[raw::RawItem]) { | 525 | fn collect(&mut self, items: &[raw::RawItem]) { |
526 | // Prelude module is always considered to be `#[macro_use]`. | ||
527 | if let Some(prelude_module) = self.def_collector.def_map.prelude { | ||
528 | tested_by!(prelude_is_macro_use); | ||
529 | self.def_collector.import_all_macros_exported(prelude_module); | ||
530 | } | ||
531 | |||
532 | // This should be processed eagerly instead of deferred to resolving. | ||
533 | // `#[macro_use] extern crate` is hoisted to imports macros before collecting | ||
534 | // any other items. | ||
535 | for item in items { | ||
536 | if let raw::RawItem::Import(import_id) = *item { | ||
537 | let import = self.raw_items[import_id].clone(); | ||
538 | if import.is_extern_crate && import.is_macro_use { | ||
539 | self.def_collector.import_macros_from_extern_crate(&import); | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | |||
523 | for item in items { | 544 | for item in items { |
524 | match *item { | 545 | match *item { |
525 | raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), | 546 | raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), |
526 | raw::RawItem::Import(import_id) => { | 547 | raw::RawItem::Import(import_id) => self.def_collector.unresolved_imports.push(( |
527 | let import = self.raw_items[import_id].clone(); | 548 | self.module_id, |
528 | // This should be processed eagerly instead of deferred to resolving. | 549 | import_id, |
529 | // Otherwise, since it will only mutate `global_macro_scope` | 550 | self.raw_items[import_id].clone(), |
530 | // without `update` names in `mod`s, unresolved macros cannot be expanded. | 551 | )), |
531 | if import.is_extern_crate && import.is_macro_use { | ||
532 | self.def_collector.import_macros_from_extern_crate(&import); | ||
533 | } | ||
534 | |||
535 | self.def_collector.unresolved_imports.push((self.module_id, import_id, import)); | ||
536 | } | ||
537 | raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), | 552 | raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), |
538 | raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), | 553 | raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), |
539 | } | 554 | } |
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index ebfefe273..aece1515b 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||
@@ -144,9 +144,6 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() { | |||
144 | let map = def_map_with_crate_graph( | 144 | let map = def_map_with_crate_graph( |
145 | " | 145 | " |
146 | //- /main.rs | 146 | //- /main.rs |
147 | #[macro_use] | ||
148 | extern crate foo; | ||
149 | |||
150 | structs!(Foo); | 147 | structs!(Foo); |
151 | structs_priv!(Bar); | 148 | structs_priv!(Bar); |
152 | structs_not_exported!(MacroNotResolved1); | 149 | structs_not_exported!(MacroNotResolved1); |
@@ -154,6 +151,9 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() { | |||
154 | 151 | ||
155 | mod bar; | 152 | mod bar; |
156 | 153 | ||
154 | #[macro_use] | ||
155 | extern crate foo; | ||
156 | |||
157 | //- /bar.rs | 157 | //- /bar.rs |
158 | structs!(Baz); | 158 | structs!(Baz); |
159 | crate::structs!(MacroNotResolved3); | 159 | crate::structs!(MacroNotResolved3); |
@@ -191,3 +191,60 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() { | |||
191 | ⋮Baz: t v | 191 | ⋮Baz: t v |
192 | "###); | 192 | "###); |
193 | } | 193 | } |
194 | |||
195 | #[test] | ||
196 | fn prelude_is_macro_use() { | ||
197 | covers!(prelude_is_macro_use); | ||
198 | let map = def_map_with_crate_graph( | ||
199 | " | ||
200 | //- /main.rs | ||
201 | structs!(Foo); | ||
202 | structs_priv!(Bar); | ||
203 | structs_outside!(Out); | ||
204 | crate::structs!(MacroNotResolved2); | ||
205 | |||
206 | mod bar; | ||
207 | |||
208 | //- /bar.rs | ||
209 | structs!(Baz); | ||
210 | crate::structs!(MacroNotResolved3); | ||
211 | |||
212 | //- /lib.rs | ||
213 | #[prelude_import] | ||
214 | use self::prelude::*; | ||
215 | |||
216 | mod prelude { | ||
217 | #[macro_export] | ||
218 | macro_rules! structs { | ||
219 | ($i:ident) => { struct $i; } | ||
220 | } | ||
221 | |||
222 | mod priv_mod { | ||
223 | #[macro_export] | ||
224 | macro_rules! structs_priv { | ||
225 | ($i:ident) => { struct $i; } | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | #[macro_export] | ||
231 | macro_rules! structs_outside { | ||
232 | ($i:ident) => { struct $i; } | ||
233 | } | ||
234 | ", | ||
235 | crate_graph! { | ||
236 | "main": ("/main.rs", ["foo"]), | ||
237 | "foo": ("/lib.rs", []), | ||
238 | }, | ||
239 | ); | ||
240 | assert_snapshot!(map, @r###" | ||
241 | ⋮crate | ||
242 | ⋮Bar: t v | ||
243 | ⋮Foo: t v | ||
244 | ⋮Out: t v | ||
245 | ⋮bar: t | ||
246 | ⋮ | ||
247 | ⋮crate::bar | ||
248 | ⋮Baz: t v | ||
249 | "###); | ||
250 | } | ||