diff options
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 50 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 51 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres/tests.rs | 7 |
3 files changed, 70 insertions, 38 deletions
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index 4a19842c4..f3a346152 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs | |||
@@ -4,9 +4,10 @@ use ra_syntax::{ | |||
4 | ast::{self, NameOwner}, | 4 | ast::{self, NameOwner}, |
5 | SmolStr, | 5 | SmolStr, |
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::{RelativePathBuf, RelativePath}; |
8 | use rustc_hash::{FxHashMap, FxHashSet}; | 8 | use rustc_hash::{FxHashMap, FxHashSet}; |
9 | use ra_db::{SourceRoot, SourceRootId, FileResolverImp, Cancelable, FileId,}; | 9 | use arrayvec::ArrayVec; |
10 | use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; | ||
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{ |
12 | HirDatabase, | 13 | HirDatabase, |
@@ -65,7 +66,7 @@ fn create_module_tree<'a>( | |||
65 | let mut visited = FxHashSet::default(); | 66 | let mut visited = FxHashSet::default(); |
66 | 67 | ||
67 | let source_root = db.source_root(source_root); | 68 | let source_root = db.source_root(source_root); |
68 | for &file_id in source_root.files.iter() { | 69 | for &file_id in source_root.files.values() { |
69 | let source = ModuleSource::new_file(file_id); | 70 | let source = ModuleSource::new_file(file_id); |
70 | if visited.contains(&source) { | 71 | if visited.contains(&source) { |
71 | continue; // TODO: use explicit crate_roots here | 72 | continue; // TODO: use explicit crate_roots here |
@@ -110,8 +111,7 @@ fn build_subtree( | |||
110 | 111 | ||
111 | let (points_to, problem) = match sub { | 112 | let (points_to, problem) = match sub { |
112 | Submodule::Declaration(name) => { | 113 | Submodule::Declaration(name) => { |
113 | let (points_to, problem) = | 114 | let (points_to, problem) = resolve_submodule(db, source, &name); |
114 | resolve_submodule(source, &name, &source_root.file_resolver); | ||
115 | let points_to = points_to | 115 | let points_to = points_to |
116 | .into_iter() | 116 | .into_iter() |
117 | .map(|file_id| match roots.remove(&file_id) { | 117 | .map(|file_id| match roots.remove(&file_id) { |
@@ -153,34 +153,42 @@ fn build_subtree( | |||
153 | } | 153 | } |
154 | 154 | ||
155 | fn resolve_submodule( | 155 | fn resolve_submodule( |
156 | db: &impl HirDatabase, | ||
156 | source: ModuleSource, | 157 | source: ModuleSource, |
157 | name: &SmolStr, | 158 | name: &SmolStr, |
158 | file_resolver: &FileResolverImp, | ||
159 | ) -> (Vec<FileId>, Option<Problem>) { | 159 | ) -> (Vec<FileId>, Option<Problem>) { |
160 | // TODO: handle submodules of inline modules properly | 160 | // FIXME: handle submodules of inline modules properly |
161 | let file_id = source.file_id(); | 161 | let file_id = source.file_id(); |
162 | let mod_name = file_resolver.file_stem(file_id); | 162 | let source_root_id = db.file_source_root(file_id); |
163 | let path = db.file_relative_path(file_id); | ||
164 | let root = RelativePathBuf::default(); | ||
165 | let dir_path = path.parent().unwrap_or(&root); | ||
166 | let mod_name = path.file_stem().unwrap_or("unknown"); | ||
163 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | 167 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; |
164 | 168 | ||
165 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); | 169 | let file_mod = dir_path.join(format!("{}.rs", name)); |
166 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); | 170 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); |
167 | let file_dir_mod = RelativePathBuf::from(format!("../{}/{}.rs", mod_name, name)); | 171 | let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name)); |
168 | let tmp1; | 172 | let mut candidates = ArrayVec::<[_; 2]>::new(); |
169 | let tmp2; | 173 | if is_dir_owner { |
170 | let candidates = if is_dir_owner { | 174 | candidates.push(file_mod.clone()); |
171 | tmp1 = [&file_mod, &dir_mod]; | 175 | candidates.push(dir_mod); |
172 | tmp1.iter() | ||
173 | } else { | 176 | } else { |
174 | tmp2 = [&file_dir_mod]; | 177 | candidates.push(file_dir_mod.clone()); |
175 | tmp2.iter() | ||
176 | }; | 178 | }; |
177 | 179 | let sr = db.source_root(source_root_id); | |
178 | let points_to = candidates | 180 | let points_to = candidates |
179 | .filter_map(|path| file_resolver.resolve(file_id, path)) | 181 | .into_iter() |
182 | .filter_map(|path| sr.files.get(&path)) | ||
183 | .map(|&it| it) | ||
180 | .collect::<Vec<_>>(); | 184 | .collect::<Vec<_>>(); |
181 | let problem = if points_to.is_empty() { | 185 | let problem = if points_to.is_empty() { |
182 | Some(Problem::UnresolvedModule { | 186 | Some(Problem::UnresolvedModule { |
183 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | 187 | candidate: RelativePath::new("../").join(&if is_dir_owner { |
188 | file_mod | ||
189 | } else { | ||
190 | file_dir_mod | ||
191 | }), | ||
184 | }) | 192 | }) |
185 | } else { | 193 | } else { |
186 | None | 194 | None |
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 5540b827f..f44abc730 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -32,11 +32,12 @@ use crate::{ | |||
32 | SourceItemId, SourceFileItemId, SourceFileItems, | 32 | SourceItemId, SourceFileItemId, SourceFileItems, |
33 | Path, PathKind, | 33 | Path, PathKind, |
34 | HirDatabase, Crate, | 34 | HirDatabase, Crate, |
35 | module::{ModuleId, ModuleTree}, | 35 | module::{Module, ModuleId, ModuleTree}, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /// Item map is the result of the name resolution. Item map contains, for each | 38 | /// Item map is the result of the name resolution. Item map contains, for each |
39 | /// module, the set of visible items. | 39 | /// module, the set of visible items. |
40 | // FIXME: currenty we compute item map per source-root. We should do it per crate instead. | ||
40 | #[derive(Default, Debug, PartialEq, Eq)] | 41 | #[derive(Default, Debug, PartialEq, Eq)] |
41 | pub struct ItemMap { | 42 | pub struct ItemMap { |
42 | pub per_module: FxHashMap<ModuleId, ModuleScope>, | 43 | pub per_module: FxHashMap<ModuleId, ModuleScope>, |
@@ -252,7 +253,8 @@ where | |||
252 | let krate = Crate::new(crate_id); | 253 | let krate = Crate::new(crate_id); |
253 | for dep in krate.dependencies(self.db) { | 254 | for dep in krate.dependencies(self.db) { |
254 | if let Some(module) = dep.krate.root_module(self.db)? { | 255 | if let Some(module) = dep.krate.root_module(self.db)? { |
255 | self.add_module_item(&mut module_items, dep.name, module.module_id); | 256 | let def_id = module.def_id(self.db); |
257 | self.add_module_item(&mut module_items, dep.name, def_id); | ||
256 | } | 258 | } |
257 | } | 259 | } |
258 | }; | 260 | }; |
@@ -294,21 +296,21 @@ where | |||
294 | 296 | ||
295 | // Populate modules | 297 | // Populate modules |
296 | for (name, module_id) in module_id.children(&self.module_tree) { | 298 | for (name, module_id) in module_id.children(&self.module_tree) { |
297 | self.add_module_item(&mut module_items, name, module_id); | 299 | let def_loc = DefLoc { |
300 | kind: DefKind::Module, | ||
301 | source_root_id: self.source_root, | ||
302 | module_id, | ||
303 | source_item_id: module_id.source(&self.module_tree).0, | ||
304 | }; | ||
305 | let def_id = def_loc.id(self.db); | ||
306 | self.add_module_item(&mut module_items, name, def_id); | ||
298 | } | 307 | } |
299 | 308 | ||
300 | self.result.per_module.insert(module_id, module_items); | 309 | self.result.per_module.insert(module_id, module_items); |
301 | Ok(()) | 310 | Ok(()) |
302 | } | 311 | } |
303 | 312 | ||
304 | fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, module_id: ModuleId) { | 313 | fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: DefId) { |
305 | let def_loc = DefLoc { | ||
306 | kind: DefKind::Module, | ||
307 | source_root_id: self.source_root, | ||
308 | module_id, | ||
309 | source_item_id: module_id.source(&self.module_tree).0, | ||
310 | }; | ||
311 | let def_id = def_loc.id(self.db); | ||
312 | let resolution = Resolution { | 314 | let resolution = Resolution { |
313 | def_id: Some(def_id), | 315 | def_id: Some(def_id), |
314 | import: None, | 316 | import: None, |
@@ -329,7 +331,7 @@ where | |||
329 | ImportKind::Named(ptr) => ptr, | 331 | ImportKind::Named(ptr) => ptr, |
330 | }; | 332 | }; |
331 | 333 | ||
332 | let mut curr = match import.path.kind { | 334 | let mut curr: ModuleId = match import.path.kind { |
333 | PathKind::Plain | PathKind::Self_ => module_id, | 335 | PathKind::Plain | PathKind::Self_ => module_id, |
334 | PathKind::Super => { | 336 | PathKind::Super => { |
335 | match module_id.parent(&self.module_tree) { | 337 | match module_id.parent(&self.module_tree) { |
@@ -356,9 +358,30 @@ where | |||
356 | curr = match def_id.loc(self.db) { | 358 | curr = match def_id.loc(self.db) { |
357 | DefLoc { | 359 | DefLoc { |
358 | kind: DefKind::Module, | 360 | kind: DefKind::Module, |
359 | module_id, | 361 | module_id: target_module_id, |
362 | source_root_id, | ||
360 | .. | 363 | .. |
361 | } => module_id, | 364 | } => { |
365 | if source_root_id == self.source_root { | ||
366 | target_module_id | ||
367 | } else { | ||
368 | let module = Module::new(self.db, source_root_id, target_module_id)?; | ||
369 | let path = Path { | ||
370 | segments: import.path.segments[i + 1..].iter().cloned().collect(), | ||
371 | kind: PathKind::Crate, | ||
372 | }; | ||
373 | if let Some(def_id) = module.resolve_path(self.db, path)? { | ||
374 | self.update(module_id, |items| { | ||
375 | let res = Resolution { | ||
376 | def_id: Some(def_id), | ||
377 | import: Some(ptr), | ||
378 | }; | ||
379 | items.items.insert(name.clone(), res); | ||
380 | }) | ||
381 | } | ||
382 | return Ok(()); | ||
383 | } | ||
384 | } | ||
362 | _ => return Ok(()), | 385 | _ => return Ok(()), |
363 | } | 386 | } |
364 | } else { | 387 | } else { |
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs index 9ddc32dcd..9fa9146e3 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/module/nameres/tests.rs | |||
@@ -3,6 +3,7 @@ use std::sync::Arc; | |||
3 | use salsa::Database; | 3 | use salsa::Database; |
4 | use ra_db::{FilesDatabase, CrateGraph}; | 4 | use ra_db::{FilesDatabase, CrateGraph}; |
5 | use ra_syntax::SmolStr; | 5 | use ra_syntax::SmolStr; |
6 | use relative_path::RelativePath; | ||
6 | 7 | ||
7 | use crate::{ | 8 | use crate::{ |
8 | self as hir, | 9 | self as hir, |
@@ -44,7 +45,7 @@ fn item_map_smoke_test() { | |||
44 | 45 | ||
45 | #[test] | 46 | #[test] |
46 | fn item_map_across_crates() { | 47 | fn item_map_across_crates() { |
47 | let (mut db, files) = MockDatabase::with_files( | 48 | let (mut db, sr) = MockDatabase::with_files( |
48 | " | 49 | " |
49 | //- /main.rs | 50 | //- /main.rs |
50 | use test_crate::Baz; | 51 | use test_crate::Baz; |
@@ -53,8 +54,8 @@ fn item_map_across_crates() { | |||
53 | pub struct Baz; | 54 | pub struct Baz; |
54 | ", | 55 | ", |
55 | ); | 56 | ); |
56 | let main_id = files.file_id("/main.rs"); | 57 | let main_id = sr.files[RelativePath::new("/main.rs")]; |
57 | let lib_id = files.file_id("/lib.rs"); | 58 | let lib_id = sr.files[RelativePath::new("/lib.rs")]; |
58 | 59 | ||
59 | let mut crate_graph = CrateGraph::default(); | 60 | let mut crate_graph = CrateGraph::default(); |
60 | let main_crate = crate_graph.add_crate_root(main_id); | 61 | let main_crate = crate_graph.add_crate_root(main_id); |