aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/collector.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-03-26 11:19:38 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-03-26 11:19:38 +0000
commit8254244e4970b085809d42a34282649b4a4e16a2 (patch)
tree380b2c4835bd7ad75a66d26cab8e25e0be801182 /crates/ra_hir/src/nameres/collector.rs
parent71f8619b4e614aa9c61be6b2851498050e7f63ae (diff)
parente231277ab2f1ebb3040457e89b92540e599dbb3e (diff)
Merge #1055
1055: store macro def inside macro id r=matklad a=matklad This makes macro expansion resilient to changes to code inside the macro Co-authored-by: Aleksey Kladov <[email protected]>
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}