diff options
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 37 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 2 |
4 files changed, 39 insertions, 29 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index befbb2a9b..74546e5e2 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -138,8 +138,21 @@ pub(crate) struct ModuleData { | |||
138 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 138 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
139 | pub struct ModuleScope { | 139 | pub struct ModuleScope { |
140 | items: FxHashMap<Name, Resolution>, | 140 | items: FxHashMap<Name, Resolution>, |
141 | /// Macros in current module scoped | ||
142 | /// | ||
143 | /// This scope works exactly the same way that item scoping does. | ||
144 | /// Macro invocation with quantified path will search in it. | ||
145 | /// See details below. | ||
141 | macros: FxHashMap<Name, MacroDef>, | 146 | macros: FxHashMap<Name, MacroDef>, |
142 | textual_macros: FxHashMap<Name, MacroDef>, | 147 | /// Macros visable in current module in legacy textual scope |
148 | /// | ||
149 | /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. | ||
150 | /// If it yields no result, then it turns to module scoped `macros`. | ||
151 | /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, | ||
152 | /// and only normal scoped `macros` will be searched in. | ||
153 | /// | ||
154 | /// Note that this automatically inherit macros defined textually before the definition of module itself. | ||
155 | legacy_macros: FxHashMap<Name, MacroDef>, | ||
143 | } | 156 | } |
144 | 157 | ||
145 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| { | 158 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| { |
@@ -173,8 +186,8 @@ impl ModuleScope { | |||
173 | _ => None, | 186 | _ => None, |
174 | } | 187 | } |
175 | } | 188 | } |
176 | fn get_textual_macro(&self, name: &Name) -> Option<MacroDef> { | 189 | fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> { |
177 | self.textual_macros.get(name).copied() | 190 | self.legacy_macros.get(name).copied() |
178 | } | 191 | } |
179 | } | 192 | } |
180 | 193 | ||
@@ -489,13 +502,13 @@ impl CrateDefMap { | |||
489 | name: &Name, | 502 | name: &Name, |
490 | ) -> ItemOrMacro { | 503 | ) -> ItemOrMacro { |
491 | // Resolve in: | 504 | // Resolve in: |
492 | // - textual scoped macros | 505 | // - legacy scope |
493 | // - current module / scope | 506 | // - current module / scope |
494 | // - extern prelude | 507 | // - extern prelude |
495 | // - std prelude | 508 | // - std prelude |
496 | let from_textual_mcro = self[module] | 509 | let from_legacy_macro = self[module] |
497 | .scope | 510 | .scope |
498 | .get_textual_macro(name) | 511 | .get_legacy_macro(name) |
499 | .map_or_else(|| Either::A(PerNs::none()), Either::B); | 512 | .map_or_else(|| Either::A(PerNs::none()), Either::B); |
500 | let from_scope = | 513 | let from_scope = |
501 | self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none())); | 514 | self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none())); |
@@ -503,7 +516,7 @@ impl CrateDefMap { | |||
503 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 516 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); |
504 | let from_prelude = self.resolve_in_prelude(db, name); | 517 | let from_prelude = self.resolve_in_prelude(db, name); |
505 | 518 | ||
506 | or(from_textual_mcro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) | 519 | or(from_legacy_macro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) |
507 | } | 520 | } |
508 | 521 | ||
509 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | 522 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 10c32ffa1..09cda7656 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -146,22 +146,19 @@ where | |||
146 | self.def_map.exported_macros.insert(name.clone(), macro_id); | 146 | self.def_map.exported_macros.insert(name.clone(), macro_id); |
147 | } | 147 | } |
148 | self.update(module_id, None, &[(name.clone(), def)]); | 148 | self.update(module_id, None, &[(name.clone(), def)]); |
149 | self.define_textual_macro(module_id, name.clone(), macro_id); | 149 | self.define_legacy_macro(module_id, name.clone(), macro_id); |
150 | } | 150 | } |
151 | 151 | ||
152 | /// Define a macro in current textual scope. | 152 | /// Define a legacy textual scoped macro in module |
153 | /// | 153 | /// |
154 | /// We use a map `textual_macros` to store all textual macros visable per module. | 154 | /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module. |
155 | /// It will clone all macros from parent textual scope, whose definition is prior to | 155 | /// It will clone all macros from parent legacy scope, whose definition is prior to |
156 | /// the definition of current module. | 156 | /// the definition of current module. |
157 | /// And also, `macro_use` on a module will import all textual macros visable inside to | 157 | /// And also, `macro_use` on a module will import all legacy macros visable inside to |
158 | /// current textual scope, with possible shadowing. | 158 | /// current legacy scope, with possible shadowing. |
159 | fn define_textual_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { | 159 | fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { |
160 | // Always shadowing | 160 | // Always shadowing |
161 | self.def_map.modules[module_id] | 161 | self.def_map.modules[module_id].scope.legacy_macros.insert(name, MacroDef { id: macro_id }); |
162 | .scope | ||
163 | .textual_macros | ||
164 | .insert(name, MacroDef { id: macro_id }); | ||
165 | } | 162 | } |
166 | 163 | ||
167 | /// Import macros from `#[macro_use] extern crate`. | 164 | /// Import macros from `#[macro_use] extern crate`. |
@@ -194,7 +191,7 @@ where | |||
194 | fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, module: Module) { | 191 | fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, module: Module) { |
195 | let item_map = self.db.crate_def_map(module.krate); | 192 | let item_map = self.db.crate_def_map(module.krate); |
196 | for (name, ¯o_id) in &item_map.exported_macros { | 193 | for (name, ¯o_id) in &item_map.exported_macros { |
197 | self.define_textual_macro(current_module_id, name.clone(), macro_id); | 194 | self.define_legacy_macro(current_module_id, name.clone(), macro_id); |
198 | } | 195 | } |
199 | } | 196 | } |
200 | 197 | ||
@@ -578,7 +575,7 @@ where | |||
578 | } | 575 | } |
579 | .collect(&*items); | 576 | .collect(&*items); |
580 | if *is_macro_use { | 577 | if *is_macro_use { |
581 | self.import_all_textual_macros(module_id); | 578 | self.import_all_legacy_macros(module_id); |
582 | } | 579 | } |
583 | } | 580 | } |
584 | // out of line module, resolve, parse and recurse | 581 | // out of line module, resolve, parse and recurse |
@@ -605,7 +602,7 @@ where | |||
605 | } | 602 | } |
606 | .collect(raw_items.items()); | 603 | .collect(raw_items.items()); |
607 | if *is_macro_use { | 604 | if *is_macro_use { |
608 | self.import_all_textual_macros(module_id); | 605 | self.import_all_legacy_macros(module_id); |
609 | } | 606 | } |
610 | } | 607 | } |
611 | Err(candidate) => self.def_collector.def_map.diagnostics.push( | 608 | Err(candidate) => self.def_collector.def_map.diagnostics.push( |
@@ -631,7 +628,7 @@ where | |||
631 | modules[res].parent = Some(self.module_id); | 628 | modules[res].parent = Some(self.module_id); |
632 | modules[res].declaration = Some(declaration); | 629 | modules[res].declaration = Some(declaration); |
633 | modules[res].definition = definition; | 630 | modules[res].definition = definition; |
634 | modules[res].scope.textual_macros = modules[self.module_id].scope.textual_macros.clone(); | 631 | modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); |
635 | modules[self.module_id].children.insert(name.clone(), res); | 632 | modules[self.module_id].children.insert(name.clone(), res); |
636 | let resolution = Resolution { | 633 | let resolution = Resolution { |
637 | def: PerNs::types( | 634 | def: PerNs::types( |
@@ -685,10 +682,10 @@ where | |||
685 | 682 | ||
686 | let ast_id = mac.ast_id.with_file_id(self.file_id); | 683 | let ast_id = mac.ast_id.with_file_id(self.file_id); |
687 | 684 | ||
688 | // Case 2: try to resolve in textual scope and expand macro_rules, triggering | 685 | // Case 2: try to resolve in legacy scope and expand macro_rules, triggering |
689 | // recursive item collection. | 686 | // recursive item collection. |
690 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { | 687 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { |
691 | self.def_collector.def_map[self.module_id].scope.get_textual_macro(&name) | 688 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) |
692 | }) { | 689 | }) { |
693 | let def = macro_def.id; | 690 | let def = macro_def.id; |
694 | let macro_call_id = MacroCallLoc { def, ast_id }.id(self.def_collector.db); | 691 | let macro_call_id = MacroCallLoc { def, ast_id }.id(self.def_collector.db); |
@@ -706,10 +703,10 @@ where | |||
706 | self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); | 703 | self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); |
707 | } | 704 | } |
708 | 705 | ||
709 | fn import_all_textual_macros(&mut self, module_id: CrateModuleId) { | 706 | fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { |
710 | let macros = self.def_collector.def_map[module_id].scope.textual_macros.clone(); | 707 | let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); |
711 | for (name, macro_) in macros { | 708 | for (name, macro_) in macros { |
712 | self.def_collector.define_textual_macro(self.module_id, name.clone(), macro_.id); | 709 | self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_.id); |
713 | } | 710 | } |
714 | } | 711 | } |
715 | } | 712 | } |
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index a894c6836..21fab53e9 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||
@@ -279,7 +279,7 @@ fn prelude_cycle() { | |||
279 | } | 279 | } |
280 | 280 | ||
281 | #[test] | 281 | #[test] |
282 | fn plain_macros_are_textual_scoped() { | 282 | fn plain_macros_are_legacy_textual_scoped() { |
283 | let map = def_map( | 283 | let map = def_map( |
284 | r#" | 284 | r#" |
285 | //- /main.rs | 285 | //- /main.rs |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f2d5b115e..25716fe8c 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2804,7 +2804,7 @@ fn main() { | |||
2804 | } | 2804 | } |
2805 | 2805 | ||
2806 | #[test] | 2806 | #[test] |
2807 | fn infer_textual_scoped_macros_expanded() { | 2807 | fn infer_legacy_textual_scoped_macros_expanded() { |
2808 | assert_snapshot!( | 2808 | assert_snapshot!( |
2809 | infer(r#" | 2809 | infer(r#" |
2810 | struct Foo(Vec<i32>); | 2810 | struct Foo(Vec<i32>); |