diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/collector.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 77 |
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; | |||
7 | use test_utils::tested_by; | 7 | use test_utils::tested_by; |
8 | 8 | ||
9 | use crate::{ | 9 | use 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 | ||
516 | impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>> | 515 | impl<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 | }; |