aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs77
1 files changed, 41 insertions, 36 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index cef2dc9d2..b5fe16bfa 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -7,14 +7,13 @@ use rustc_hash::FxHashMap;
7use test_utils::tested_by; 7use test_utils::tested_by;
8 8
9use crate::{ 9use crate::{
10 attr::Attr,
10 db::DefDatabase, 11 db::DefDatabase,
11 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 12 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
12 name::MACRO_RULES, 13 name::MACRO_RULES,
13 nameres::{ 14 nameres::{
14 diagnostics::DefDiagnostic, 15 diagnostics::DefDiagnostic, mod_resolution::ModDir, raw, Crate, CrateDefMap, CrateModuleId,
15 mod_resolution::{resolve_submodule, ParentModule}, 16 ModuleData, ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode,
16 raw, Crate, CrateDefMap, CrateModuleId, ModuleData, ModuleDef, PerNs, ReachedFixedPoint,
17 Resolution, ResolveMode,
18 }, 17 },
19 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static, 18 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
20 Struct, Trait, TypeAlias, Union, 19 Struct, Trait, TypeAlias, Union,
@@ -45,6 +44,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
45 glob_imports: FxHashMap::default(), 44 glob_imports: FxHashMap::default(),
46 unresolved_imports: Vec::new(), 45 unresolved_imports: Vec::new(),
47 unexpanded_macros: Vec::new(), 46 unexpanded_macros: Vec::new(),
47 mod_dirs: FxHashMap::default(),
48 macro_stack_monitor: MacroStackMonitor::default(), 48 macro_stack_monitor: MacroStackMonitor::default(),
49 cfg_options, 49 cfg_options,
50 }; 50 };
@@ -87,6 +87,7 @@ struct DefCollector<'a, DB> {
87 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 87 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
88 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 88 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
89 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>, 89 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
90 mod_dirs: FxHashMap<CrateModuleId, ModDir>,
90 91
91 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 92 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
92 /// To prevent stack overflow, we add a deep counter here for prevent that. 93 /// To prevent stack overflow, we add a deep counter here for prevent that.
@@ -107,11 +108,10 @@ where
107 self.def_map.modules[module_id].definition = Some(file_id); 108 self.def_map.modules[module_id].definition = Some(file_id);
108 ModCollector { 109 ModCollector {
109 def_collector: &mut *self, 110 def_collector: &mut *self,
110 attr_path: None,
111 module_id, 111 module_id,
112 file_id: file_id.into(), 112 file_id: file_id.into(),
113 raw_items: &raw_items, 113 raw_items: &raw_items,
114 parent_module: None, 114 mod_dir: ModDir::root(),
115 } 115 }
116 .collect(raw_items.items()); 116 .collect(raw_items.items());
117 117
@@ -481,13 +481,13 @@ where
481 if !self.macro_stack_monitor.is_poison(macro_def_id) { 481 if !self.macro_stack_monitor.is_poison(macro_def_id) {
482 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); 482 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
483 let raw_items = self.db.raw_items(file_id); 483 let raw_items = self.db.raw_items(file_id);
484 let mod_dir = self.mod_dirs[&module_id].clone();
484 ModCollector { 485 ModCollector {
485 def_collector: &mut *self, 486 def_collector: &mut *self,
486 file_id, 487 file_id,
487 attr_path: None,
488 module_id, 488 module_id,
489 raw_items: &raw_items, 489 raw_items: &raw_items,
490 parent_module: None, 490 mod_dir,
491 } 491 }
492 .collect(raw_items.items()); 492 .collect(raw_items.items());
493 } else { 493 } else {
@@ -508,9 +508,8 @@ struct ModCollector<'a, D> {
508 def_collector: D, 508 def_collector: D,
509 module_id: CrateModuleId, 509 module_id: CrateModuleId,
510 file_id: HirFileId, 510 file_id: HirFileId,
511 attr_path: Option<&'a SmolStr>,
512 raw_items: &'a raw::RawItems, 511 raw_items: &'a raw::RawItems,
513 parent_module: Option<ParentModule<'a>>, 512 mod_dir: ModDir,
514} 513}
515 514
516impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> 515impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
@@ -518,6 +517,10 @@ where
518 DB: DefDatabase, 517 DB: DefDatabase,
519{ 518{
520 fn collect(&mut self, items: &[raw::RawItem]) { 519 fn collect(&mut self, items: &[raw::RawItem]) {
520 // Note: don't assert that inserted value is fresh: it's simply not true
521 // for macros.
522 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
523
521 // Prelude module is always considered to be `#[macro_use]`. 524 // Prelude module is always considered to be `#[macro_use]`.
522 if let Some(prelude_module) = self.def_collector.def_map.prelude { 525 if let Some(prelude_module) = self.def_collector.def_map.prelude {
523 if prelude_module.krate != self.def_collector.def_map.krate { 526 if prelude_module.krate != self.def_collector.def_map.krate {
@@ -530,7 +533,7 @@ where
530 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 533 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
531 // any other items. 534 // any other items.
532 for item in items { 535 for item in items {
533 if self.is_cfg_enabled(&item.attrs) { 536 if self.is_cfg_enabled(item.attrs()) {
534 if let raw::RawItemKind::Import(import_id) = item.kind { 537 if let raw::RawItemKind::Import(import_id) = item.kind {
535 let import = self.raw_items[import_id].clone(); 538 let import = self.raw_items[import_id].clone();
536 if import.is_extern_crate && import.is_macro_use { 539 if import.is_extern_crate && import.is_macro_use {
@@ -541,9 +544,11 @@ where
541 } 544 }
542 545
543 for item in items { 546 for item in items {
544 if self.is_cfg_enabled(&item.attrs) { 547 if self.is_cfg_enabled(item.attrs()) {
545 match item.kind { 548 match item.kind {
546 raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), 549 raw::RawItemKind::Module(m) => {
550 self.collect_module(&self.raw_items[m], item.attrs())
551 }
547 raw::RawItemKind::Import(import_id) => self 552 raw::RawItemKind::Import(import_id) => self
548 .def_collector 553 .def_collector
549 .unresolved_imports 554 .unresolved_imports
@@ -555,53 +560,48 @@ where
555 } 560 }
556 } 561 }
557 562
558 fn collect_module(&mut self, module: &raw::ModuleData) { 563 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) {
564 let path_attr = self.path_attr(attrs);
565 let is_macro_use = self.is_macro_use(attrs);
559 match module { 566 match module {
560 // inline module, just recurse 567 // inline module, just recurse
561 raw::ModuleData::Definition { name, items, ast_id, attr_path, is_macro_use } => { 568 raw::ModuleData::Definition { name, items, ast_id } => {
562 let module_id = 569 let module_id =
563 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); 570 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
564 let parent_module = ParentModule { name, attr_path: attr_path.as_ref() };
565 571
566 ModCollector { 572 ModCollector {
567 def_collector: &mut *self.def_collector, 573 def_collector: &mut *self.def_collector,
568 module_id, 574 module_id,
569 attr_path: attr_path.as_ref(),
570 file_id: self.file_id, 575 file_id: self.file_id,
571 raw_items: self.raw_items, 576 raw_items: self.raw_items,
572 parent_module: Some(parent_module), 577 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
573 } 578 }
574 .collect(&*items); 579 .collect(&*items);
575 if *is_macro_use { 580 if is_macro_use {
576 self.import_all_legacy_macros(module_id); 581 self.import_all_legacy_macros(module_id);
577 } 582 }
578 } 583 }
579 // out of line module, resolve, parse and recurse 584 // out of line module, resolve, parse and recurse
580 raw::ModuleData::Declaration { name, ast_id, attr_path, is_macro_use } => { 585 raw::ModuleData::Declaration { name, ast_id } => {
581 let ast_id = ast_id.with_file_id(self.file_id); 586 let ast_id = ast_id.with_file_id(self.file_id);
582 let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none(); 587 match self.mod_dir.resolve_declaration(
583 match resolve_submodule(
584 self.def_collector.db, 588 self.def_collector.db,
585 self.file_id, 589 self.file_id,
586 self.attr_path,
587 name, 590 name,
588 is_root, 591 path_attr,
589 attr_path.as_ref(),
590 self.parent_module,
591 ) { 592 ) {
592 Ok(file_id) => { 593 Ok((file_id, mod_dir)) => {
593 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 594 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
594 let raw_items = self.def_collector.db.raw_items(file_id.into()); 595 let raw_items = self.def_collector.db.raw_items(file_id.into());
595 ModCollector { 596 ModCollector {
596 def_collector: &mut *self.def_collector, 597 def_collector: &mut *self.def_collector,
597 module_id, 598 module_id,
598 attr_path: attr_path.as_ref(),
599 file_id: file_id.into(), 599 file_id: file_id.into(),
600 raw_items: &raw_items, 600 raw_items: &raw_items,
601 parent_module: None, 601 mod_dir,
602 } 602 }
603 .collect(raw_items.items()); 603 .collect(raw_items.items());
604 if *is_macro_use { 604 if is_macro_use {
605 self.import_all_legacy_macros(module_id); 605 self.import_all_legacy_macros(module_id);
606 } 606 }
607 } 607 }
@@ -714,12 +714,16 @@ where
714 } 714 }
715 } 715 }
716 716
717 fn is_cfg_enabled(&self, attrs: &raw::Attrs) -> bool { 717 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool {
718 attrs.as_ref().map_or(true, |attrs| { 718 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
719 attrs 719 }
720 .iter() 720
721 .all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) 721 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> {
722 }) 722 attrs.iter().find_map(|attr| attr.as_path())
723 }
724
725 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
726 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
723 } 727 }
724} 728}
725 729
@@ -747,6 +751,7 @@ mod tests {
747 glob_imports: FxHashMap::default(), 751 glob_imports: FxHashMap::default(),
748 unresolved_imports: Vec::new(), 752 unresolved_imports: Vec::new(),
749 unexpanded_macros: Vec::new(), 753 unexpanded_macros: Vec::new(),
754 mod_dirs: FxHashMap::default(),
750 macro_stack_monitor: monitor, 755 macro_stack_monitor: monitor,
751 cfg_options: &CfgOptions::default(), 756 cfg_options: &CfgOptions::default(),
752 }; 757 };