aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/nameres.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs190
-rw-r--r--crates/ra_hir/src/nameres/mod_resolution.rs182
-rw-r--r--crates/ra_hir/src/nameres/tests.rs2
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs (renamed from crates/ra_hir/src/nameres/tests/mods.rs)0
5 files changed, 191 insertions, 184 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index f69179bf6..dc2e2172b 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -50,6 +50,7 @@
50mod per_ns; 50mod per_ns;
51mod raw; 51mod raw;
52mod collector; 52mod collector;
53mod mod_resolution;
53#[cfg(test)] 54#[cfg(test)]
54mod tests; 55mod tests;
55 56
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 698e40247..5af26f953 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,9 +1,5 @@
1use std::borrow::Cow; 1use ra_db::FileId;
2use std::sync::Arc; 2use ra_syntax::ast;
3
4use ra_db::{FileId, SourceRoot};
5use ra_syntax::{ast, SmolStr};
6use relative_path::RelativePathBuf;
7use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
8use test_utils::tested_by; 4use test_utils::tested_by;
9 5
@@ -12,8 +8,10 @@ use crate::{
12 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 8 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
13 name::MACRO_RULES, 9 name::MACRO_RULES,
14 nameres::{ 10 nameres::{
15 diagnostics::DefDiagnostic, raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, 11 diagnostics::DefDiagnostic,
16 ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode, 12 mod_resolution::{resolve_submodule, ParentModule},
13 raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs,
14 ReachedFixedPoint, Resolution, ResolveMode,
17 }, 15 },
18 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static, 16 AstId, Const, DefDatabase, Enum, Function, HirFileId, MacroDef, Module, Name, Path, Static,
19 Struct, Trait, TypeAlias, Union, 17 Struct, Trait, TypeAlias, Union,
@@ -583,7 +581,7 @@ where
583 name, 581 name,
584 is_root, 582 is_root,
585 attr_path.as_ref(), 583 attr_path.as_ref(),
586 self.parent_module.as_ref(), 584 self.parent_module,
587 ) { 585 ) {
588 Ok(file_id) => { 586 Ok(file_id) => {
589 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 587 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
@@ -694,180 +692,6 @@ fn is_macro_rules(path: &Path) -> bool {
694 path.as_ident() == Some(&MACRO_RULES) 692 path.as_ident() == Some(&MACRO_RULES)
695} 693}
696 694
697fn resolve_submodule(
698 db: &impl DefDatabase,
699 file_id: HirFileId,
700 name: &Name,
701 is_root: bool,
702 attr_path: Option<&SmolStr>,
703 parent_module: Option<&ParentModule>,
704) -> Result<FileId, RelativePathBuf> {
705 let file_id = file_id.original_file(db);
706 let source_root_id = db.file_source_root(file_id);
707 let path = db.file_relative_path(file_id);
708 let root = RelativePathBuf::default();
709 let dir_path = path.parent().unwrap_or(&root);
710 let mod_name = path.file_stem().unwrap_or("unknown");
711
712 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
713 (Some(file_path), Some(parent_module)) => {
714 let file_path = normalize_attribute_path(file_path);
715 match parent_module.attribute_path() {
716 Some(parent_module_attr_path) => {
717 let path = dir_path
718 .join(format!(
719 "{}/{}",
720 normalize_attribute_path(parent_module_attr_path),
721 file_path
722 ))
723 .normalize();
724 ResolutionMode::InlineModuleWithAttributePath(
725 InsideInlineModuleMode::WithAttributePath(path),
726 )
727 }
728 None => {
729 let path =
730 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
731 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
732 path,
733 ))
734 }
735 }
736 }
737 (None, Some(parent_module)) => match parent_module.attribute_path() {
738 Some(parent_module_attr_path) => {
739 let path = dir_path.join(format!(
740 "{}/{}.rs",
741 normalize_attribute_path(parent_module_attr_path),
742 name
743 ));
744 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
745 }
746 None => {
747 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
748 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
749 }
750 },
751 (Some(file_path), None) => {
752 let file_path = normalize_attribute_path(file_path);
753 let path = dir_path.join(file_path.as_ref()).normalize();
754 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
755 }
756 _ => {
757 let is_dir_owner = is_root || mod_name == "mod";
758 if is_dir_owner {
759 let file_mod = dir_path.join(format!("{}.rs", name));
760 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
761 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
762 file: file_mod,
763 directory: dir_mod,
764 })
765 } else {
766 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
767 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
768 }
769 }
770 };
771
772 resolve_mode.resolve(db.source_root(source_root_id))
773}
774
775fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
776 let current_dir = "./";
777 let windows_path_separator = r#"\"#;
778 let current_dir_normalize = if file_path.starts_with(current_dir) {
779 &file_path[current_dir.len()..]
780 } else {
781 file_path.as_str()
782 };
783 if current_dir_normalize.contains(windows_path_separator) {
784 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
785 } else {
786 Cow::Borrowed(current_dir_normalize)
787 }
788}
789
790enum OutOfLineMode {
791 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
792 FileInDirectory(RelativePathBuf),
793 WithAttributePath(RelativePathBuf),
794}
795
796impl OutOfLineMode {
797 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
798 match self {
799 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
800 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
801 file_id => resolve_find_result(file_id, file),
802 },
803 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
804 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
805 }
806 }
807}
808
809enum InsideInlineModuleMode {
810 File(RelativePathBuf),
811 WithAttributePath(RelativePathBuf),
812}
813
814impl InsideInlineModuleMode {
815 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
816 match self {
817 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
818 InsideInlineModuleMode::WithAttributePath(path) => {
819 resolve_simple_path(source_root, path)
820 }
821 }
822 }
823}
824
825enum ResolutionMode {
826 OutOfLine(OutOfLineMode),
827 InsideInlineModule(InsideInlineModuleMode),
828 InlineModuleWithAttributePath(InsideInlineModuleMode),
829}
830
831impl ResolutionMode {
832 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
833 use self::ResolutionMode::*;
834
835 match self {
836 OutOfLine(mode) => mode.resolve(source_root),
837 InsideInlineModule(mode) => mode.resolve(source_root),
838 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
839 }
840 }
841}
842
843fn resolve_simple_path(
844 source_root: Arc<SourceRoot>,
845 path: &RelativePathBuf,
846) -> Result<FileId, RelativePathBuf> {
847 resolve_find_result(source_root.files.get(path), path)
848}
849
850fn resolve_find_result(
851 file_id: Option<&FileId>,
852 path: &RelativePathBuf,
853) -> Result<FileId, RelativePathBuf> {
854 match file_id {
855 Some(file_id) => Ok(file_id.clone()),
856 None => Err(path.clone()),
857 }
858}
859
860struct ParentModule<'a> {
861 name: &'a Name,
862 attr_path: Option<&'a SmolStr>,
863}
864
865impl<'a> ParentModule<'a> {
866 pub fn attribute_path(&self) -> Option<&SmolStr> {
867 self.attr_path.filter(|p| !p.is_empty())
868 }
869}
870
871#[cfg(test)] 695#[cfg(test)]
872mod tests { 696mod tests {
873 use ra_db::SourceDatabase; 697 use ra_db::SourceDatabase;
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs
new file mode 100644
index 000000000..94c9946ff
--- /dev/null
+++ b/crates/ra_hir/src/nameres/mod_resolution.rs
@@ -0,0 +1,182 @@
1use std::{borrow::Cow, sync::Arc};
2
3use ra_db::{FileId, SourceRoot};
4use ra_syntax::SmolStr;
5use relative_path::RelativePathBuf;
6
7use crate::{DefDatabase, HirFileId, Name};
8
9#[derive(Clone, Copy)]
10pub(super) struct ParentModule<'a> {
11 pub(super) name: &'a Name,
12 pub(super) attr_path: Option<&'a SmolStr>,
13}
14
15impl<'a> ParentModule<'a> {
16 fn attribute_path(&self) -> Option<&SmolStr> {
17 self.attr_path.filter(|p| !p.is_empty())
18 }
19}
20
21pub(super) fn resolve_submodule(
22 db: &impl DefDatabase,
23 file_id: HirFileId,
24 name: &Name,
25 is_root: bool,
26 attr_path: Option<&SmolStr>,
27 parent_module: Option<ParentModule<'_>>,
28) -> Result<FileId, RelativePathBuf> {
29 let file_id = file_id.original_file(db);
30 let source_root_id = db.file_source_root(file_id);
31 let path = db.file_relative_path(file_id);
32 let root = RelativePathBuf::default();
33 let dir_path = path.parent().unwrap_or(&root);
34 let mod_name = path.file_stem().unwrap_or("unknown");
35
36 let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
37 (Some(file_path), Some(parent_module)) => {
38 let file_path = normalize_attribute_path(file_path);
39 match parent_module.attribute_path() {
40 Some(parent_module_attr_path) => {
41 let path = dir_path
42 .join(format!(
43 "{}/{}",
44 normalize_attribute_path(parent_module_attr_path),
45 file_path
46 ))
47 .normalize();
48 ResolutionMode::InlineModuleWithAttributePath(
49 InsideInlineModuleMode::WithAttributePath(path),
50 )
51 }
52 None => {
53 let path =
54 dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize();
55 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(
56 path,
57 ))
58 }
59 }
60 }
61 (None, Some(parent_module)) => match parent_module.attribute_path() {
62 Some(parent_module_attr_path) => {
63 let path = dir_path.join(format!(
64 "{}/{}.rs",
65 normalize_attribute_path(parent_module_attr_path),
66 name
67 ));
68 ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path))
69 }
70 None => {
71 let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name));
72 ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
73 }
74 },
75 (Some(file_path), None) => {
76 let file_path = normalize_attribute_path(file_path);
77 let path = dir_path.join(file_path.as_ref()).normalize();
78 ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
79 }
80 _ => {
81 let is_dir_owner = is_root || mod_name == "mod";
82 if is_dir_owner {
83 let file_mod = dir_path.join(format!("{}.rs", name));
84 let dir_mod = dir_path.join(format!("{}/mod.rs", name));
85 ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
86 file: file_mod,
87 directory: dir_mod,
88 })
89 } else {
90 let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
91 ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
92 }
93 }
94 };
95
96 resolve_mode.resolve(db.source_root(source_root_id))
97}
98
99fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
100 let current_dir = "./";
101 let windows_path_separator = r#"\"#;
102 let current_dir_normalize = if file_path.starts_with(current_dir) {
103 &file_path[current_dir.len()..]
104 } else {
105 file_path.as_str()
106 };
107 if current_dir_normalize.contains(windows_path_separator) {
108 Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/"))
109 } else {
110 Cow::Borrowed(current_dir_normalize)
111 }
112}
113
114enum OutOfLineMode {
115 RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
116 FileInDirectory(RelativePathBuf),
117 WithAttributePath(RelativePathBuf),
118}
119
120impl OutOfLineMode {
121 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
122 match self {
123 OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
124 None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
125 file_id => resolve_find_result(file_id, file),
126 },
127 OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
128 OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
129 }
130 }
131}
132
133enum InsideInlineModuleMode {
134 File(RelativePathBuf),
135 WithAttributePath(RelativePathBuf),
136}
137
138impl InsideInlineModuleMode {
139 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
140 match self {
141 InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
142 InsideInlineModuleMode::WithAttributePath(path) => {
143 resolve_simple_path(source_root, path)
144 }
145 }
146 }
147}
148
149enum ResolutionMode {
150 OutOfLine(OutOfLineMode),
151 InsideInlineModule(InsideInlineModuleMode),
152 InlineModuleWithAttributePath(InsideInlineModuleMode),
153}
154
155impl ResolutionMode {
156 pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
157 use self::ResolutionMode::*;
158
159 match self {
160 OutOfLine(mode) => mode.resolve(source_root),
161 InsideInlineModule(mode) => mode.resolve(source_root),
162 InlineModuleWithAttributePath(mode) => mode.resolve(source_root),
163 }
164 }
165}
166
167fn resolve_simple_path(
168 source_root: Arc<SourceRoot>,
169 path: &RelativePathBuf,
170) -> Result<FileId, RelativePathBuf> {
171 resolve_find_result(source_root.files.get(path), path)
172}
173
174fn resolve_find_result(
175 file_id: Option<&FileId>,
176 path: &RelativePathBuf,
177) -> Result<FileId, RelativePathBuf> {
178 match file_id {
179 Some(file_id) => Ok(file_id.clone()),
180 None => Err(path.clone()),
181 }
182}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index c1dbad283..4ff897ca5 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -2,7 +2,7 @@ mod macros;
2mod globs; 2mod globs;
3mod incremental; 3mod incremental;
4mod primitives; 4mod primitives;
5mod mods; 5mod mod_resolution;
6 6
7use std::sync::Arc; 7use std::sync::Arc;
8 8
diff --git a/crates/ra_hir/src/nameres/tests/mods.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
index 4f8398460..4f8398460 100644
--- a/crates/ra_hir/src/nameres/tests/mods.rs
+++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs