diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 93 |
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 | ||
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 | 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 | ||
20 | pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 20 | pub(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 | ||
58 | impl<'a, DB> DefCollector<&'a DB> | 58 | impl<'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(¯o_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(¯o_id) = | 473 | if let Some(¯o_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 | } |