diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index f2336c271..9992e054d 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -6,13 +6,13 @@ use ra_db::FileId; | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | 8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, |
9 | PersistentHirDatabase, HirFileId, Name, Path, Problem, | 9 | PersistentHirDatabase, HirFileId, Name, Path, Problem, Crate, |
10 | KnownName, | 10 | KnownName, |
11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, | 11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, |
12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, | 12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use super::{CrateDefMap, CrateModuleId, ModuleData}; | 15 | use super::{CrateDefMap, CrateModuleId, ModuleData, CrateMacroId}; |
16 | 16 | ||
17 | pub(super) fn collect_defs( | 17 | pub(super) fn collect_defs( |
18 | db: &impl PersistentHirDatabase, | 18 | db: &impl PersistentHirDatabase, |
@@ -52,7 +52,7 @@ struct DefCollector<DB> { | |||
52 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, | 52 | glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, |
53 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, | 53 | unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, |
54 | unexpanded_macros: Vec<(CrateModuleId, MacroCallId, Path, tt::Subtree)>, | 54 | unexpanded_macros: Vec<(CrateModuleId, MacroCallId, Path, tt::Subtree)>, |
55 | global_macro_scope: FxHashMap<Name, mbe::MacroRules>, | 55 | global_macro_scope: FxHashMap<Name, CrateMacroId>, |
56 | } | 56 | } |
57 | 57 | ||
58 | impl<'a, DB> DefCollector<&'a DB> | 58 | impl<'a, DB> DefCollector<&'a DB> |
@@ -95,10 +95,11 @@ where | |||
95 | 95 | ||
96 | fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { | 96 | fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { |
97 | if let Ok(rules) = mbe::MacroRules::parse(tt) { | 97 | if let Ok(rules) = mbe::MacroRules::parse(tt) { |
98 | let macro_id = self.def_map.macros.alloc(rules); | ||
98 | if export { | 99 | if export { |
99 | self.def_map.public_macros.insert(name.clone(), rules.clone()); | 100 | self.def_map.public_macros.insert(name.clone(), macro_id); |
100 | } | 101 | } |
101 | self.global_macro_scope.insert(name, rules); | 102 | self.global_macro_scope.insert(name, macro_id); |
102 | } | 103 | } |
103 | } | 104 | } |
104 | 105 | ||
@@ -295,6 +296,7 @@ where | |||
295 | fn resolve_macros(&mut self) -> ReachedFixedPoint { | 296 | fn resolve_macros(&mut self) -> ReachedFixedPoint { |
296 | let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); | 297 | let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); |
297 | let mut resolved = Vec::new(); | 298 | let mut resolved = Vec::new(); |
299 | let mut res = ReachedFixedPoint::Yes; | ||
298 | macros.retain(|(module_id, call_id, path, tt)| { | 300 | macros.retain(|(module_id, call_id, path, tt)| { |
299 | if path.segments.len() != 2 { | 301 | if path.segments.len() != 2 { |
300 | return true; | 302 | return true; |
@@ -308,19 +310,16 @@ where | |||
308 | Some(it) => it, | 310 | Some(it) => it, |
309 | _ => return true, | 311 | _ => return true, |
310 | }; | 312 | }; |
313 | res = ReachedFixedPoint::No; | ||
311 | let def_map = self.db.crate_def_map(krate); | 314 | let def_map = self.db.crate_def_map(krate); |
312 | let rules = def_map.public_macros.get(&path.segments[1].name).cloned(); | 315 | if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { |
313 | resolved.push((*module_id, *call_id, rules, tt.clone())); | 316 | resolved.push((*module_id, *call_id, (krate, macro_id), tt.clone())); |
317 | } | ||
314 | false | 318 | false |
315 | }); | 319 | }); |
316 | let res = if resolved.is_empty() { ReachedFixedPoint::Yes } else { ReachedFixedPoint::No }; | ||
317 | 320 | ||
318 | for (module_id, macro_call_id, rules, arg) in resolved { | 321 | for (module_id, macro_call_id, macro_def_id, arg) in resolved { |
319 | if let Some(rules) = rules { | 322 | self.collect_macro_expansion(module_id, macro_call_id, macro_def_id, arg); |
320 | if let Ok(tt) = rules.expand(&arg) { | ||
321 | self.collect_macro_expansion(module_id, macro_call_id, tt); | ||
322 | } | ||
323 | } | ||
324 | } | 323 | } |
325 | res | 324 | res |
326 | } | 325 | } |
@@ -329,20 +328,32 @@ where | |||
329 | &mut self, | 328 | &mut self, |
330 | module_id: CrateModuleId, | 329 | module_id: CrateModuleId, |
331 | macro_call_id: MacroCallId, | 330 | macro_call_id: MacroCallId, |
332 | expansion: tt::Subtree, | 331 | macro_def_id: (Crate, CrateMacroId), |
332 | macro_arg: tt::Subtree, | ||
333 | ) { | 333 | ) { |
334 | // XXX: this **does not** go through a database, because we can't | 334 | let (macro_krate, macro_id) = macro_def_id; |
335 | // identify macro_call without adding the whole state of name resolution | 335 | let dm; |
336 | // as a parameter to the query. | 336 | let rules = if macro_krate == self.def_map.krate { |
337 | // | 337 | &self.def_map[macro_id] |
338 | // So, we run the queries "manually" and we must ensure that | 338 | } else { |
339 | // `db.hir_parse(macro_call_id)` returns the same source_file. | 339 | dm = self.db.crate_def_map(macro_krate); |
340 | let file_id: HirFileId = macro_call_id.into(); | 340 | &dm[macro_id] |
341 | let source_file = mbe::token_tree_to_ast_item_list(&expansion); | 341 | }; |
342 | 342 | if let Ok(expansion) = rules.expand(¯o_arg) { | |
343 | let raw_items = raw::RawItems::from_source_file(&source_file, file_id); | 343 | self.def_map.macro_resolutions.insert(macro_call_id, macro_def_id); |
344 | ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } | 344 | // XXX: this **does not** go through a database, because we can't |
345 | .collect(raw_items.items()) | 345 | // identify macro_call without adding the whole state of name resolution |
346 | // as a parameter to the query. | ||
347 | // | ||
348 | // So, we run the queries "manually" and we must ensure that | ||
349 | // `db.hir_parse(macro_call_id)` returns the same source_file. | ||
350 | let file_id: HirFileId = macro_call_id.into(); | ||
351 | let source_file = mbe::token_tree_to_ast_item_list(&expansion); | ||
352 | |||
353 | let raw_items = raw::RawItems::from_source_file(&source_file, file_id); | ||
354 | ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } | ||
355 | .collect(raw_items.items()) | ||
356 | } | ||
346 | } | 357 | } |
347 | 358 | ||
348 | fn finish(self) -> CrateDefMap { | 359 | fn finish(self) -> CrateDefMap { |
@@ -486,12 +497,15 @@ where | |||
486 | 497 | ||
487 | // Case 2: try to expand macro_rules from this crate, triggering | 498 | // Case 2: try to expand macro_rules from this crate, triggering |
488 | // recursive item collection. | 499 | // recursive item collection. |
489 | if let Some(rules) = | 500 | if let Some(¯o_id) = |
490 | mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) | 501 | mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) |
491 | { | 502 | { |
492 | if let Ok(tt) = rules.expand(&mac.arg) { | 503 | self.def_collector.collect_macro_expansion( |
493 | self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, tt); | 504 | self.module_id, |
494 | } | 505 | macro_call_id, |
506 | (self.def_collector.def_map.krate, macro_id), | ||
507 | mac.arg.clone(), | ||
508 | ); | ||
495 | return; | 509 | return; |
496 | } | 510 | } |
497 | 511 | ||