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 | |
parent | a66214b34effe1ad7f4351a1b920cf3a8f98d3c0 (diff) |
Let `macro_use` bypass module scope
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 58 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 29 |
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, ¯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 | } |
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 | } |