aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs77
-rw-r--r--crates/ra_hir/src/nameres/mod_resolution.rs228
-rw-r--r--crates/ra_hir/src/nameres/raw.rs53
-rw-r--r--crates/ra_hir/src/nameres/tests.rs13
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs2
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs29
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs214
7 files changed, 262 insertions, 354 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 };
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs
index 3aa32bd66..e8b808514 100644
--- a/crates/ra_hir/src/nameres/mod_resolution.rs
+++ b/crates/ra_hir/src/nameres/mod_resolution.rs
@@ -1,187 +1,87 @@
1//! This module resolves `mod foo;` declaration to file. 1//! This module resolves `mod foo;` declaration to file.
2 2use ra_db::FileId;
3use std::{borrow::Cow, sync::Arc};
4
5use ra_db::{FileId, SourceRoot};
6use ra_syntax::SmolStr; 3use ra_syntax::SmolStr;
7use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
8 5
9use crate::{db::DefDatabase, HirFileId, Name}; 6use crate::{db::DefDatabase, HirFileId, Name};
10 7
11#[derive(Clone, Copy)] 8#[derive(Clone, Debug)]
12pub(super) struct ParentModule<'a> { 9pub(super) struct ModDir {
13 pub(super) name: &'a Name, 10 /// `.` for `mod.rs`, `lib.rs`
14 pub(super) attr_path: Option<&'a SmolStr>, 11 /// `./foo` for `foo.rs`
12 /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs`
13 path: RelativePathBuf,
14 /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/`
15 root_non_dir_owner: bool,
15} 16}
16 17
17impl<'a> ParentModule<'a> { 18impl ModDir {
18 fn attribute_path(&self) -> Option<&SmolStr> { 19 pub(super) fn root() -> ModDir {
19 self.attr_path.filter(|p| !p.is_empty()) 20 ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false }
20 } 21 }
21}
22 22
23pub(super) fn resolve_submodule( 23 pub(super) fn descend_into_definition(
24 db: &impl DefDatabase, 24 &self,
25 file_id: HirFileId, 25 name: &Name,
26 mod_attr_path: Option<&SmolStr>, 26 attr_path: Option<&SmolStr>,
27 name: &Name, 27 ) -> ModDir {
28 is_root: bool, 28 let mut path = self.path.clone();
29 attr_path: Option<&SmolStr>, 29 match attr_to_path(attr_path) {
30 parent_module: Option<ParentModule<'_>>, 30 None => path.push(&name.to_string()),
31) -> Result<FileId, RelativePathBuf> { 31 Some(attr_path) => {
32 let file_id = file_id.original_file(db); 32 if self.root_non_dir_owner {
33 let source_root_id = db.file_source_root(file_id); 33 // Workaround for relative path API: turn `lib.rs` into ``.
34 let path = db.file_relative_path(file_id); 34 if !path.pop() {
35 let root = RelativePathBuf::default(); 35 path = RelativePathBuf::default();
36 let dir_path = path.parent().unwrap_or(&root); 36 }
37 let mod_name = path.file_stem().unwrap_or("unknown");
38
39 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
40 (Some(file_path), Some(parent_module)) => {
41 let file_path = normalize_attribute_path(file_path);
42 match parent_module.attribute_path() {
43 Some(parent_module_attr_path) => {
44 let path = dir_path
45 .join(format!(
46 "{}/{}",
47 normalize_attribute_path(parent_module_attr_path),
48 file_path
49 ))
50 .normalize();
51 ResolutionMode::InlineModuleWithAttributePath(
52 InsideInlineModuleMode::WithAttributePath(path),
53 )
54 }
55 None => {
56 let path =
57 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
58 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
59 path,
60 ))
61 } 37 }
38 path.push(attr_path);
62 } 39 }
63 } 40 }
64 (None, Some(parent_module)) => match parent_module.attribute_path() { 41 ModDir { path, root_non_dir_owner: false }
65 Some(parent_module_attr_path) => { 42 }
66 let path = dir_path.join(format!( 43
67 "{}/{}.rs", 44 pub(super) fn resolve_declaration(
68 normalize_attribute_path(parent_module_attr_path), 45 &self,
69 name 46 db: &impl DefDatabase,
70 )); 47 file_id: HirFileId,
71 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path)) 48 name: &Name,
49 attr_path: Option<&SmolStr>,
50 ) -> Result<(FileId, ModDir), RelativePathBuf> {
51 let empty_path = RelativePathBuf::default();
52 let file_id = file_id.original_file(db);
53
54 let mut candidate_files = Vec::new();
55 match attr_to_path(attr_path) {
56 Some(attr_path) => {
57 let base = if self.root_non_dir_owner {
58 self.path.parent().unwrap_or(&empty_path)
59 } else {
60 &self.path
61 };
62 candidate_files.push(base.join(attr_path))
72 } 63 }
73 None => { 64 None => {
74 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name)); 65 candidate_files.push(self.path.join(&format!("{}.rs", name)));
75 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path)) 66 candidate_files.push(self.path.join(&format!("{}/mod.rs", name)));
76 }
77 },
78 (Some(file_path), None) => {
79 let file_path = normalize_attribute_path(file_path);
80 let path = dir_path.join(file_path.as_ref()).normalize();
81 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
82 }
83 (None, None) => {
84 let is_dir_owner = is_root || mod_name == "mod" || mod_attr_path.is_some();
85 if is_dir_owner {
86 let file_mod = dir_path.join(format!("{}.rs", name));
87 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
88 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
89 file: file_mod,
90 directory: dir_mod,
91 })
92 } else {
93 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
94 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
95 } 67 }
96 } 68 };
97 }; 69
98 70 for candidate in candidate_files.iter() {
99 resolve_mode.resolve(db.source_root(source_root_id)) 71 if let Some(file_id) = db.resolve_relative_path(file_id, candidate) {
100} 72 let mut root_non_dir_owner = false;
101 73 let mut mod_path = RelativePathBuf::new();
102fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> { 74 if !(candidate.ends_with("mod.rs") || attr_path.is_some()) {
103 let current_dir = "./"; 75 root_non_dir_owner = true;
104 let windows_path_separator = r#"\"#; 76 mod_path.push(&name.to_string());
105 let current_dir_normalize = if file_path.starts_with(current_dir) {
106 &file_path[current_dir.len()..]
107 } else {
108 file_path.as_str()
109 };
110 if current_dir_normalize.contains(windows_path_separator) {
111 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
112 } else {
113 Cow::Borrowed(current_dir_normalize)
114 }
115}
116
117enum OutOfLineMode {
118 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
119 FileInDirectory(RelativePathBuf),
120 WithAttributePath(RelativePathBuf),
121}
122
123impl OutOfLineMode {
124 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
125 match self {
126 OutOfLineMode::RootOrModRs { file, directory } => {
127 match source_root.file_by_relative_path(file) {
128 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
129 file_id => resolve_find_result(file_id, file),
130 } 77 }
78 return Ok((file_id, ModDir { path: mod_path, root_non_dir_owner }));
131 } 79 }
132 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
133 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
134 } 80 }
81 Err(candidate_files.remove(0))
135 } 82 }
136} 83}
137 84
138enum InsideInlineModuleMode { 85fn attr_to_path(attr: Option<&SmolStr>) -> Option<RelativePathBuf> {
139 File(RelativePathBuf), 86 attr.and_then(|it| RelativePathBuf::from_path(&it.replace("\\", "/")).ok())
140 WithAttributePath(RelativePathBuf),
141}
142
143impl InsideInlineModuleMode {
144 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
145 match self {
146 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
147 InsideInlineModuleMode::WithAttributePath(path) => {
148 resolve_simple_path(source_root, path)
149 }
150 }
151 }
152}
153
154enum ResolutionMode {
155 OutOfLine(OutOfLineMode),
156 InsideInlineModule(InsideInlineModuleMode),
157 InlineModuleWithAttributePath(InsideInlineModuleMode),
158}
159
160impl ResolutionMode {
161 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
162 use self::ResolutionMode::*;
163
164 match self {
165 OutOfLine(mode) => mode.resolve(source_root),
166 InsideInlineModule(mode) => mode.resolve(source_root),
167 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
168 }
169 }
170}
171
172fn resolve_simple_path(
173 source_root: Arc<SourceRoot>,
174 path: &RelativePathBuf,
175) -> Result<FileId, RelativePathBuf> {
176 resolve_find_result(source_root.file_by_relative_path(path), path)
177}
178
179fn resolve_find_result(
180 file_id: Option<FileId>,
181 path: &RelativePathBuf,
182) -> Result<FileId, RelativePathBuf> {
183 match file_id {
184 Some(file_id) => Ok(file_id.clone()),
185 None => Err(path.clone()),
186 }
187} 87}
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 623b343c4..57f2929c3 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -5,7 +5,7 @@ use std::{ops::Index, sync::Arc};
5use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 5use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, AttrsOwner, NameOwner}, 7 ast::{self, AttrsOwner, NameOwner},
8 AstNode, AstPtr, SmolStr, SourceFile, 8 AstNode, AstPtr, SourceFile,
9}; 9};
10use test_utils::tested_by; 10use test_utils::tested_by;
11 11
@@ -121,14 +121,20 @@ impl Index<Macro> for RawItems {
121} 121}
122 122
123// Avoid heap allocation on items without attributes. 123// Avoid heap allocation on items without attributes.
124pub(super) type Attrs = Option<Arc<[Attr]>>; 124type Attrs = Option<Arc<[Attr]>>;
125 125
126#[derive(Debug, PartialEq, Eq, Clone)] 126#[derive(Debug, PartialEq, Eq, Clone)]
127pub(super) struct RawItem { 127pub(super) struct RawItem {
128 pub(super) attrs: Attrs, 128 attrs: Attrs,
129 pub(super) kind: RawItemKind, 129 pub(super) kind: RawItemKind,
130} 130}
131 131
132impl RawItem {
133 pub(super) fn attrs(&self) -> &[Attr] {
134 self.attrs.as_ref().map_or(&[], |it| &*it)
135 }
136}
137
132#[derive(Debug, PartialEq, Eq, Clone, Copy)] 138#[derive(Debug, PartialEq, Eq, Clone, Copy)]
133pub(super) enum RawItemKind { 139pub(super) enum RawItemKind {
134 Module(Module), 140 Module(Module),
@@ -143,19 +149,8 @@ impl_arena_id!(Module);
143 149
144#[derive(Debug, PartialEq, Eq)] 150#[derive(Debug, PartialEq, Eq)]
145pub(super) enum ModuleData { 151pub(super) enum ModuleData {
146 Declaration { 152 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
147 name: Name, 153 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
148 ast_id: FileAstId<ast::Module>,
149 attr_path: Option<SmolStr>,
150 is_macro_use: bool,
151 },
152 Definition {
153 name: Name,
154 ast_id: FileAstId<ast::Module>,
155 items: Vec<RawItem>,
156 attr_path: Option<SmolStr>,
157 is_macro_use: bool,
158 },
159} 154}
160 155
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -286,28 +281,17 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
286 let attrs = self.parse_attrs(&module); 281 let attrs = self.parse_attrs(&module);
287 282
288 let ast_id = self.source_ast_id_map.ast_id(&module); 283 let ast_id = self.source_ast_id_map.ast_id(&module);
289 // FIXME: cfg_attr
290 let is_macro_use = module.has_atom_attr("macro_use");
291 if module.has_semi() { 284 if module.has_semi() {
292 let attr_path = extract_mod_path_attribute(&module); 285 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
293 let item = self.raw_items.modules.alloc(ModuleData::Declaration {
294 name,
295 ast_id,
296 attr_path,
297 is_macro_use,
298 });
299 self.push_item(current_module, attrs, RawItemKind::Module(item)); 286 self.push_item(current_module, attrs, RawItemKind::Module(item));
300 return; 287 return;
301 } 288 }
302 289
303 if let Some(item_list) = module.item_list() { 290 if let Some(item_list) = module.item_list() {
304 let attr_path = extract_mod_path_attribute(&module);
305 let item = self.raw_items.modules.alloc(ModuleData::Definition { 291 let item = self.raw_items.modules.alloc(ModuleData::Definition {
306 name, 292 name,
307 ast_id, 293 ast_id,
308 items: Vec::new(), 294 items: Vec::new(),
309 attr_path,
310 is_macro_use,
311 }); 295 });
312 self.process_module(Some(item), item_list); 296 self.process_module(Some(item), item_list);
313 self.push_item(current_module, attrs, RawItemKind::Module(item)); 297 self.push_item(current_module, attrs, RawItemKind::Module(item));
@@ -417,16 +401,3 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
417 Attr::from_attrs_owner(self.file_id, item, self.db) 401 Attr::from_attrs_owner(self.file_id, item, self.db)
418 } 402 }
419} 403}
420
421fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> {
422 module.attrs().into_iter().find_map(|attr| {
423 attr.as_simple_key_value().and_then(|(name, value)| {
424 let is_path = name == "path";
425 if is_path {
426 Some(value)
427 } else {
428 None
429 }
430 })
431 })
432}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 34dd79574..8c6b40aaf 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -7,7 +7,6 @@ mod mod_resolution;
7use std::sync::Arc; 7use std::sync::Arc;
8 8
9use insta::assert_snapshot; 9use insta::assert_snapshot;
10use ra_cfg::CfgOptions;
11use ra_db::SourceDatabase; 10use ra_db::SourceDatabase;
12use test_utils::covers; 11use test_utils::covers;
13 12
@@ -561,12 +560,12 @@ fn cfg_test() {
561 "#, 560 "#,
562 crate_graph! { 561 crate_graph! {
563 "main": ("/main.rs", ["std"]), 562 "main": ("/main.rs", ["std"]),
564 "std": ("/lib.rs", [], CfgOptions::default() 563 "std": ("/lib.rs", [], cfg = {
565 .atom("test".into()) 564 "test",
566 .key_value("feature".into(), "foo".into()) 565 "feature" = "foo",
567 .key_value("feature".into(), "bar".into()) 566 "feature" = "bar",
568 .key_value("opt".into(), "42".into()) 567 "opt" = "42",
569 ), 568 }),
570 }, 569 },
571 ); 570 );
572 571
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
index c41862a0b..af9c39760 100644
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
@@ -2,7 +2,7 @@ use super::*;
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_db::SourceDatabase; 5use ra_db::{SourceDatabase, SourceDatabaseExt};
6 6
7fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { 7fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) {
8 let (mut db, pos) = MockDatabase::with_position(initial); 8 let (mut db, pos) = MockDatabase::with_position(initial);
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index e4b408394..4f52ad2c5 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -38,21 +38,34 @@ fn macro_rules_can_define_modules() {
38 } 38 }
39 m!(n1); 39 m!(n1);
40 40
41 mod m {
42 m!(n3)
43 }
44
41 //- /n1.rs 45 //- /n1.rs
42 m!(n2) 46 m!(n2)
43 //- /n1/n2.rs 47 //- /n1/n2.rs
44 struct X; 48 struct X;
49 //- /m/n3.rs
50 struct Y;
45 ", 51 ",
46 ); 52 );
47 assert_snapshot!(map, @r###" 53 assert_snapshot!(map, @r###"
48 ⋮crate 54 crate
49 ⋮n1: t 55 m: t
50 56 n1: t
51 ⋮crate::n1 57
52 ⋮n2: t 58 crate::m
53 59 n3: t
54 ⋮crate::n1::n2 60
55 ⋮X: t v 61 crate::m::n3
62 Y: t v
63
64 crate::n1
65 n2: t
66
67 crate::n1::n2
68 X: t v
56 "###); 69 "###);
57} 70}
58 71
diff --git a/crates/ra_hir/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
index e3e6f1e95..f569aacdc 100644
--- a/crates/ra_hir/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
@@ -26,6 +26,33 @@ fn name_res_works_for_broken_modules() {
26} 26}
27 27
28#[test] 28#[test]
29fn nested_module_resolution() {
30 let map = def_map(
31 "
32 //- /lib.rs
33 mod n1;
34
35 //- /n1.rs
36 mod n2;
37
38 //- /n1/n2.rs
39 struct X;
40 ",
41 );
42
43 assert_snapshot!(map, @r###"
44 ⋮crate
45 ⋮n1: t
46
47 ⋮crate::n1
48 ⋮n2: t
49
50 ⋮crate::n1::n2
51 ⋮X: t v
52 "###);
53}
54
55#[test]
29fn module_resolution_works_for_non_standard_filenames() { 56fn module_resolution_works_for_non_standard_filenames() {
30 let map = def_map_with_crate_graph( 57 let map = def_map_with_crate_graph(
31 " 58 "
@@ -53,18 +80,15 @@ fn module_resolution_works_for_non_standard_filenames() {
53 80
54#[test] 81#[test]
55fn module_resolution_works_for_raw_modules() { 82fn module_resolution_works_for_raw_modules() {
56 let map = def_map_with_crate_graph( 83 let map = def_map(
57 " 84 "
58 //- /library.rs 85 //- /lib.rs
59 mod r#async; 86 mod r#async;
60 use self::r#async::Bar; 87 use self::r#async::Bar;
61 88
62 //- /async.rs 89 //- /async.rs
63 pub struct Bar; 90 pub struct Bar;
64 ", 91 ",
65 crate_graph! {
66 "library": ("/library.rs", []),
67 },
68 ); 92 );
69 93
70 assert_snapshot!(map, @r###" 94 assert_snapshot!(map, @r###"
@@ -79,9 +103,9 @@ fn module_resolution_works_for_raw_modules() {
79 103
80#[test] 104#[test]
81fn module_resolution_decl_path() { 105fn module_resolution_decl_path() {
82 let map = def_map_with_crate_graph( 106 let map = def_map(
83 r###" 107 r###"
84 //- /library.rs 108 //- /lib.rs
85 #[path = "bar/baz/foo.rs"] 109 #[path = "bar/baz/foo.rs"]
86 mod foo; 110 mod foo;
87 use self::foo::Bar; 111 use self::foo::Bar;
@@ -89,9 +113,6 @@ fn module_resolution_decl_path() {
89 //- /bar/baz/foo.rs 113 //- /bar/baz/foo.rs
90 pub struct Bar; 114 pub struct Bar;
91 "###, 115 "###,
92 crate_graph! {
93 "library": ("/library.rs", []),
94 },
95 ); 116 );
96 117
97 assert_snapshot!(map, @r###" 118 assert_snapshot!(map, @r###"
@@ -106,7 +127,7 @@ fn module_resolution_decl_path() {
106 127
107#[test] 128#[test]
108fn module_resolution_module_with_path_in_mod_rs() { 129fn module_resolution_module_with_path_in_mod_rs() {
109 let map = def_map_with_crate_graph( 130 let map = def_map(
110 r###" 131 r###"
111 //- /main.rs 132 //- /main.rs
112 mod foo; 133 mod foo;
@@ -120,9 +141,6 @@ fn module_resolution_module_with_path_in_mod_rs() {
120 //- /foo/baz.rs 141 //- /foo/baz.rs
121 pub struct Baz; 142 pub struct Baz;
122 "###, 143 "###,
123 crate_graph! {
124 "main": ("/main.rs", []),
125 },
126 ); 144 );
127 145
128 assert_snapshot!(map, @r###" 146 assert_snapshot!(map, @r###"
@@ -140,7 +158,7 @@ fn module_resolution_module_with_path_in_mod_rs() {
140 158
141#[test] 159#[test]
142fn module_resolution_module_with_path_non_crate_root() { 160fn module_resolution_module_with_path_non_crate_root() {
143 let map = def_map_with_crate_graph( 161 let map = def_map(
144 r###" 162 r###"
145 //- /main.rs 163 //- /main.rs
146 mod foo; 164 mod foo;
@@ -154,9 +172,6 @@ fn module_resolution_module_with_path_non_crate_root() {
154 //- /baz.rs 172 //- /baz.rs
155 pub struct Baz; 173 pub struct Baz;
156 "###, 174 "###,
157 crate_graph! {
158 "main": ("/main.rs", []),
159 },
160 ); 175 );
161 176
162 assert_snapshot!(map, @r###" 177 assert_snapshot!(map, @r###"
@@ -174,7 +189,7 @@ fn module_resolution_module_with_path_non_crate_root() {
174 189
175#[test] 190#[test]
176fn module_resolution_module_decl_path_super() { 191fn module_resolution_module_decl_path_super() {
177 let map = def_map_with_crate_graph( 192 let map = def_map(
178 r###" 193 r###"
179 //- /main.rs 194 //- /main.rs
180 #[path = "bar/baz/module.rs"] 195 #[path = "bar/baz/module.rs"]
@@ -184,9 +199,6 @@ fn module_resolution_module_decl_path_super() {
184 //- /bar/baz/module.rs 199 //- /bar/baz/module.rs
185 use super::Baz; 200 use super::Baz;
186 "###, 201 "###,
187 crate_graph! {
188 "main": ("/main.rs", []),
189 },
190 ); 202 );
191 203
192 assert_snapshot!(map, @r###" 204 assert_snapshot!(map, @r###"
@@ -201,7 +213,7 @@ fn module_resolution_module_decl_path_super() {
201 213
202#[test] 214#[test]
203fn module_resolution_explicit_path_mod_rs() { 215fn module_resolution_explicit_path_mod_rs() {
204 let map = def_map_with_crate_graph( 216 let map = def_map(
205 r###" 217 r###"
206 //- /main.rs 218 //- /main.rs
207 #[path = "module/mod.rs"] 219 #[path = "module/mod.rs"]
@@ -210,9 +222,6 @@ fn module_resolution_explicit_path_mod_rs() {
210 //- /module/mod.rs 222 //- /module/mod.rs
211 pub struct Baz; 223 pub struct Baz;
212 "###, 224 "###,
213 crate_graph! {
214 "main": ("/main.rs", []),
215 },
216 ); 225 );
217 226
218 assert_snapshot!(map, @r###" 227 assert_snapshot!(map, @r###"
@@ -226,7 +235,7 @@ fn module_resolution_explicit_path_mod_rs() {
226 235
227#[test] 236#[test]
228fn module_resolution_relative_path() { 237fn module_resolution_relative_path() {
229 let map = def_map_with_crate_graph( 238 let map = def_map(
230 r###" 239 r###"
231 //- /main.rs 240 //- /main.rs
232 mod foo; 241 mod foo;
@@ -238,9 +247,6 @@ fn module_resolution_relative_path() {
238 //- /sub.rs 247 //- /sub.rs
239 pub struct Baz; 248 pub struct Baz;
240 "###, 249 "###,
241 crate_graph! {
242 "main": ("/main.rs", []),
243 },
244 ); 250 );
245 251
246 assert_snapshot!(map, @r###" 252 assert_snapshot!(map, @r###"
@@ -257,7 +263,7 @@ fn module_resolution_relative_path() {
257 263
258#[test] 264#[test]
259fn module_resolution_relative_path_2() { 265fn module_resolution_relative_path_2() {
260 let map = def_map_with_crate_graph( 266 let map = def_map(
261 r###" 267 r###"
262 //- /main.rs 268 //- /main.rs
263 mod foo; 269 mod foo;
@@ -269,9 +275,6 @@ fn module_resolution_relative_path_2() {
269 //- /sub.rs 275 //- /sub.rs
270 pub struct Baz; 276 pub struct Baz;
271 "###, 277 "###,
272 crate_graph! {
273 "main": ("/main.rs", []),
274 },
275 ); 278 );
276 279
277 assert_snapshot!(map, @r###" 280 assert_snapshot!(map, @r###"
@@ -288,7 +291,7 @@ fn module_resolution_relative_path_2() {
288 291
289#[test] 292#[test]
290fn module_resolution_explicit_path_mod_rs_2() { 293fn module_resolution_explicit_path_mod_rs_2() {
291 let map = def_map_with_crate_graph( 294 let map = def_map(
292 r###" 295 r###"
293 //- /main.rs 296 //- /main.rs
294 #[path = "module/bar/mod.rs"] 297 #[path = "module/bar/mod.rs"]
@@ -297,9 +300,6 @@ fn module_resolution_explicit_path_mod_rs_2() {
297 //- /module/bar/mod.rs 300 //- /module/bar/mod.rs
298 pub struct Baz; 301 pub struct Baz;
299 "###, 302 "###,
300 crate_graph! {
301 "main": ("/main.rs", []),
302 },
303 ); 303 );
304 304
305 assert_snapshot!(map, @r###" 305 assert_snapshot!(map, @r###"
@@ -313,7 +313,7 @@ fn module_resolution_explicit_path_mod_rs_2() {
313 313
314#[test] 314#[test]
315fn module_resolution_explicit_path_mod_rs_with_win_separator() { 315fn module_resolution_explicit_path_mod_rs_with_win_separator() {
316 let map = def_map_with_crate_graph( 316 let map = def_map(
317 r###" 317 r###"
318 //- /main.rs 318 //- /main.rs
319 #[path = "module\bar\mod.rs"] 319 #[path = "module\bar\mod.rs"]
@@ -322,9 +322,6 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() {
322 //- /module/bar/mod.rs 322 //- /module/bar/mod.rs
323 pub struct Baz; 323 pub struct Baz;
324 "###, 324 "###,
325 crate_graph! {
326 "main": ("/main.rs", []),
327 },
328 ); 325 );
329 326
330 assert_snapshot!(map, @r###" 327 assert_snapshot!(map, @r###"
@@ -338,7 +335,7 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() {
338 335
339#[test] 336#[test]
340fn module_resolution_decl_inside_inline_module_with_path_attribute() { 337fn module_resolution_decl_inside_inline_module_with_path_attribute() {
341 let map = def_map_with_crate_graph( 338 let map = def_map(
342 r###" 339 r###"
343 //- /main.rs 340 //- /main.rs
344 #[path = "models"] 341 #[path = "models"]
@@ -349,9 +346,6 @@ fn module_resolution_decl_inside_inline_module_with_path_attribute() {
349 //- /models/bar.rs 346 //- /models/bar.rs
350 pub struct Baz; 347 pub struct Baz;
351 "###, 348 "###,
352 crate_graph! {
353 "main": ("/main.rs", []),
354 },
355 ); 349 );
356 350
357 assert_snapshot!(map, @r###" 351 assert_snapshot!(map, @r###"
@@ -368,7 +362,7 @@ fn module_resolution_decl_inside_inline_module_with_path_attribute() {
368 362
369#[test] 363#[test]
370fn module_resolution_decl_inside_inline_module() { 364fn module_resolution_decl_inside_inline_module() {
371 let map = def_map_with_crate_graph( 365 let map = def_map(
372 r###" 366 r###"
373 //- /main.rs 367 //- /main.rs
374 mod foo { 368 mod foo {
@@ -378,9 +372,6 @@ fn module_resolution_decl_inside_inline_module() {
378 //- /foo/bar.rs 372 //- /foo/bar.rs
379 pub struct Baz; 373 pub struct Baz;
380 "###, 374 "###,
381 crate_graph! {
382 "main": ("/main.rs", []),
383 },
384 ); 375 );
385 376
386 assert_snapshot!(map, @r###" 377 assert_snapshot!(map, @r###"
@@ -397,7 +388,7 @@ fn module_resolution_decl_inside_inline_module() {
397 388
398#[test] 389#[test]
399fn module_resolution_decl_inside_inline_module_2_with_path_attribute() { 390fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
400 let map = def_map_with_crate_graph( 391 let map = def_map(
401 r###" 392 r###"
402 //- /main.rs 393 //- /main.rs
403 #[path = "models/db"] 394 #[path = "models/db"]
@@ -408,9 +399,6 @@ fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
408 //- /models/db/bar.rs 399 //- /models/db/bar.rs
409 pub struct Baz; 400 pub struct Baz;
410 "###, 401 "###,
411 crate_graph! {
412 "main": ("/main.rs", []),
413 },
414 ); 402 );
415 403
416 assert_snapshot!(map, @r###" 404 assert_snapshot!(map, @r###"
@@ -427,7 +415,7 @@ fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
427 415
428#[test] 416#[test]
429fn module_resolution_decl_inside_inline_module_3() { 417fn module_resolution_decl_inside_inline_module_3() {
430 let map = def_map_with_crate_graph( 418 let map = def_map(
431 r###" 419 r###"
432 //- /main.rs 420 //- /main.rs
433 #[path = "models/db"] 421 #[path = "models/db"]
@@ -439,9 +427,6 @@ fn module_resolution_decl_inside_inline_module_3() {
439 //- /models/db/users.rs 427 //- /models/db/users.rs
440 pub struct Baz; 428 pub struct Baz;
441 "###, 429 "###,
442 crate_graph! {
443 "main": ("/main.rs", []),
444 },
445 ); 430 );
446 431
447 assert_snapshot!(map, @r###" 432 assert_snapshot!(map, @r###"
@@ -458,7 +443,7 @@ fn module_resolution_decl_inside_inline_module_3() {
458 443
459#[test] 444#[test]
460fn module_resolution_decl_inside_inline_module_empty_path() { 445fn module_resolution_decl_inside_inline_module_empty_path() {
461 let map = def_map_with_crate_graph( 446 let map = def_map(
462 r###" 447 r###"
463 //- /main.rs 448 //- /main.rs
464 #[path = ""] 449 #[path = ""]
@@ -467,12 +452,9 @@ fn module_resolution_decl_inside_inline_module_empty_path() {
467 mod bar; 452 mod bar;
468 } 453 }
469 454
470 //- /foo/users.rs 455 //- /users.rs
471 pub struct Baz; 456 pub struct Baz;
472 "###, 457 "###,
473 crate_graph! {
474 "main": ("/main.rs", []),
475 },
476 ); 458 );
477 459
478 assert_snapshot!(map, @r###" 460 assert_snapshot!(map, @r###"
@@ -489,32 +471,25 @@ fn module_resolution_decl_inside_inline_module_empty_path() {
489 471
490#[test] 472#[test]
491fn module_resolution_decl_empty_path() { 473fn module_resolution_decl_empty_path() {
492 let map = def_map_with_crate_graph( 474 let map = def_map(
493 r###" 475 r###"
494 //- /main.rs 476 //- /main.rs
495 #[path = ""] 477 #[path = ""] // Should try to read `/` (a directory)
496 mod foo; 478 mod foo;
497 479
498 //- /foo.rs 480 //- /foo.rs
499 pub struct Baz; 481 pub struct Baz;
500 "###, 482 "###,
501 crate_graph! {
502 "main": ("/main.rs", []),
503 },
504 ); 483 );
505 484
506 assert_snapshot!(map, @r###" 485 assert_snapshot!(map, @r###"
507 ⋮crate 486 ⋮crate
508 ⋮foo: t
509
510 ⋮crate::foo
511 ⋮Baz: t v
512 "###); 487 "###);
513} 488}
514 489
515#[test] 490#[test]
516fn module_resolution_decl_inside_inline_module_relative_path() { 491fn module_resolution_decl_inside_inline_module_relative_path() {
517 let map = def_map_with_crate_graph( 492 let map = def_map(
518 r###" 493 r###"
519 //- /main.rs 494 //- /main.rs
520 #[path = "./models"] 495 #[path = "./models"]
@@ -525,9 +500,6 @@ fn module_resolution_decl_inside_inline_module_relative_path() {
525 //- /models/bar.rs 500 //- /models/bar.rs
526 pub struct Baz; 501 pub struct Baz;
527 "###, 502 "###,
528 crate_graph! {
529 "main": ("/main.rs", []),
530 },
531 ); 503 );
532 504
533 assert_snapshot!(map, @r###" 505 assert_snapshot!(map, @r###"
@@ -544,7 +516,7 @@ fn module_resolution_decl_inside_inline_module_relative_path() {
544 516
545#[test] 517#[test]
546fn module_resolution_decl_inside_inline_module_in_crate_root() { 518fn module_resolution_decl_inside_inline_module_in_crate_root() {
547 let map = def_map_with_crate_graph( 519 let map = def_map(
548 r###" 520 r###"
549 //- /main.rs 521 //- /main.rs
550 mod foo { 522 mod foo {
@@ -556,9 +528,6 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
556 //- /foo/baz.rs 528 //- /foo/baz.rs
557 pub struct Baz; 529 pub struct Baz;
558 "###, 530 "###,
559 crate_graph! {
560 "main": ("/main.rs", []),
561 },
562 ); 531 );
563 532
564 assert_snapshot!(map, @r###" 533 assert_snapshot!(map, @r###"
@@ -576,7 +545,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
576 545
577#[test] 546#[test]
578fn module_resolution_decl_inside_inline_module_in_mod_rs() { 547fn module_resolution_decl_inside_inline_module_in_mod_rs() {
579 let map = def_map_with_crate_graph( 548 let map = def_map(
580 r###" 549 r###"
581 //- /main.rs 550 //- /main.rs
582 mod foo; 551 mod foo;
@@ -591,9 +560,6 @@ fn module_resolution_decl_inside_inline_module_in_mod_rs() {
591 //- /foo/bar/qwe.rs 560 //- /foo/bar/qwe.rs
592 pub struct Baz; 561 pub struct Baz;
593 "###, 562 "###,
594 crate_graph! {
595 "main": ("/main.rs", []),
596 },
597 ); 563 );
598 564
599 assert_snapshot!(map, @r###" 565 assert_snapshot!(map, @r###"
@@ -614,7 +580,7 @@ fn module_resolution_decl_inside_inline_module_in_mod_rs() {
614 580
615#[test] 581#[test]
616fn module_resolution_decl_inside_inline_module_in_non_crate_root() { 582fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
617 let map = def_map_with_crate_graph( 583 let map = def_map(
618 r###" 584 r###"
619 //- /main.rs 585 //- /main.rs
620 mod foo; 586 mod foo;
@@ -626,12 +592,9 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
626 } 592 }
627 use self::bar::baz::Baz; 593 use self::bar::baz::Baz;
628 594
629 //- /bar/qwe.rs 595 //- /foo/bar/qwe.rs
630 pub struct Baz; 596 pub struct Baz;
631 "###, 597 "###,
632 crate_graph! {
633 "main": ("/main.rs", []),
634 },
635 ); 598 );
636 599
637 assert_snapshot!(map, @r###" 600 assert_snapshot!(map, @r###"
@@ -652,7 +615,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
652 615
653#[test] 616#[test]
654fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() { 617fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
655 let map = def_map_with_crate_graph( 618 let map = def_map(
656 r###" 619 r###"
657 //- /main.rs 620 //- /main.rs
658 mod foo; 621 mod foo;
@@ -667,9 +630,6 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
667 //- /bar/baz.rs 630 //- /bar/baz.rs
668 pub struct Baz; 631 pub struct Baz;
669 "###, 632 "###,
670 crate_graph! {
671 "main": ("/main.rs", []),
672 },
673 ); 633 );
674 634
675 assert_snapshot!(map, @r###" 635 assert_snapshot!(map, @r###"
@@ -709,7 +669,7 @@ fn unresolved_module_diagnostics() {
709 669
710#[test] 670#[test]
711fn module_resolution_decl_inside_module_in_non_crate_root_2() { 671fn module_resolution_decl_inside_module_in_non_crate_root_2() {
712 let map = def_map_with_crate_graph( 672 let map = def_map(
713 r###" 673 r###"
714 //- /main.rs 674 //- /main.rs
715 #[path="module/m2.rs"] 675 #[path="module/m2.rs"]
@@ -721,9 +681,6 @@ fn module_resolution_decl_inside_module_in_non_crate_root_2() {
721 //- /module/submod.rs 681 //- /module/submod.rs
722 pub struct Baz; 682 pub struct Baz;
723 "###, 683 "###,
724 crate_graph! {
725 "main": ("/main.rs", []),
726 },
727 ); 684 );
728 685
729 assert_snapshot!(map, @r###" 686 assert_snapshot!(map, @r###"
@@ -737,3 +694,66 @@ fn module_resolution_decl_inside_module_in_non_crate_root_2() {
737 ⋮Baz: t v 694 ⋮Baz: t v
738 "###); 695 "###);
739} 696}
697
698#[test]
699fn nested_out_of_line_module() {
700 let map = def_map(
701 r###"
702 //- /lib.rs
703 mod a {
704 mod b {
705 mod c;
706 }
707 }
708
709 //- /a/b/c.rs
710 struct X;
711 "###,
712 );
713
714 assert_snapshot!(map, @r###"
715 crate
716 a: t
717
718 crate::a
719 b: t
720
721 crate::a::b
722 c: t
723
724 crate::a::b::c
725 X: t v
726 "###);
727}
728
729#[test]
730fn nested_out_of_line_module_with_path() {
731 let map = def_map(
732 r###"
733 //- /lib.rs
734 mod a {
735 #[path = "d/e"]
736 mod b {
737 mod c;
738 }
739 }
740
741 //- /a/d/e/c.rs
742 struct X;
743 "###,
744 );
745
746 assert_snapshot!(map, @r###"
747 crate
748 a: t
749
750 crate::a
751 b: t
752
753 crate::a::b
754 c: t
755
756 crate::a::b::c
757 X: t v
758 "###);
759}