diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 6 |
7 files changed, 68 insertions, 66 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 9d9769859..012f374ec 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -827,25 +827,25 @@ where | |||
827 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 827 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
828 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 828 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
829 | ast::ExprKind::MacroCall(e) => { | 829 | ast::ExprKind::MacroCall(e) => { |
830 | // very hacky.FIXME change to use the macro resolution | ||
831 | let path = e.path().and_then(Path::from_ast); | ||
832 | |||
833 | let ast_id = self | 830 | let ast_id = self |
834 | .db | 831 | .db |
835 | .ast_id_map(self.current_file_id) | 832 | .ast_id_map(self.current_file_id) |
836 | .ast_id(e) | 833 | .ast_id(e) |
837 | .with_file_id(self.current_file_id); | 834 | .with_file_id(self.current_file_id); |
838 | 835 | ||
839 | if let Some(def) = self.resolver.resolve_macro_call(self.db, path) { | 836 | if let Some(path) = e.path().and_then(Path::from_ast) { |
840 | let call_id = MacroCallLoc { def, ast_id }.id(self.db); | 837 | if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { |
841 | let file_id = call_id.as_file(MacroFileKind::Expr); | 838 | let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db); |
842 | if let Some(node) = self.db.parse_or_expand(file_id) { | 839 | let file_id = call_id.as_file(MacroFileKind::Expr); |
843 | if let Some(expr) = ast::Expr::cast(&*node) { | 840 | if let Some(node) = self.db.parse_or_expand(file_id) { |
844 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); | 841 | if let Some(expr) = ast::Expr::cast(&*node) { |
845 | let old_file_id = std::mem::replace(&mut self.current_file_id, file_id); | 842 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); |
846 | let id = self.collect_expr(&expr); | 843 | let old_file_id = |
847 | self.current_file_id = old_file_id; | 844 | std::mem::replace(&mut self.current_file_id, file_id); |
848 | return id; | 845 | let id = self.collect_expr(&expr); |
846 | self.current_file_id = old_file_id; | ||
847 | return id; | ||
848 | } | ||
849 | } | 849 | } |
850 | } | 850 | } |
851 | } | 851 | } |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index dc0dd23c9..b5938fa03 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -92,7 +92,6 @@ pub struct CrateDefMap { | |||
92 | extern_prelude: FxHashMap<Name, ModuleDef>, | 92 | extern_prelude: FxHashMap<Name, ModuleDef>, |
93 | root: CrateModuleId, | 93 | root: CrateModuleId, |
94 | modules: Arena<CrateModuleId, ModuleData>, | 94 | modules: Arena<CrateModuleId, ModuleData>, |
95 | public_macros: FxHashMap<Name, MacroDefId>, | ||
96 | 95 | ||
97 | /// Some macros are not well-behavior, which leads to infinite loop | 96 | /// Some macros are not well-behavior, which leads to infinite loop |
98 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } | 97 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } |
@@ -106,7 +105,6 @@ pub struct CrateDefMap { | |||
106 | /// However, do we want to put it as a global variable? | 105 | /// However, do we want to put it as a global variable? |
107 | poison_macros: FxHashSet<MacroDefId>, | 106 | poison_macros: FxHashSet<MacroDefId>, |
108 | 107 | ||
109 | local_macros: FxHashMap<Name, MacroDefId>, | ||
110 | diagnostics: Vec<DefDiagnostic>, | 108 | diagnostics: Vec<DefDiagnostic>, |
111 | } | 109 | } |
112 | 110 | ||
@@ -249,9 +247,7 @@ impl CrateDefMap { | |||
249 | prelude: None, | 247 | prelude: None, |
250 | root, | 248 | root, |
251 | modules, | 249 | modules, |
252 | public_macros: FxHashMap::default(), | ||
253 | poison_macros: FxHashSet::default(), | 250 | poison_macros: FxHashSet::default(), |
254 | local_macros: FxHashMap::default(), | ||
255 | diagnostics: Vec::new(), | 251 | diagnostics: Vec::new(), |
256 | } | 252 | } |
257 | }; | 253 | }; |
@@ -313,7 +309,7 @@ impl CrateDefMap { | |||
313 | (res.resolved_def.left().unwrap_or_else(PerNs::none), res.segment_index) | 309 | (res.resolved_def.left().unwrap_or_else(PerNs::none), res.segment_index) |
314 | } | 310 | } |
315 | 311 | ||
316 | fn resolve_path_with_macro( | 312 | pub(crate) fn resolve_path_with_macro( |
317 | &self, | 313 | &self, |
318 | db: &impl DefDatabase, | 314 | db: &impl DefDatabase, |
319 | original_module: CrateModuleId, | 315 | original_module: CrateModuleId, |
@@ -323,27 +319,6 @@ impl CrateDefMap { | |||
323 | (res.resolved_def, res.segment_index) | 319 | (res.resolved_def, res.segment_index) |
324 | } | 320 | } |
325 | 321 | ||
326 | // FIXME: This seems to do the same work as `resolve_path_with_macro`, but | ||
327 | // using a completely different code path. Seems bad, huh? | ||
328 | pub(crate) fn find_macro( | ||
329 | &self, | ||
330 | db: &impl DefDatabase, | ||
331 | original_module: CrateModuleId, | ||
332 | path: &Path, | ||
333 | ) -> Option<MacroDefId> { | ||
334 | let name = path.expand_macro_expr()?; | ||
335 | // search local first | ||
336 | // FIXME: Remove public_macros check when we have a correct local_macors implementation | ||
337 | let local = | ||
338 | self.public_macros.get(&name).or_else(|| self.local_macros.get(&name)).map(|it| *it); | ||
339 | if local.is_some() { | ||
340 | return local; | ||
341 | } | ||
342 | |||
343 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); | ||
344 | res.resolved_def.right().map(|m| m.id) | ||
345 | } | ||
346 | |||
347 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 322 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
348 | // the result. | 323 | // the result. |
349 | fn resolve_path_fp_with_macro( | 324 | fn resolve_path_fp_with_macro( |
@@ -511,7 +486,7 @@ impl CrateDefMap { | |||
511 | let from_scope = self[module] | 486 | let from_scope = self[module] |
512 | .scope | 487 | .scope |
513 | .get_item_or_macro(name) | 488 | .get_item_or_macro(name) |
514 | .unwrap_or_else(|| Either::Left(PerNs::none()));; | 489 | .unwrap_or_else(|| Either::Left(PerNs::none())); |
515 | let from_extern_prelude = | 490 | let from_extern_prelude = |
516 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | 491 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); |
517 | let from_prelude = self.resolve_in_prelude(db, name); | 492 | let from_prelude = self.resolve_in_prelude(db, name); |
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 3bfef799d..99110d58d 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -138,15 +138,35 @@ where | |||
138 | } | 138 | } |
139 | } | 139 | } |
140 | 140 | ||
141 | fn define_macro(&mut self, name: Name, macro_id: MacroDefId, export: bool) { | 141 | fn define_macro( |
142 | &mut self, | ||
143 | module_id: CrateModuleId, | ||
144 | name: Name, | ||
145 | macro_id: MacroDefId, | ||
146 | export: bool, | ||
147 | ) { | ||
148 | // macro-by-example in Rust have completely weird name resolution logic, | ||
149 | // unlike anything else in the language. We'd don't fully implement yet, | ||
150 | // just give a somewhat precise approximation. | ||
151 | // | ||
152 | // Specifically, we store a set of visible macros in each module, just | ||
153 | // like how we do with usual items. This is wrong, however, because | ||
154 | // macros can be shadowed and their scopes are mostly unrelated to | ||
155 | // modules. To paper over the second problem, we also maintain | ||
156 | // `global_macro_scope` which works when we construct `CrateDefMap`, but | ||
157 | // is completely ignored in expressions. | ||
158 | // | ||
159 | // What we should do is that, in CrateDefMap, we should maintain a | ||
160 | // separate tower of macro scopes, with ids. Then, for each item in the | ||
161 | // module, we need to store it's macro scope. | ||
162 | let def = Either::Right(MacroDef { id: macro_id }); | ||
163 | |||
164 | // In Rust, `#[macro_export]` macros are unconditionally visible at the | ||
165 | // crate root, even if the parent modules is **not** visible. | ||
142 | if export { | 166 | if export { |
143 | self.def_map.public_macros.insert(name.clone(), macro_id); | 167 | self.update(self.def_map.root, None, &[(name.clone(), def.clone())]); |
144 | |||
145 | let def = Either::Right(MacroDef { id: macro_id }); | ||
146 | self.update(self.def_map.root, None, &[(name.clone(), def)]); | ||
147 | } else { | ||
148 | self.def_map.local_macros.insert(name.clone(), macro_id); | ||
149 | } | 168 | } |
169 | self.update(module_id, None, &[(name.clone(), def)]); | ||
150 | self.global_macro_scope.insert(name, macro_id); | 170 | self.global_macro_scope.insert(name, macro_id); |
151 | } | 171 | } |
152 | 172 | ||
@@ -589,7 +609,7 @@ where | |||
589 | if is_macro_rules(&mac.path) { | 609 | if is_macro_rules(&mac.path) { |
590 | if let Some(name) = &mac.name { | 610 | if let Some(name) = &mac.name { |
591 | let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); | 611 | let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); |
592 | self.def_collector.define_macro(name.clone(), macro_id, mac.export) | 612 | self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export) |
593 | } | 613 | } |
594 | return; | 614 | return; |
595 | } | 615 | } |
@@ -694,9 +714,7 @@ mod tests { | |||
694 | prelude: None, | 714 | prelude: None, |
695 | root, | 715 | root, |
696 | modules, | 716 | modules, |
697 | public_macros: FxHashMap::default(), | ||
698 | poison_macros: FxHashSet::default(), | 717 | poison_macros: FxHashSet::default(), |
699 | local_macros: FxHashMap::default(), | ||
700 | diagnostics: Vec::new(), | 718 | diagnostics: Vec::new(), |
701 | } | 719 | } |
702 | }; | 720 | }; |
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index 42241aeff..4e04740eb 100644 --- a/crates/ra_hir/src/nameres/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||
@@ -21,6 +21,7 @@ fn macro_rules_are_globally_visible() { | |||
21 | ⋮crate | 21 | ⋮crate |
22 | ⋮Foo: t v | 22 | ⋮Foo: t v |
23 | ⋮nested: t | 23 | ⋮nested: t |
24 | ⋮structs: m | ||
24 | ⋮ | 25 | ⋮ |
25 | ⋮crate::nested | 26 | ⋮crate::nested |
26 | ⋮Bar: t v | 27 | ⋮Bar: t v |
@@ -46,6 +47,7 @@ fn macro_rules_can_define_modules() { | |||
46 | ); | 47 | ); |
47 | assert_snapshot_matches!(map, @r###" | 48 | assert_snapshot_matches!(map, @r###" |
48 | ⋮crate | 49 | ⋮crate |
50 | ⋮m: m | ||
49 | ⋮n1: t | 51 | ⋮n1: t |
50 | ⋮ | 52 | ⋮ |
51 | ⋮crate::n1 | 53 | ⋮crate::n1 |
@@ -127,8 +129,11 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() { | |||
127 | "foo": ("/lib.rs", []), | 129 | "foo": ("/lib.rs", []), |
128 | }, | 130 | }, |
129 | ); | 131 | ); |
130 | assert_snapshot_matches!(map, @r###"crate | 132 | assert_snapshot_matches!(map, @r###" |
131 | Foo: t v | 133 | ⋮crate |
132 | bar: m | 134 | ⋮Foo: t v |
133 | foo: m"###); | 135 | ⋮bar: m |
136 | ⋮baz: m | ||
137 | ⋮foo: m | ||
138 | "###); | ||
134 | } | 139 | } |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 347bcf27d..1b987c1b6 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -2,11 +2,11 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use rustc_hash::{FxHashMap, FxHashSet}; | 4 | use rustc_hash::{FxHashMap, FxHashSet}; |
5 | use either::Either; | ||
5 | 6 | ||
6 | use crate::{ | 7 | use crate::{ |
7 | ModuleDef, Trait, | 8 | ModuleDef, Trait, MacroDef, |
8 | code_model::Crate, | 9 | code_model::Crate, |
9 | MacroDefId, | ||
10 | db::HirDatabase, | 10 | db::HirDatabase, |
11 | name::{Name, KnownName}, | 11 | name::{Name, KnownName}, |
12 | nameres::{PerNs, CrateDefMap, CrateModuleId}, | 12 | nameres::{PerNs, CrateDefMap, CrateModuleId}, |
@@ -130,13 +130,16 @@ impl Resolver { | |||
130 | resolution | 130 | resolution |
131 | } | 131 | } |
132 | 132 | ||
133 | pub(crate) fn resolve_macro_call( | 133 | pub(crate) fn resolve_path_as_macro( |
134 | &self, | 134 | &self, |
135 | db: &impl HirDatabase, | 135 | db: &impl HirDatabase, |
136 | path: Option<Path>, | 136 | path: &Path, |
137 | ) -> Option<MacroDefId> { | 137 | ) -> Option<MacroDef> { |
138 | let m = self.module()?; | 138 | let (item_map, module) = self.module()?; |
139 | m.0.find_macro(db, m.1, &path?) | 139 | match item_map.resolve_path_with_macro(db, module, path) { |
140 | (Either::Right(macro_def), None) => Some(macro_def), | ||
141 | _ => None, | ||
142 | } | ||
140 | } | 143 | } |
141 | 144 | ||
142 | /// Returns the resolved path segments | 145 | /// Returns the resolved path segments |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 63ec59314..876ebe0e3 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -267,9 +267,8 @@ impl SourceAnalyzer { | |||
267 | db: &impl HirDatabase, | 267 | db: &impl HirDatabase, |
268 | macro_call: &ast::MacroCall, | 268 | macro_call: &ast::MacroCall, |
269 | ) -> Option<MacroDef> { | 269 | ) -> Option<MacroDef> { |
270 | let id = | 270 | let path = macro_call.path().and_then(Path::from_ast)?; |
271 | self.resolver.resolve_macro_call(db, macro_call.path().and_then(Path::from_ast))?; | 271 | self.resolver.resolve_path_as_macro(db, &path) |
272 | Some(MacroDef { id }) | ||
273 | } | 272 | } |
274 | 273 | ||
275 | pub fn resolve_hir_path( | 274 | pub fn resolve_hir_path( |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index c34e89af7..54b2a8c16 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2481,8 +2481,10 @@ fn main() { | |||
2481 | } | 2481 | } |
2482 | "#), | 2482 | "#), |
2483 | @r###" | 2483 | @r###" |
2484 | [156; 182) '{ ...,2); }': () | 2484 | ⋮ |
2485 | [166; 167) 'x': Foo"### | 2485 | ⋮[156; 182) '{ ...,2); }': () |
2486 | ⋮[166; 167) 'x': Foo | ||
2487 | "### | ||
2486 | ); | 2488 | ); |
2487 | } | 2489 | } |
2488 | 2490 | ||