diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs | 190 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/mod_resolution.rs | 182 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 2 | ||||
-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 @@ | |||
50 | mod per_ns; | 50 | mod per_ns; |
51 | mod raw; | 51 | mod raw; |
52 | mod collector; | 52 | mod collector; |
53 | mod mod_resolution; | ||
53 | #[cfg(test)] | 54 | #[cfg(test)] |
54 | mod tests; | 55 | mod 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 @@ | |||
1 | use std::borrow::Cow; | 1 | use ra_db::FileId; |
2 | use std::sync::Arc; | 2 | use ra_syntax::ast; |
3 | |||
4 | use ra_db::{FileId, SourceRoot}; | ||
5 | use ra_syntax::{ast, SmolStr}; | ||
6 | use relative_path::RelativePathBuf; | ||
7 | use rustc_hash::FxHashMap; | 3 | use rustc_hash::FxHashMap; |
8 | use test_utils::tested_by; | 4 | use 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 | ||
697 | fn 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 | |||
775 | fn 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 | |||
790 | enum OutOfLineMode { | ||
791 | RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf }, | ||
792 | FileInDirectory(RelativePathBuf), | ||
793 | WithAttributePath(RelativePathBuf), | ||
794 | } | ||
795 | |||
796 | impl 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 | |||
809 | enum InsideInlineModuleMode { | ||
810 | File(RelativePathBuf), | ||
811 | WithAttributePath(RelativePathBuf), | ||
812 | } | ||
813 | |||
814 | impl 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 | |||
825 | enum ResolutionMode { | ||
826 | OutOfLine(OutOfLineMode), | ||
827 | InsideInlineModule(InsideInlineModuleMode), | ||
828 | InlineModuleWithAttributePath(InsideInlineModuleMode), | ||
829 | } | ||
830 | |||
831 | impl 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 | |||
843 | fn 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 | |||
850 | fn 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 | |||
860 | struct ParentModule<'a> { | ||
861 | name: &'a Name, | ||
862 | attr_path: Option<&'a SmolStr>, | ||
863 | } | ||
864 | |||
865 | impl<'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)] |
872 | mod tests { | 696 | mod 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 @@ | |||
1 | use std::{borrow::Cow, sync::Arc}; | ||
2 | |||
3 | use ra_db::{FileId, SourceRoot}; | ||
4 | use ra_syntax::SmolStr; | ||
5 | use relative_path::RelativePathBuf; | ||
6 | |||
7 | use crate::{DefDatabase, HirFileId, Name}; | ||
8 | |||
9 | #[derive(Clone, Copy)] | ||
10 | pub(super) struct ParentModule<'a> { | ||
11 | pub(super) name: &'a Name, | ||
12 | pub(super) attr_path: Option<&'a SmolStr>, | ||
13 | } | ||
14 | |||
15 | impl<'a> ParentModule<'a> { | ||
16 | fn attribute_path(&self) -> Option<&SmolStr> { | ||
17 | self.attr_path.filter(|p| !p.is_empty()) | ||
18 | } | ||
19 | } | ||
20 | |||
21 | pub(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 | |||
99 | fn 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 | |||
114 | enum OutOfLineMode { | ||
115 | RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf }, | ||
116 | FileInDirectory(RelativePathBuf), | ||
117 | WithAttributePath(RelativePathBuf), | ||
118 | } | ||
119 | |||
120 | impl 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 | |||
133 | enum InsideInlineModuleMode { | ||
134 | File(RelativePathBuf), | ||
135 | WithAttributePath(RelativePathBuf), | ||
136 | } | ||
137 | |||
138 | impl 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 | |||
149 | enum ResolutionMode { | ||
150 | OutOfLine(OutOfLineMode), | ||
151 | InsideInlineModule(InsideInlineModuleMode), | ||
152 | InlineModuleWithAttributePath(InsideInlineModuleMode), | ||
153 | } | ||
154 | |||
155 | impl 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 | |||
167 | fn 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 | |||
174 | fn 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; | |||
2 | mod globs; | 2 | mod globs; |
3 | mod incremental; | 3 | mod incremental; |
4 | mod primitives; | 4 | mod primitives; |
5 | mod mods; | 5 | mod mod_resolution; |
6 | 6 | ||
7 | use std::sync::Arc; | 7 | use 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 | |||