aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs45
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs63
3 files changed, 91 insertions, 18 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index 2e1d35c8c..fe119b97c 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -12,4 +12,5 @@ test_utils::marks!(
12 trait_resolution_on_fn_type 12 trait_resolution_on_fn_type
13 infer_while_let 13 infer_while_let
14 macro_rules_from_other_crates_are_visible_with_macro_use 14 macro_rules_from_other_crates_are_visible_with_macro_use
15 prelude_is_macro_use
15); 16);
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, &macro_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, &macro_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]
196fn 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}