diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl.rs | 196 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/krate.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 154 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/impl_block.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 190 | ||||
-rw-r--r-- | crates/ra_hir/src/module_tree.rs (renamed from crates/ra_hir/src/module.rs) | 232 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs (renamed from crates/ra_hir/src/module/nameres.rs) | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs (renamed from crates/ra_hir/src/module/nameres/tests.rs) | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 2 |
13 files changed, 431 insertions, 436 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index d00d3246f..09b532f74 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | use relative_path::RelativePathBuf; | ||
1 | use ra_db::{CrateId, Cancelable, FileId}; | 2 | use ra_db::{CrateId, Cancelable, FileId}; |
2 | use ra_syntax::{ast, SyntaxNode}; | 3 | use ra_syntax::{ast, SyntaxNode}; |
3 | 4 | ||
4 | use crate::{Name, db::HirDatabase, DefId, Path, PerNs, module::{Problem, ModuleScope}}; | 5 | use crate::{Name, db::HirDatabase, DefId, Path, PerNs, nameres::ModuleScope}; |
5 | 6 | ||
6 | /// hir::Crate describes a single crate. It's the main inteface with which | 7 | /// hir::Crate describes a single crate. It's the main inteface with which |
7 | /// crate's dependencies interact. Mostly, it should be just a proxy for the | 8 | /// crate's dependencies interact. Mostly, it should be just a proxy for the |
@@ -39,6 +40,17 @@ pub enum ModuleSource { | |||
39 | Module(ast::ModuleNode), | 40 | Module(ast::ModuleNode), |
40 | } | 41 | } |
41 | 42 | ||
43 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | ||
44 | pub enum Problem { | ||
45 | UnresolvedModule { | ||
46 | candidate: RelativePathBuf, | ||
47 | }, | ||
48 | NotDirOwner { | ||
49 | move_to: RelativePathBuf, | ||
50 | candidate: RelativePathBuf, | ||
51 | }, | ||
52 | } | ||
53 | |||
42 | impl Module { | 54 | impl Module { |
43 | /// Name of this module. | 55 | /// Name of this module. |
44 | pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { | 56 | pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { |
diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs index 4f4b506dd..d602a439d 100644 --- a/crates/ra_hir/src/code_model_impl.rs +++ b/crates/ra_hir/src/code_model_impl.rs | |||
@@ -1,194 +1,2 @@ | |||
1 | use ra_db::{CrateId, Cancelable, SourceRootId, FileId}; | 1 | mod krate; // `crate` is invalid ident :( |
2 | use ra_syntax::{ast, SyntaxNode, AstNode}; | 2 | pub(crate) mod module; |
3 | |||
4 | use crate::{ | ||
5 | HirFileId, Crate, CrateDependency, AsName, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, ModuleId, | ||
6 | module::{ModuleScope, Problem}, | ||
7 | db::HirDatabase, | ||
8 | }; | ||
9 | |||
10 | use crate::code_model_api::{Module, ModuleSource}; | ||
11 | |||
12 | impl Crate { | ||
13 | pub(crate) fn new(crate_id: CrateId) -> Crate { | ||
14 | Crate { crate_id } | ||
15 | } | ||
16 | pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { | ||
17 | let crate_graph = db.crate_graph(); | ||
18 | crate_graph | ||
19 | .dependencies(self.crate_id) | ||
20 | .map(|dep| { | ||
21 | let krate = Crate::new(dep.crate_id()); | ||
22 | let name = dep.as_name(); | ||
23 | CrateDependency { krate, name } | ||
24 | }) | ||
25 | .collect() | ||
26 | } | ||
27 | pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
28 | let crate_graph = db.crate_graph(); | ||
29 | let file_id = crate_graph.crate_root(self.crate_id); | ||
30 | let source_root_id = db.file_source_root(file_id); | ||
31 | let file_id = HirFileId::from(file_id); | ||
32 | let module_tree = db.module_tree(source_root_id)?; | ||
33 | // FIXME: teach module tree about crate roots instead of guessing | ||
34 | let (module_id, _) = ctry!(module_tree | ||
35 | .modules_with_sources() | ||
36 | .find(|(_, src)| src.file_id() == file_id)); | ||
37 | |||
38 | let def_loc = DefLoc { | ||
39 | kind: DefKind::Module, | ||
40 | source_root_id, | ||
41 | module_id, | ||
42 | source_item_id: module_id.source(&module_tree).0, | ||
43 | }; | ||
44 | let def_id = def_loc.id(db); | ||
45 | |||
46 | let module = Module::new(def_id); | ||
47 | Ok(Some(module)) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | impl Module { | ||
52 | pub(crate) fn new(def_id: DefId) -> Self { | ||
53 | crate::code_model_api::Module { def_id } | ||
54 | } | ||
55 | pub(crate) fn from_module_id( | ||
56 | db: &impl HirDatabase, | ||
57 | source_root_id: SourceRootId, | ||
58 | module_id: ModuleId, | ||
59 | ) -> Cancelable<Self> { | ||
60 | let module_tree = db.module_tree(source_root_id)?; | ||
61 | let def_loc = DefLoc { | ||
62 | kind: DefKind::Module, | ||
63 | source_root_id, | ||
64 | module_id, | ||
65 | source_item_id: module_id.source(&module_tree).0, | ||
66 | }; | ||
67 | let def_id = def_loc.id(db); | ||
68 | let module = Module::new(def_id); | ||
69 | Ok(module) | ||
70 | } | ||
71 | |||
72 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { | ||
73 | let loc = self.def_id.loc(db); | ||
74 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
75 | let link = ctry!(loc.module_id.parent_link(&module_tree)); | ||
76 | Ok(Some(link.name(&module_tree).clone())) | ||
77 | } | ||
78 | |||
79 | pub fn defenition_source_impl( | ||
80 | &self, | ||
81 | db: &impl HirDatabase, | ||
82 | ) -> Cancelable<(FileId, ModuleSource)> { | ||
83 | let loc = self.def_id.loc(db); | ||
84 | let file_id = loc.source_item_id.file_id.as_original_file(); | ||
85 | let syntax_node = db.file_item(loc.source_item_id); | ||
86 | let syntax_node = syntax_node.borrowed(); | ||
87 | let module_source = if let Some(source_file) = ast::SourceFile::cast(syntax_node) { | ||
88 | ModuleSource::SourceFile(source_file.owned()) | ||
89 | } else { | ||
90 | let module = ast::Module::cast(syntax_node).unwrap(); | ||
91 | ModuleSource::Module(module.owned()) | ||
92 | }; | ||
93 | Ok((file_id, module_source)) | ||
94 | } | ||
95 | |||
96 | pub fn declaration_source_impl( | ||
97 | &self, | ||
98 | db: &impl HirDatabase, | ||
99 | ) -> Cancelable<Option<(FileId, ast::ModuleNode)>> { | ||
100 | let loc = self.def_id.loc(db); | ||
101 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
102 | let link = ctry!(loc.module_id.parent_link(&module_tree)); | ||
103 | let file_id = link | ||
104 | .owner(&module_tree) | ||
105 | .source(&module_tree) | ||
106 | .file_id() | ||
107 | .as_original_file(); | ||
108 | let src = link.bind_source(&module_tree, db); | ||
109 | Ok(Some((file_id, src))) | ||
110 | } | ||
111 | |||
112 | pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { | ||
113 | let root = self.crate_root(db)?; | ||
114 | let loc = root.def_id.loc(db); | ||
115 | let file_id = loc.source_item_id.file_id.as_original_file(); | ||
116 | |||
117 | let crate_graph = db.crate_graph(); | ||
118 | let crate_id = ctry!(crate_graph.crate_id_for_crate_root(file_id)); | ||
119 | Ok(Some(Crate::new(crate_id))) | ||
120 | } | ||
121 | |||
122 | pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Cancelable<Module> { | ||
123 | let loc = self.def_id.loc(db); | ||
124 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
125 | let module_id = loc.module_id.crate_root(&module_tree); | ||
126 | Module::from_module_id(db, loc.source_root_id, module_id) | ||
127 | } | ||
128 | /// Finds a child module with the specified name. | ||
129 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | ||
130 | let loc = self.def_id.loc(db); | ||
131 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
132 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); | ||
133 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) | ||
134 | } | ||
135 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
136 | let loc = self.def_id.loc(db); | ||
137 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
138 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); | ||
139 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) | ||
140 | } | ||
141 | /// Returns a `ModuleScope`: a set of items, visible in this module. | ||
142 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | ||
143 | let loc = self.def_id.loc(db); | ||
144 | let item_map = db.item_map(loc.source_root_id)?; | ||
145 | let res = item_map.per_module[&loc.module_id].clone(); | ||
146 | Ok(res) | ||
147 | } | ||
148 | pub fn resolve_path_impl( | ||
149 | &self, | ||
150 | db: &impl HirDatabase, | ||
151 | path: &Path, | ||
152 | ) -> Cancelable<PerNs<DefId>> { | ||
153 | let mut curr_per_ns = PerNs::types( | ||
154 | match path.kind { | ||
155 | PathKind::Crate => self.crate_root(db)?, | ||
156 | PathKind::Self_ | PathKind::Plain => self.clone(), | ||
157 | PathKind::Super => { | ||
158 | if let Some(p) = self.parent(db)? { | ||
159 | p | ||
160 | } else { | ||
161 | return Ok(PerNs::none()); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | .def_id, | ||
166 | ); | ||
167 | |||
168 | let segments = &path.segments; | ||
169 | for name in segments.iter() { | ||
170 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { | ||
171 | r | ||
172 | } else { | ||
173 | return Ok(PerNs::none()); | ||
174 | }; | ||
175 | let module = match curr.resolve(db)? { | ||
176 | Def::Module(it) => it, | ||
177 | // TODO here would be the place to handle enum variants... | ||
178 | _ => return Ok(PerNs::none()), | ||
179 | }; | ||
180 | let scope = module.scope(db)?; | ||
181 | curr_per_ns = if let Some(r) = scope.get(&name) { | ||
182 | r.def_id | ||
183 | } else { | ||
184 | return Ok(PerNs::none()); | ||
185 | }; | ||
186 | } | ||
187 | Ok(curr_per_ns) | ||
188 | } | ||
189 | pub fn problems_impl(&self, db: &impl HirDatabase) -> Cancelable<Vec<(SyntaxNode, Problem)>> { | ||
190 | let loc = self.def_id.loc(db); | ||
191 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
192 | Ok(loc.module_id.problems(&module_tree, db)) | ||
193 | } | ||
194 | } | ||
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs new file mode 100644 index 000000000..591a81597 --- /dev/null +++ b/crates/ra_hir/src/code_model_impl/krate.rs | |||
@@ -0,0 +1,45 @@ | |||
1 | use ra_db::{CrateId, Cancelable}; | ||
2 | |||
3 | use crate::{ | ||
4 | HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, | ||
5 | db::HirDatabase, | ||
6 | }; | ||
7 | |||
8 | impl Crate { | ||
9 | pub(crate) fn new(crate_id: CrateId) -> Crate { | ||
10 | Crate { crate_id } | ||
11 | } | ||
12 | pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { | ||
13 | let crate_graph = db.crate_graph(); | ||
14 | crate_graph | ||
15 | .dependencies(self.crate_id) | ||
16 | .map(|dep| { | ||
17 | let krate = Crate::new(dep.crate_id()); | ||
18 | let name = dep.as_name(); | ||
19 | CrateDependency { krate, name } | ||
20 | }) | ||
21 | .collect() | ||
22 | } | ||
23 | pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
24 | let crate_graph = db.crate_graph(); | ||
25 | let file_id = crate_graph.crate_root(self.crate_id); | ||
26 | let source_root_id = db.file_source_root(file_id); | ||
27 | let file_id = HirFileId::from(file_id); | ||
28 | let module_tree = db.module_tree(source_root_id)?; | ||
29 | // FIXME: teach module tree about crate roots instead of guessing | ||
30 | let (module_id, _) = ctry!(module_tree | ||
31 | .modules_with_sources() | ||
32 | .find(|(_, src)| src.file_id() == file_id)); | ||
33 | |||
34 | let def_loc = DefLoc { | ||
35 | kind: DefKind::Module, | ||
36 | source_root_id, | ||
37 | module_id, | ||
38 | source_item_id: module_id.source(&module_tree).0, | ||
39 | }; | ||
40 | let def_id = def_loc.id(db); | ||
41 | |||
42 | let module = Module::new(def_id); | ||
43 | Ok(Some(module)) | ||
44 | } | ||
45 | } | ||
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs new file mode 100644 index 000000000..02078f188 --- /dev/null +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -0,0 +1,154 @@ | |||
1 | use ra_db::{Cancelable, SourceRootId, FileId}; | ||
2 | use ra_syntax::{ast, SyntaxNode, AstNode}; | ||
3 | |||
4 | use crate::{ | ||
5 | Module, ModuleSource, Problem, | ||
6 | Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, ModuleId, | ||
7 | nameres::ModuleScope, | ||
8 | db::HirDatabase, | ||
9 | }; | ||
10 | |||
11 | impl Module { | ||
12 | pub(crate) fn new(def_id: DefId) -> Self { | ||
13 | crate::code_model_api::Module { def_id } | ||
14 | } | ||
15 | pub(crate) fn from_module_id( | ||
16 | db: &impl HirDatabase, | ||
17 | source_root_id: SourceRootId, | ||
18 | module_id: ModuleId, | ||
19 | ) -> Cancelable<Self> { | ||
20 | let module_tree = db.module_tree(source_root_id)?; | ||
21 | let def_loc = DefLoc { | ||
22 | kind: DefKind::Module, | ||
23 | source_root_id, | ||
24 | module_id, | ||
25 | source_item_id: module_id.source(&module_tree).0, | ||
26 | }; | ||
27 | let def_id = def_loc.id(db); | ||
28 | let module = Module::new(def_id); | ||
29 | Ok(module) | ||
30 | } | ||
31 | |||
32 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { | ||
33 | let loc = self.def_id.loc(db); | ||
34 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
35 | let link = ctry!(loc.module_id.parent_link(&module_tree)); | ||
36 | Ok(Some(link.name(&module_tree).clone())) | ||
37 | } | ||
38 | |||
39 | pub fn defenition_source_impl( | ||
40 | &self, | ||
41 | db: &impl HirDatabase, | ||
42 | ) -> Cancelable<(FileId, ModuleSource)> { | ||
43 | let loc = self.def_id.loc(db); | ||
44 | let file_id = loc.source_item_id.file_id.as_original_file(); | ||
45 | let syntax_node = db.file_item(loc.source_item_id); | ||
46 | let syntax_node = syntax_node.borrowed(); | ||
47 | let module_source = if let Some(source_file) = ast::SourceFile::cast(syntax_node) { | ||
48 | ModuleSource::SourceFile(source_file.owned()) | ||
49 | } else { | ||
50 | let module = ast::Module::cast(syntax_node).unwrap(); | ||
51 | ModuleSource::Module(module.owned()) | ||
52 | }; | ||
53 | Ok((file_id, module_source)) | ||
54 | } | ||
55 | |||
56 | pub fn declaration_source_impl( | ||
57 | &self, | ||
58 | db: &impl HirDatabase, | ||
59 | ) -> Cancelable<Option<(FileId, ast::ModuleNode)>> { | ||
60 | let loc = self.def_id.loc(db); | ||
61 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
62 | let link = ctry!(loc.module_id.parent_link(&module_tree)); | ||
63 | let file_id = link | ||
64 | .owner(&module_tree) | ||
65 | .source(&module_tree) | ||
66 | .file_id() | ||
67 | .as_original_file(); | ||
68 | let src = link.bind_source(&module_tree, db); | ||
69 | Ok(Some((file_id, src))) | ||
70 | } | ||
71 | |||
72 | pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { | ||
73 | let root = self.crate_root(db)?; | ||
74 | let loc = root.def_id.loc(db); | ||
75 | let file_id = loc.source_item_id.file_id.as_original_file(); | ||
76 | |||
77 | let crate_graph = db.crate_graph(); | ||
78 | let crate_id = ctry!(crate_graph.crate_id_for_crate_root(file_id)); | ||
79 | Ok(Some(Crate::new(crate_id))) | ||
80 | } | ||
81 | |||
82 | pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Cancelable<Module> { | ||
83 | let loc = self.def_id.loc(db); | ||
84 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
85 | let module_id = loc.module_id.crate_root(&module_tree); | ||
86 | Module::from_module_id(db, loc.source_root_id, module_id) | ||
87 | } | ||
88 | /// Finds a child module with the specified name. | ||
89 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | ||
90 | let loc = self.def_id.loc(db); | ||
91 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
92 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); | ||
93 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) | ||
94 | } | ||
95 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | ||
96 | let loc = self.def_id.loc(db); | ||
97 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
98 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); | ||
99 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) | ||
100 | } | ||
101 | /// Returns a `ModuleScope`: a set of items, visible in this module. | ||
102 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | ||
103 | let loc = self.def_id.loc(db); | ||
104 | let item_map = db.item_map(loc.source_root_id)?; | ||
105 | let res = item_map.per_module[&loc.module_id].clone(); | ||
106 | Ok(res) | ||
107 | } | ||
108 | pub fn resolve_path_impl( | ||
109 | &self, | ||
110 | db: &impl HirDatabase, | ||
111 | path: &Path, | ||
112 | ) -> Cancelable<PerNs<DefId>> { | ||
113 | let mut curr_per_ns = PerNs::types( | ||
114 | match path.kind { | ||
115 | PathKind::Crate => self.crate_root(db)?, | ||
116 | PathKind::Self_ | PathKind::Plain => self.clone(), | ||
117 | PathKind::Super => { | ||
118 | if let Some(p) = self.parent(db)? { | ||
119 | p | ||
120 | } else { | ||
121 | return Ok(PerNs::none()); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | .def_id, | ||
126 | ); | ||
127 | |||
128 | let segments = &path.segments; | ||
129 | for name in segments.iter() { | ||
130 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { | ||
131 | r | ||
132 | } else { | ||
133 | return Ok(PerNs::none()); | ||
134 | }; | ||
135 | let module = match curr.resolve(db)? { | ||
136 | Def::Module(it) => it, | ||
137 | // TODO here would be the place to handle enum variants... | ||
138 | _ => return Ok(PerNs::none()), | ||
139 | }; | ||
140 | let scope = module.scope(db)?; | ||
141 | curr_per_ns = if let Some(r) = scope.get(&name) { | ||
142 | r.def_id | ||
143 | } else { | ||
144 | return Ok(PerNs::none()); | ||
145 | }; | ||
146 | } | ||
147 | Ok(curr_per_ns) | ||
148 | } | ||
149 | pub fn problems_impl(&self, db: &impl HirDatabase) -> Cancelable<Vec<(SyntaxNode, Problem)>> { | ||
150 | let loc = self.def_id.loc(db); | ||
151 | let module_tree = db.module_tree(loc.source_root_id)?; | ||
152 | Ok(loc.module_id.problems(&module_tree, db)) | ||
153 | } | ||
154 | } | ||
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 96a3c60b9..2702961ba 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -9,8 +9,8 @@ use crate::{ | |||
9 | query_definitions, | 9 | query_definitions, |
10 | FnSignature, FnScopes, | 10 | FnSignature, FnScopes, |
11 | macros::MacroExpansion, | 11 | macros::MacroExpansion, |
12 | module::{ModuleId, ModuleTree, ModuleSource, | 12 | module_tree::{ModuleId, ModuleTree, ModuleSource}, |
13 | nameres::{ItemMap, InputModuleItems}}, | 13 | nameres::{ItemMap, InputModuleItems}, |
14 | ty::{InferenceResult, Ty}, | 14 | ty::{InferenceResult, Ty}, |
15 | adt::{StructData, EnumData}, | 15 | adt::{StructData, EnumData}, |
16 | impl_block::ModuleImplBlocks, | 16 | impl_block::ModuleImplBlocks, |
@@ -71,7 +71,7 @@ pub trait HirDatabase: SyntaxDatabase | |||
71 | use fn query_definitions::file_item; | 71 | use fn query_definitions::file_item; |
72 | } | 72 | } |
73 | 73 | ||
74 | fn submodules(source: ModuleSource) -> Cancelable<Arc<Vec<crate::module::imp::Submodule>>> { | 74 | fn submodules(source: ModuleSource) -> Cancelable<Arc<Vec<crate::module_tree::Submodule>>> { |
75 | type SubmodulesQuery; | 75 | type SubmodulesQuery; |
76 | use fn query_definitions::submodules; | 76 | use fn query_definitions::submodules; |
77 | } | 77 | } |
@@ -86,7 +86,7 @@ pub trait HirDatabase: SyntaxDatabase | |||
86 | } | 86 | } |
87 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { | 87 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { |
88 | type ModuleTreeQuery; | 88 | type ModuleTreeQuery; |
89 | use fn crate::module::imp::module_tree; | 89 | use fn crate::module_tree::ModuleTree::module_tree_query; |
90 | } | 90 | } |
91 | 91 | ||
92 | fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleImplBlocks>> { | 92 | fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleImplBlocks>> { |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 0d1b94c42..7ce8d17e6 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | Function, | 10 | Function, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | type_ref::TypeRef, | 12 | type_ref::TypeRef, |
13 | module::ModuleId, | 13 | module_tree::ModuleId, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use crate::code_model_api::{Module, ModuleSource}; | 16 | use crate::code_model_api::{Module, ModuleSource}; |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 2fa357fec..7e74f2eaf 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -24,7 +24,8 @@ pub mod source_binder; | |||
24 | mod ids; | 24 | mod ids; |
25 | mod macros; | 25 | mod macros; |
26 | mod name; | 26 | mod name; |
27 | mod module; | 27 | mod module_tree; |
28 | mod nameres; | ||
28 | mod function; | 29 | mod function; |
29 | mod adt; | 30 | mod adt; |
30 | mod type_ref; | 31 | mod type_ref; |
@@ -32,14 +33,13 @@ mod ty; | |||
32 | mod impl_block; | 33 | mod impl_block; |
33 | mod expr; | 34 | mod expr; |
34 | 35 | ||
35 | pub mod code_model_api; | 36 | mod code_model_api; |
36 | mod code_model_impl; | 37 | mod code_model_impl; |
37 | 38 | ||
38 | use crate::{ | 39 | use crate::{ |
39 | db::HirDatabase, | 40 | db::HirDatabase, |
40 | name::{AsName, KnownName}, | 41 | name::{AsName, KnownName}, |
41 | ids::{DefKind, SourceItemId, SourceFileItemId, SourceFileItems}, | 42 | ids::{DefKind, SourceItemId, SourceFileItemId, SourceFileItems}, |
42 | code_model_api::{Crate, CrateDependency} | ||
43 | }; | 43 | }; |
44 | 44 | ||
45 | pub use self::{ | 45 | pub use self::{ |
@@ -56,7 +56,10 @@ pub use self::{ | |||
56 | 56 | ||
57 | pub use self::function::FnSignatureInfo; | 57 | pub use self::function::FnSignatureInfo; |
58 | 58 | ||
59 | pub use self::code_model_api::Module; | 59 | pub use self::code_model_api::{ |
60 | Crate, CrateDependency, | ||
61 | Module, ModuleSource, Problem, | ||
62 | }; | ||
60 | 63 | ||
61 | pub enum Def { | 64 | pub enum Def { |
62 | Module(Module), | 65 | Module(Module), |
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs deleted file mode 100644 index 3849026db..000000000 --- a/crates/ra_hir/src/module/imp.rs +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_syntax::ast::{self, NameOwner}; | ||
4 | use relative_path::RelativePathBuf; | ||
5 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
6 | use arrayvec::ArrayVec; | ||
7 | use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; | ||
8 | |||
9 | use crate::{ | ||
10 | HirDatabase, Name, AsName, | ||
11 | }; | ||
12 | |||
13 | use super::{ | ||
14 | LinkData, LinkId, ModuleData, ModuleId, ModuleSource, | ||
15 | ModuleTree, Problem, | ||
16 | }; | ||
17 | |||
18 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | ||
19 | pub enum Submodule { | ||
20 | Declaration(Name), | ||
21 | Definition(Name, ModuleSource), | ||
22 | } | ||
23 | |||
24 | impl Submodule { | ||
25 | fn name(&self) -> &Name { | ||
26 | match self { | ||
27 | Submodule::Declaration(name) => name, | ||
28 | Submodule::Definition(name, _) => name, | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | |||
33 | pub(crate) fn modules<'a>( | ||
34 | root: impl ast::ModuleItemOwner<'a>, | ||
35 | ) -> impl Iterator<Item = (Name, ast::Module<'a>)> { | ||
36 | root.items() | ||
37 | .filter_map(|item| match item { | ||
38 | ast::ModuleItem::Module(m) => Some(m), | ||
39 | _ => None, | ||
40 | }) | ||
41 | .filter_map(|module| { | ||
42 | let name = module.name()?.as_name(); | ||
43 | Some((name, module)) | ||
44 | }) | ||
45 | } | ||
46 | |||
47 | pub(crate) fn module_tree( | ||
48 | db: &impl HirDatabase, | ||
49 | source_root: SourceRootId, | ||
50 | ) -> Cancelable<Arc<ModuleTree>> { | ||
51 | db.check_canceled()?; | ||
52 | let res = create_module_tree(db, source_root)?; | ||
53 | Ok(Arc::new(res)) | ||
54 | } | ||
55 | |||
56 | fn create_module_tree<'a>( | ||
57 | db: &impl HirDatabase, | ||
58 | source_root: SourceRootId, | ||
59 | ) -> Cancelable<ModuleTree> { | ||
60 | let mut tree = ModuleTree::default(); | ||
61 | |||
62 | let mut roots = FxHashMap::default(); | ||
63 | let mut visited = FxHashSet::default(); | ||
64 | |||
65 | let source_root = db.source_root(source_root); | ||
66 | for &file_id in source_root.files.values() { | ||
67 | let source = ModuleSource::new_file(file_id.into()); | ||
68 | if visited.contains(&source) { | ||
69 | continue; // TODO: use explicit crate_roots here | ||
70 | } | ||
71 | assert!(!roots.contains_key(&file_id)); | ||
72 | let module_id = build_subtree( | ||
73 | db, | ||
74 | &source_root, | ||
75 | &mut tree, | ||
76 | &mut visited, | ||
77 | &mut roots, | ||
78 | None, | ||
79 | source, | ||
80 | )?; | ||
81 | roots.insert(file_id, module_id); | ||
82 | } | ||
83 | Ok(tree) | ||
84 | } | ||
85 | |||
86 | fn build_subtree( | ||
87 | db: &impl HirDatabase, | ||
88 | source_root: &SourceRoot, | ||
89 | tree: &mut ModuleTree, | ||
90 | visited: &mut FxHashSet<ModuleSource>, | ||
91 | roots: &mut FxHashMap<FileId, ModuleId>, | ||
92 | parent: Option<LinkId>, | ||
93 | source: ModuleSource, | ||
94 | ) -> Cancelable<ModuleId> { | ||
95 | visited.insert(source); | ||
96 | let id = tree.push_mod(ModuleData { | ||
97 | source, | ||
98 | parent, | ||
99 | children: Vec::new(), | ||
100 | }); | ||
101 | for sub in db.submodules(source)?.iter() { | ||
102 | let link = tree.push_link(LinkData { | ||
103 | name: sub.name().clone(), | ||
104 | owner: id, | ||
105 | points_to: Vec::new(), | ||
106 | problem: None, | ||
107 | }); | ||
108 | |||
109 | let (points_to, problem) = match sub { | ||
110 | Submodule::Declaration(name) => { | ||
111 | let (points_to, problem) = resolve_submodule(db, source, &name); | ||
112 | let points_to = points_to | ||
113 | .into_iter() | ||
114 | .map(|file_id| match roots.remove(&file_id) { | ||
115 | Some(module_id) => { | ||
116 | tree.mods[module_id].parent = Some(link); | ||
117 | Ok(module_id) | ||
118 | } | ||
119 | None => build_subtree( | ||
120 | db, | ||
121 | source_root, | ||
122 | tree, | ||
123 | visited, | ||
124 | roots, | ||
125 | Some(link), | ||
126 | ModuleSource::new_file(file_id.into()), | ||
127 | ), | ||
128 | }) | ||
129 | .collect::<Cancelable<Vec<_>>>()?; | ||
130 | (points_to, problem) | ||
131 | } | ||
132 | Submodule::Definition(_name, submodule_source) => { | ||
133 | let points_to = build_subtree( | ||
134 | db, | ||
135 | source_root, | ||
136 | tree, | ||
137 | visited, | ||
138 | roots, | ||
139 | Some(link), | ||
140 | *submodule_source, | ||
141 | )?; | ||
142 | (vec![points_to], None) | ||
143 | } | ||
144 | }; | ||
145 | |||
146 | tree.links[link].points_to = points_to; | ||
147 | tree.links[link].problem = problem; | ||
148 | } | ||
149 | Ok(id) | ||
150 | } | ||
151 | |||
152 | fn resolve_submodule( | ||
153 | db: &impl HirDatabase, | ||
154 | source: ModuleSource, | ||
155 | name: &Name, | ||
156 | ) -> (Vec<FileId>, Option<Problem>) { | ||
157 | // FIXME: handle submodules of inline modules properly | ||
158 | let file_id = source.file_id().original_file(db); | ||
159 | let source_root_id = db.file_source_root(file_id); | ||
160 | let path = db.file_relative_path(file_id); | ||
161 | let root = RelativePathBuf::default(); | ||
162 | let dir_path = path.parent().unwrap_or(&root); | ||
163 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
164 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | ||
165 | |||
166 | let file_mod = dir_path.join(format!("{}.rs", name)); | ||
167 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | ||
168 | let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); | ||
169 | let mut candidates = ArrayVec::<[_; 2]>::new(); | ||
170 | if is_dir_owner { | ||
171 | candidates.push(file_mod.clone()); | ||
172 | candidates.push(dir_mod); | ||
173 | } else { | ||
174 | candidates.push(file_dir_mod.clone()); | ||
175 | }; | ||
176 | let sr = db.source_root(source_root_id); | ||
177 | let points_to = candidates | ||
178 | .into_iter() | ||
179 | .filter_map(|path| sr.files.get(&path)) | ||
180 | .map(|&it| it) | ||
181 | .collect::<Vec<_>>(); | ||
182 | let problem = if points_to.is_empty() { | ||
183 | Some(Problem::UnresolvedModule { | ||
184 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
185 | }) | ||
186 | } else { | ||
187 | None | ||
188 | }; | ||
189 | (points_to, problem) | ||
190 | } | ||
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module_tree.rs index ebaf5f47a..cd82f25db 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -1,17 +1,32 @@ | |||
1 | pub(super) mod imp; | 1 | use std::sync::Arc; |
2 | pub(super) mod nameres; | ||
3 | 2 | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
4 | use arrayvec::ArrayVec; | ||
5 | use relative_path::RelativePathBuf; | ||
6 | use ra_db::{FileId, SourceRootId, Cancelable, SourceRoot}; | ||
4 | use ra_syntax::{ | 7 | use ra_syntax::{ |
5 | algo::generate, | 8 | algo::generate, |
6 | ast::{self, AstNode, NameOwner}, | 9 | ast::{self, AstNode, NameOwner}, |
7 | SyntaxNode, | 10 | SyntaxNode, |
8 | }; | 11 | }; |
9 | use ra_arena::{Arena, RawId, impl_arena_id}; | 12 | use ra_arena::{Arena, RawId, impl_arena_id}; |
10 | use relative_path::RelativePathBuf; | ||
11 | 13 | ||
12 | use crate::{Name, HirDatabase, SourceItemId, SourceFileItemId, HirFileId}; | 14 | use crate::{Name, AsName, HirDatabase, SourceItemId, SourceFileItemId, HirFileId, Problem}; |
13 | 15 | ||
14 | pub use self::nameres::{ModuleScope, Resolution, Namespace, PerNs}; | 16 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
17 | pub enum Submodule { | ||
18 | Declaration(Name), | ||
19 | Definition(Name, ModuleSource), | ||
20 | } | ||
21 | |||
22 | impl Submodule { | ||
23 | fn name(&self) -> &Name { | ||
24 | match self { | ||
25 | Submodule::Declaration(name) => name, | ||
26 | Submodule::Definition(name, _) => name, | ||
27 | } | ||
28 | } | ||
29 | } | ||
15 | 30 | ||
16 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 31 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
17 | pub struct ModuleId(RawId); | 32 | pub struct ModuleId(RawId); |
@@ -34,7 +49,31 @@ pub struct ModuleTree { | |||
34 | links: Arena<LinkId, LinkData>, | 49 | links: Arena<LinkId, LinkData>, |
35 | } | 50 | } |
36 | 51 | ||
52 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
53 | pub struct ModuleData { | ||
54 | source: ModuleSource, | ||
55 | parent: Option<LinkId>, | ||
56 | children: Vec<LinkId>, | ||
57 | } | ||
58 | |||
59 | #[derive(Hash, Debug, PartialEq, Eq)] | ||
60 | struct LinkData { | ||
61 | owner: ModuleId, | ||
62 | name: Name, | ||
63 | points_to: Vec<ModuleId>, | ||
64 | problem: Option<Problem>, | ||
65 | } | ||
66 | |||
37 | impl ModuleTree { | 67 | impl ModuleTree { |
68 | pub(crate) fn module_tree_query( | ||
69 | db: &impl HirDatabase, | ||
70 | source_root: SourceRootId, | ||
71 | ) -> Cancelable<Arc<ModuleTree>> { | ||
72 | db.check_canceled()?; | ||
73 | let res = create_module_tree(db, source_root)?; | ||
74 | Ok(Arc::new(res)) | ||
75 | } | ||
76 | |||
38 | pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { | 77 | pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { |
39 | self.mods.iter().map(|(id, _)| id) | 78 | self.mods.iter().map(|(id, _)| id) |
40 | } | 79 | } |
@@ -58,17 +97,6 @@ pub(crate) enum ModuleSourceNode { | |||
58 | Module(ast::ModuleNode), | 97 | Module(ast::ModuleNode), |
59 | } | 98 | } |
60 | 99 | ||
61 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | ||
62 | pub enum Problem { | ||
63 | UnresolvedModule { | ||
64 | candidate: RelativePathBuf, | ||
65 | }, | ||
66 | NotDirOwner { | ||
67 | move_to: RelativePathBuf, | ||
68 | candidate: RelativePathBuf, | ||
69 | }, | ||
70 | } | ||
71 | |||
72 | impl ModuleId { | 100 | impl ModuleId { |
73 | pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { | 101 | pub(crate) fn source(self, tree: &ModuleTree) -> ModuleSource { |
74 | tree.mods[self].source | 102 | tree.mods[self].source |
@@ -93,7 +121,10 @@ impl ModuleId { | |||
93 | .find(|it| it.name == *name)?; | 121 | .find(|it| it.name == *name)?; |
94 | Some(*link.points_to.first()?) | 122 | Some(*link.points_to.first()?) |
95 | } | 123 | } |
96 | fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (Name, ModuleId)> + 'a { | 124 | pub(crate) fn children<'a>( |
125 | self, | ||
126 | tree: &'a ModuleTree, | ||
127 | ) -> impl Iterator<Item = (Name, ModuleId)> + 'a { | ||
97 | tree.mods[self].children.iter().filter_map(move |&it| { | 128 | tree.mods[self].children.iter().filter_map(move |&it| { |
98 | let link = &tree.links[it]; | 129 | let link = &tree.links[it]; |
99 | let module = *link.points_to.first()?; | 130 | let module = *link.points_to.first()?; |
@@ -133,7 +164,7 @@ impl LinkId { | |||
133 | let owner = self.owner(tree); | 164 | let owner = self.owner(tree); |
134 | match owner.source(tree).resolve(db) { | 165 | match owner.source(tree).resolve(db) { |
135 | ModuleSourceNode::SourceFile(root) => { | 166 | ModuleSourceNode::SourceFile(root) => { |
136 | let ast = imp::modules(root.borrowed()) | 167 | let ast = modules(root.borrowed()) |
137 | .find(|(name, _)| name == &tree.links[self].name) | 168 | .find(|(name, _)| name == &tree.links[self].name) |
138 | .unwrap() | 169 | .unwrap() |
139 | .1; | 170 | .1; |
@@ -144,13 +175,6 @@ impl LinkId { | |||
144 | } | 175 | } |
145 | } | 176 | } |
146 | 177 | ||
147 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
148 | pub struct ModuleData { | ||
149 | source: ModuleSource, | ||
150 | parent: Option<LinkId>, | ||
151 | children: Vec<LinkId>, | ||
152 | } | ||
153 | |||
154 | impl ModuleSource { | 178 | impl ModuleSource { |
155 | // precondition: item_id **must** point to module | 179 | // precondition: item_id **must** point to module |
156 | fn new(file_id: HirFileId, item_id: Option<SourceFileItemId>) -> ModuleSource { | 180 | fn new(file_id: HirFileId, item_id: Option<SourceFileItemId>) -> ModuleSource { |
@@ -188,14 +212,6 @@ impl ModuleSource { | |||
188 | } | 212 | } |
189 | } | 213 | } |
190 | 214 | ||
191 | #[derive(Hash, Debug, PartialEq, Eq)] | ||
192 | struct LinkData { | ||
193 | owner: ModuleId, | ||
194 | name: Name, | ||
195 | points_to: Vec<ModuleId>, | ||
196 | problem: Option<Problem>, | ||
197 | } | ||
198 | |||
199 | impl ModuleTree { | 215 | impl ModuleTree { |
200 | fn push_mod(&mut self, data: ModuleData) -> ModuleId { | 216 | fn push_mod(&mut self, data: ModuleData) -> ModuleId { |
201 | self.mods.alloc(data) | 217 | self.mods.alloc(data) |
@@ -207,3 +223,153 @@ impl ModuleTree { | |||
207 | id | 223 | id |
208 | } | 224 | } |
209 | } | 225 | } |
226 | |||
227 | fn modules<'a>( | ||
228 | root: impl ast::ModuleItemOwner<'a>, | ||
229 | ) -> impl Iterator<Item = (Name, ast::Module<'a>)> { | ||
230 | root.items() | ||
231 | .filter_map(|item| match item { | ||
232 | ast::ModuleItem::Module(m) => Some(m), | ||
233 | _ => None, | ||
234 | }) | ||
235 | .filter_map(|module| { | ||
236 | let name = module.name()?.as_name(); | ||
237 | Some((name, module)) | ||
238 | }) | ||
239 | } | ||
240 | |||
241 | fn create_module_tree<'a>( | ||
242 | db: &impl HirDatabase, | ||
243 | source_root: SourceRootId, | ||
244 | ) -> Cancelable<ModuleTree> { | ||
245 | let mut tree = ModuleTree::default(); | ||
246 | |||
247 | let mut roots = FxHashMap::default(); | ||
248 | let mut visited = FxHashSet::default(); | ||
249 | |||
250 | let source_root = db.source_root(source_root); | ||
251 | for &file_id in source_root.files.values() { | ||
252 | let source = ModuleSource::new_file(file_id.into()); | ||
253 | if visited.contains(&source) { | ||
254 | continue; // TODO: use explicit crate_roots here | ||
255 | } | ||
256 | assert!(!roots.contains_key(&file_id)); | ||
257 | let module_id = build_subtree( | ||
258 | db, | ||
259 | &source_root, | ||
260 | &mut tree, | ||
261 | &mut visited, | ||
262 | &mut roots, | ||
263 | None, | ||
264 | source, | ||
265 | )?; | ||
266 | roots.insert(file_id, module_id); | ||
267 | } | ||
268 | Ok(tree) | ||
269 | } | ||
270 | |||
271 | fn build_subtree( | ||
272 | db: &impl HirDatabase, | ||
273 | source_root: &SourceRoot, | ||
274 | tree: &mut ModuleTree, | ||
275 | visited: &mut FxHashSet<ModuleSource>, | ||
276 | roots: &mut FxHashMap<FileId, ModuleId>, | ||
277 | parent: Option<LinkId>, | ||
278 | source: ModuleSource, | ||
279 | ) -> Cancelable<ModuleId> { | ||
280 | visited.insert(source); | ||
281 | let id = tree.push_mod(ModuleData { | ||
282 | source, | ||
283 | parent, | ||
284 | children: Vec::new(), | ||
285 | }); | ||
286 | for sub in db.submodules(source)?.iter() { | ||
287 | let link = tree.push_link(LinkData { | ||
288 | name: sub.name().clone(), | ||
289 | owner: id, | ||
290 | points_to: Vec::new(), | ||
291 | problem: None, | ||
292 | }); | ||
293 | |||
294 | let (points_to, problem) = match sub { | ||
295 | Submodule::Declaration(name) => { | ||
296 | let (points_to, problem) = resolve_submodule(db, source, &name); | ||
297 | let points_to = points_to | ||
298 | .into_iter() | ||
299 | .map(|file_id| match roots.remove(&file_id) { | ||
300 | Some(module_id) => { | ||
301 | tree.mods[module_id].parent = Some(link); | ||
302 | Ok(module_id) | ||
303 | } | ||
304 | None => build_subtree( | ||
305 | db, | ||
306 | source_root, | ||
307 | tree, | ||
308 | visited, | ||
309 | roots, | ||
310 | Some(link), | ||
311 | ModuleSource::new_file(file_id.into()), | ||
312 | ), | ||
313 | }) | ||
314 | .collect::<Cancelable<Vec<_>>>()?; | ||
315 | (points_to, problem) | ||
316 | } | ||
317 | Submodule::Definition(_name, submodule_source) => { | ||
318 | let points_to = build_subtree( | ||
319 | db, | ||
320 | source_root, | ||
321 | tree, | ||
322 | visited, | ||
323 | roots, | ||
324 | Some(link), | ||
325 | *submodule_source, | ||
326 | )?; | ||
327 | (vec![points_to], None) | ||
328 | } | ||
329 | }; | ||
330 | |||
331 | tree.links[link].points_to = points_to; | ||
332 | tree.links[link].problem = problem; | ||
333 | } | ||
334 | Ok(id) | ||
335 | } | ||
336 | |||
337 | fn resolve_submodule( | ||
338 | db: &impl HirDatabase, | ||
339 | source: ModuleSource, | ||
340 | name: &Name, | ||
341 | ) -> (Vec<FileId>, Option<Problem>) { | ||
342 | // FIXME: handle submodules of inline modules properly | ||
343 | let file_id = source.file_id().original_file(db); | ||
344 | let source_root_id = db.file_source_root(file_id); | ||
345 | let path = db.file_relative_path(file_id); | ||
346 | let root = RelativePathBuf::default(); | ||
347 | let dir_path = path.parent().unwrap_or(&root); | ||
348 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
349 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | ||
350 | |||
351 | let file_mod = dir_path.join(format!("{}.rs", name)); | ||
352 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | ||
353 | let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); | ||
354 | let mut candidates = ArrayVec::<[_; 2]>::new(); | ||
355 | if is_dir_owner { | ||
356 | candidates.push(file_mod.clone()); | ||
357 | candidates.push(dir_mod); | ||
358 | } else { | ||
359 | candidates.push(file_dir_mod.clone()); | ||
360 | }; | ||
361 | let sr = db.source_root(source_root_id); | ||
362 | let points_to = candidates | ||
363 | .into_iter() | ||
364 | .filter_map(|path| sr.files.get(&path)) | ||
365 | .map(|&it| it) | ||
366 | .collect::<Vec<_>>(); | ||
367 | let problem = if points_to.is_empty() { | ||
368 | Some(Problem::UnresolvedModule { | ||
369 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
370 | }) | ||
371 | } else { | ||
372 | None | ||
373 | }; | ||
374 | (points_to, problem) | ||
375 | } | ||
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/nameres.rs index 7d5e86c89..e65cbcb27 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -31,7 +31,7 @@ use crate::{ | |||
31 | Path, PathKind, | 31 | Path, PathKind, |
32 | HirDatabase, Crate, | 32 | HirDatabase, Crate, |
33 | Name, AsName, | 33 | Name, AsName, |
34 | module::{ModuleId, ModuleTree}, | 34 | module_tree::{ModuleId, ModuleTree}, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | /// Item map is the result of the name resolution. Item map contains, for each | 37 | /// Item map is the result of the name resolution. Item map contains, for each |
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index dcbe65aec..a6a0bea31 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -17,7 +17,7 @@ fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, hir::ModuleId) { | |||
17 | let module = hir::source_binder::module_from_position(&db, pos) | 17 | let module = hir::source_binder::module_from_position(&db, pos) |
18 | .unwrap() | 18 | .unwrap() |
19 | .unwrap(); | 19 | .unwrap(); |
20 | let module_id = module.def_id.loc(&db).module_id; | 20 | let module_id = module.module_id; |
21 | (db.item_map(source_root).unwrap(), module_id) | 21 | (db.item_map(source_root).unwrap(), module_id) |
22 | } | 22 | } |
23 | 23 | ||
@@ -155,7 +155,7 @@ fn item_map_across_crates() { | |||
155 | let module = hir::source_binder::module_from_file_id(&db, main_id) | 155 | let module = hir::source_binder::module_from_file_id(&db, main_id) |
156 | .unwrap() | 156 | .unwrap() |
157 | .unwrap(); | 157 | .unwrap(); |
158 | let module_id = module.def_id.loc(&db).module_id; | 158 | let module_id = module.module_id; |
159 | let item_map = db.item_map(source_root).unwrap(); | 159 | let item_map = db.item_map(source_root).unwrap(); |
160 | 160 | ||
161 | check_module_item_map( | 161 | check_module_item_map( |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index d9ee9d37f..b17c00e26 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -15,11 +15,8 @@ use crate::{ | |||
15 | MacroCallLoc, | 15 | MacroCallLoc, |
16 | db::HirDatabase, | 16 | db::HirDatabase, |
17 | function::FnScopes, | 17 | function::FnScopes, |
18 | module::{ | 18 | module_tree::{ModuleId, Submodule, ModuleSource, ModuleSourceNode}, |
19 | ModuleSource, ModuleSourceNode, ModuleId, | 19 | nameres::{InputModuleItems, ItemMap, Resolver}, |
20 | imp::Submodule, | ||
21 | nameres::{InputModuleItems, ItemMap, Resolver}, | ||
22 | }, | ||
23 | adt::{StructData, EnumData}, | 20 | adt::{StructData, EnumData}, |
24 | }; | 21 | }; |
25 | 22 | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ac097e81a..b7e3ff9b0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -14,7 +14,7 @@ use ra_syntax::{ | |||
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Function, SourceItemId, | 16 | HirDatabase, Function, SourceItemId, |
17 | module::ModuleSource, | 17 | module_tree::ModuleSource, |
18 | DefKind, DefLoc, AsName, | 18 | DefKind, DefLoc, AsName, |
19 | }; | 19 | }; |
20 | 20 | ||