diff options
Diffstat (limited to 'crates')
-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 |
3 files changed, 190 insertions, 183 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 5d1c42926..d6c7c083d 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, |
@@ -568,7 +566,7 @@ where | |||
568 | name, | 566 | name, |
569 | is_root, | 567 | is_root, |
570 | attr_path.as_ref(), | 568 | attr_path.as_ref(), |
571 | self.parent_module.as_ref(), | 569 | self.parent_module, |
572 | ) { | 570 | ) { |
573 | Ok(file_id) => { | 571 | Ok(file_id) => { |
574 | let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); | 572 | let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); |
@@ -679,180 +677,6 @@ fn is_macro_rules(path: &Path) -> bool { | |||
679 | path.as_ident() == Some(&MACRO_RULES) | 677 | path.as_ident() == Some(&MACRO_RULES) |
680 | } | 678 | } |
681 | 679 | ||
682 | fn resolve_submodule( | ||
683 | db: &impl DefDatabase, | ||
684 | file_id: HirFileId, | ||
685 | name: &Name, | ||
686 | is_root: bool, | ||
687 | attr_path: Option<&SmolStr>, | ||
688 | parent_module: Option<&ParentModule>, | ||
689 | ) -> Result<FileId, RelativePathBuf> { | ||
690 | let file_id = file_id.original_file(db); | ||
691 | let source_root_id = db.file_source_root(file_id); | ||
692 | let path = db.file_relative_path(file_id); | ||
693 | let root = RelativePathBuf::default(); | ||
694 | let dir_path = path.parent().unwrap_or(&root); | ||
695 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
696 | |||
697 | let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) { | ||
698 | (Some(file_path), Some(parent_module)) => { | ||
699 | let file_path = normalize_attribute_path(file_path); | ||
700 | match parent_module.attribute_path() { | ||
701 | Some(parent_module_attr_path) => { | ||
702 | let path = dir_path | ||
703 | .join(format!( | ||
704 | "{}/{}", | ||
705 | normalize_attribute_path(parent_module_attr_path), | ||
706 | file_path | ||
707 | )) | ||
708 | .normalize(); | ||
709 | ResolutionMode::InlineModuleWithAttributePath( | ||
710 | InsideInlineModuleMode::WithAttributePath(path), | ||
711 | ) | ||
712 | } | ||
713 | None => { | ||
714 | let path = | ||
715 | dir_path.join(format!("{}/{}", parent_module.name, file_path)).normalize(); | ||
716 | ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath( | ||
717 | path, | ||
718 | )) | ||
719 | } | ||
720 | } | ||
721 | } | ||
722 | (None, Some(parent_module)) => match parent_module.attribute_path() { | ||
723 | Some(parent_module_attr_path) => { | ||
724 | let path = dir_path.join(format!( | ||
725 | "{}/{}.rs", | ||
726 | normalize_attribute_path(parent_module_attr_path), | ||
727 | name | ||
728 | )); | ||
729 | ResolutionMode::InlineModuleWithAttributePath(InsideInlineModuleMode::File(path)) | ||
730 | } | ||
731 | None => { | ||
732 | let path = dir_path.join(format!("{}/{}.rs", parent_module.name, name)); | ||
733 | ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path)) | ||
734 | } | ||
735 | }, | ||
736 | (Some(file_path), None) => { | ||
737 | let file_path = normalize_attribute_path(file_path); | ||
738 | let path = dir_path.join(file_path.as_ref()).normalize(); | ||
739 | ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path)) | ||
740 | } | ||
741 | _ => { | ||
742 | let is_dir_owner = is_root || mod_name == "mod"; | ||
743 | if is_dir_owner { | ||
744 | let file_mod = dir_path.join(format!("{}.rs", name)); | ||
745 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | ||
746 | ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs { | ||
747 | file: file_mod, | ||
748 | directory: dir_mod, | ||
749 | }) | ||
750 | } else { | ||
751 | let path = dir_path.join(format!("{}/{}.rs", mod_name, name)); | ||
752 | ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path)) | ||
753 | } | ||
754 | } | ||
755 | }; | ||
756 | |||
757 | resolve_mode.resolve(db.source_root(source_root_id)) | ||
758 | } | ||
759 | |||
760 | fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> { | ||
761 | let current_dir = "./"; | ||
762 | let windows_path_separator = r#"\"#; | ||
763 | let current_dir_normalize = if file_path.starts_with(current_dir) { | ||
764 | &file_path[current_dir.len()..] | ||
765 | } else { | ||
766 | file_path.as_str() | ||
767 | }; | ||
768 | if current_dir_normalize.contains(windows_path_separator) { | ||
769 | Cow::Owned(current_dir_normalize.replace(windows_path_separator, "/")) | ||
770 | } else { | ||
771 | Cow::Borrowed(current_dir_normalize) | ||
772 | } | ||
773 | } | ||
774 | |||
775 | enum OutOfLineMode { | ||
776 | RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf }, | ||
777 | FileInDirectory(RelativePathBuf), | ||
778 | WithAttributePath(RelativePathBuf), | ||
779 | } | ||
780 | |||
781 | impl OutOfLineMode { | ||
782 | pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> { | ||
783 | match self { | ||
784 | OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) { | ||
785 | None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()), | ||
786 | file_id => resolve_find_result(file_id, file), | ||
787 | }, | ||
788 | OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path), | ||
789 | OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path), | ||
790 | } | ||
791 | } | ||
792 | } | ||
793 | |||
794 | enum InsideInlineModuleMode { | ||
795 | File(RelativePathBuf), | ||
796 | WithAttributePath(RelativePathBuf), | ||
797 | } | ||
798 | |||
799 | impl InsideInlineModuleMode { | ||
800 | pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> { | ||
801 | match self { | ||
802 | InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path), | ||
803 | InsideInlineModuleMode::WithAttributePath(path) => { | ||
804 | resolve_simple_path(source_root, path) | ||
805 | } | ||
806 | } | ||
807 | } | ||
808 | } | ||
809 | |||
810 | enum ResolutionMode { | ||
811 | OutOfLine(OutOfLineMode), | ||
812 | InsideInlineModule(InsideInlineModuleMode), | ||
813 | InlineModuleWithAttributePath(InsideInlineModuleMode), | ||
814 | } | ||
815 | |||
816 | impl ResolutionMode { | ||
817 | pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> { | ||
818 | use self::ResolutionMode::*; | ||
819 | |||
820 | match self { | ||
821 | OutOfLine(mode) => mode.resolve(source_root), | ||
822 | InsideInlineModule(mode) => mode.resolve(source_root), | ||
823 | InlineModuleWithAttributePath(mode) => mode.resolve(source_root), | ||
824 | } | ||
825 | } | ||
826 | } | ||
827 | |||
828 | fn resolve_simple_path( | ||
829 | source_root: Arc<SourceRoot>, | ||
830 | path: &RelativePathBuf, | ||
831 | ) -> Result<FileId, RelativePathBuf> { | ||
832 | resolve_find_result(source_root.files.get(path), path) | ||
833 | } | ||
834 | |||
835 | fn resolve_find_result( | ||
836 | file_id: Option<&FileId>, | ||
837 | path: &RelativePathBuf, | ||
838 | ) -> Result<FileId, RelativePathBuf> { | ||
839 | match file_id { | ||
840 | Some(file_id) => Ok(file_id.clone()), | ||
841 | None => Err(path.clone()), | ||
842 | } | ||
843 | } | ||
844 | |||
845 | struct ParentModule<'a> { | ||
846 | name: &'a Name, | ||
847 | attr_path: Option<&'a SmolStr>, | ||
848 | } | ||
849 | |||
850 | impl<'a> ParentModule<'a> { | ||
851 | pub fn attribute_path(&self) -> Option<&SmolStr> { | ||
852 | self.attr_path.filter(|p| !p.is_empty()) | ||
853 | } | ||
854 | } | ||
855 | |||
856 | #[cfg(test)] | 680 | #[cfg(test)] |
857 | mod tests { | 681 | mod tests { |
858 | use ra_db::SourceDatabase; | 682 | 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 | } | ||