aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/collector.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-03-26 10:09:39 +0000
committerAleksey Kladov <[email protected]>2019-03-26 10:20:54 +0000
commit5270bca5f72fa65f0515be776e06d3d6a4d1efca (patch)
treefa1b8b8ac66713ba29b676e1c2fdd4c4357f24ff /crates/ra_hir/src/nameres/collector.rs
parentdc94f3612583c5e960b334761ad0c18d328840ea (diff)
store macro def inside macro id
This solves the problem of "macro expansion can't call into name resolution, because name resolution calls back into macro expansion" Because we store macro def as a part of call id, macro expansion just knows the def!
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs93
1 files changed, 31 insertions, 62 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 8830b4624..89300d2ec 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -6,15 +6,15 @@ use ra_db::FileId;
6 6
7use crate::{ 7use crate::{
8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, 8 Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
9 DefDatabase, HirFileId, Name, Path, Crate, 9 DefDatabase, HirFileId, Name, Path,
10 KnownName, 10 KnownName,
11 nameres::{ 11 nameres::{
12 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, 12 Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
13 CrateDefMap, CrateModuleId, ModuleData, CrateMacroId, 13 CrateDefMap, CrateModuleId, ModuleData,
14 diagnostics::DefDiagnostic, 14 diagnostics::DefDiagnostic,
15 raw, 15 raw,
16 }, 16 },
17 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, 17 ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId, MacroDefId},
18}; 18};
19 19
20pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 20pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -51,8 +51,8 @@ struct DefCollector<DB> {
51 def_map: CrateDefMap, 51 def_map: CrateDefMap,
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, SourceItemId, Path)>,
55 global_macro_scope: FxHashMap<Name, CrateMacroId>, 55 global_macro_scope: FxHashMap<Name, MacroDefId>,
56} 56}
57 57
58impl<'a, DB> DefCollector<&'a DB> 58impl<'a, DB> DefCollector<&'a DB>
@@ -62,7 +62,7 @@ where
62 fn collect(&mut self) { 62 fn collect(&mut self) {
63 let crate_graph = self.db.crate_graph(); 63 let crate_graph = self.db.crate_graph();
64 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id()); 64 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
65 let raw_items = self.db.raw_items(file_id); 65 let raw_items = self.db.raw_items(file_id.into());
66 let module_id = self.def_map.root; 66 let module_id = self.def_map.root;
67 self.def_map.modules[module_id].definition = Some(file_id); 67 self.def_map.modules[module_id].definition = Some(file_id);
68 ModCollector { 68 ModCollector {
@@ -93,14 +93,11 @@ where
93 } 93 }
94 } 94 }
95 95
96 fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { 96 fn define_macro(&mut self, name: Name, macro_id: MacroDefId, export: bool) {
97 if let Ok(rules) = mbe::MacroRules::parse(tt) { 97 if export {
98 let macro_id = self.def_map.macros.alloc(rules); 98 self.def_map.public_macros.insert(name.clone(), macro_id);
99 if export {
100 self.def_map.public_macros.insert(name.clone(), macro_id);
101 }
102 self.global_macro_scope.insert(name, macro_id);
103 } 99 }
100 self.global_macro_scope.insert(name, macro_id);
104 } 101 }
105 102
106 fn resolve_imports(&mut self) -> ReachedFixedPoint { 103 fn resolve_imports(&mut self) -> ReachedFixedPoint {
@@ -296,7 +293,7 @@ where
296 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); 293 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
297 let mut resolved = Vec::new(); 294 let mut resolved = Vec::new();
298 let mut res = ReachedFixedPoint::Yes; 295 let mut res = ReachedFixedPoint::Yes;
299 macros.retain(|(module_id, call_id, path, tt)| { 296 macros.retain(|(module_id, source_item_id, path)| {
300 if path.segments.len() != 2 { 297 if path.segments.len() != 2 {
301 return true; 298 return true;
302 } 299 }
@@ -312,47 +309,24 @@ where
312 res = ReachedFixedPoint::No; 309 res = ReachedFixedPoint::No;
313 let def_map = self.db.crate_def_map(krate); 310 let def_map = self.db.crate_def_map(krate);
314 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { 311 if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
315 resolved.push((*module_id, *call_id, (krate, macro_id), tt.clone())); 312 let call_id =
313 MacroCallLoc { def: macro_id, source_item_id: *source_item_id }.id(self.db);
314 resolved.push((*module_id, call_id));
316 } 315 }
317 false 316 false
318 }); 317 });
319 318
320 for (module_id, macro_call_id, macro_def_id, arg) in resolved { 319 for (module_id, macro_call_id) in resolved {
321 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id, arg); 320 self.collect_macro_expansion(module_id, macro_call_id);
322 } 321 }
323 res 322 res
324 } 323 }
325 324
326 fn collect_macro_expansion( 325 fn collect_macro_expansion(&mut self, module_id: CrateModuleId, macro_call_id: MacroCallId) {
327 &mut self, 326 let file_id: HirFileId = macro_call_id.into();
328 module_id: CrateModuleId, 327 let raw_items = self.db.raw_items(file_id);
329 macro_call_id: MacroCallId, 328 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
330 macro_def_id: (Crate, CrateMacroId), 329 .collect(raw_items.items())
331 macro_arg: tt::Subtree,
332 ) {
333 let (macro_krate, macro_id) = macro_def_id;
334 let dm;
335 let rules = if macro_krate == self.def_map.krate {
336 &self.def_map[macro_id]
337 } else {
338 dm = self.db.crate_def_map(macro_krate);
339 &dm[macro_id]
340 };
341 if let Ok(expansion) = rules.expand(&macro_arg) {
342 self.def_map.macro_resolutions.insert(macro_call_id, macro_def_id);
343 // XXX: this **does not** go through a database, because we can't
344 // identify macro_call without adding the whole state of name resolution
345 // as a parameter to the query.
346 //
347 // So, we run the queries "manually" and we must ensure that
348 // `db.hir_parse(macro_call_id)` returns the same source_file.
349 let file_id: HirFileId = macro_call_id.into();
350 let source_file = mbe::token_tree_to_ast_item_list(&expansion);
351
352 let raw_items = raw::RawItems::from_source_file(&source_file, file_id);
353 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
354 .collect(raw_items.items())
355 }
356 } 330 }
357 331
358 fn finish(self) -> CrateDefMap { 332 fn finish(self) -> CrateDefMap {
@@ -412,7 +386,7 @@ where
412 Ok(file_id) => { 386 Ok(file_id) => {
413 let module_id = 387 let module_id =
414 self.push_child_module(name.clone(), source_item_id, Some(file_id)); 388 self.push_child_module(name.clone(), source_item_id, Some(file_id));
415 let raw_items = self.def_collector.db.raw_items(file_id); 389 let raw_items = self.def_collector.db.raw_items(file_id.into());
416 ModCollector { 390 ModCollector {
417 def_collector: &mut *self.def_collector, 391 def_collector: &mut *self.def_collector,
418 module_id, 392 module_id,
@@ -484,38 +458,33 @@ where
484 // Case 1: macro rules, define a macro in crate-global mutable scope 458 // Case 1: macro rules, define a macro in crate-global mutable scope
485 if is_macro_rules(&mac.path) { 459 if is_macro_rules(&mac.path) {
486 if let Some(name) = &mac.name { 460 if let Some(name) = &mac.name {
487 self.def_collector.define_macro(name.clone(), &mac.arg, mac.export) 461 let macro_id = MacroDefId::MacroByExample {
462 source_item_id: mac.source_item_id.with_file_id(self.file_id),
463 };
464 self.def_collector.define_macro(name.clone(), macro_id, mac.export)
488 } 465 }
489 return; 466 return;
490 } 467 }
491 468
492 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id }; 469 let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id };
493 let macro_call_id = MacroCallLoc {
494 module: Module { krate: self.def_collector.def_map.krate, module_id: self.module_id },
495 source_item_id,
496 }
497 .id(self.def_collector.db);
498 470
499 // Case 2: try to expand macro_rules from this crate, triggering 471 // Case 2: try to expand macro_rules from this crate, triggering
500 // recursive item collection. 472 // recursive item collection.
501 if let Some(&macro_id) = 473 if let Some(&macro_id) =
502 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) 474 mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
503 { 475 {
504 self.def_collector.collect_macro_expansion( 476 let macro_call_id =
505 self.module_id, 477 MacroCallLoc { def: macro_id, source_item_id }.id(self.def_collector.db);
506 macro_call_id, 478
507 (self.def_collector.def_map.krate, macro_id), 479 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
508 mac.arg.clone(),
509 );
510 return; 480 return;
511 } 481 }
512 482
513 // Case 3: path to a macro from another crate, expand during name resolution 483 // Case 3: path to a macro from another crate, expand during name resolution
514 self.def_collector.unexpanded_macros.push(( 484 self.def_collector.unexpanded_macros.push((
515 self.module_id, 485 self.module_id,
516 macro_call_id, 486 source_item_id,
517 mac.path.clone(), 487 mac.path.clone(),
518 mac.arg.clone(),
519 )) 488 ))
520 } 489 }
521} 490}