aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/module
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r--crates/ra_hir/src/module/imp.rs50
-rw-r--r--crates/ra_hir/src/module/nameres.rs51
-rw-r--r--crates/ra_hir/src/module/nameres/tests.rs7
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};
7use relative_path::RelativePathBuf; 7use relative_path::{RelativePathBuf, RelativePath};
8use rustc_hash::{FxHashMap, FxHashSet}; 8use rustc_hash::{FxHashMap, FxHashSet};
9use ra_db::{SourceRoot, SourceRootId, FileResolverImp, Cancelable, FileId,}; 9use arrayvec::ArrayVec;
10use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
10 11
11use crate::{ 12use 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
155fn resolve_submodule( 155fn 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)]
41pub struct ItemMap { 42pub 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;
3use salsa::Database; 3use salsa::Database;
4use ra_db::{FilesDatabase, CrateGraph}; 4use ra_db::{FilesDatabase, CrateGraph};
5use ra_syntax::SmolStr; 5use ra_syntax::SmolStr;
6use relative_path::RelativePath;
6 7
7use crate::{ 8use crate::{
8 self as hir, 9 self as hir,
@@ -44,7 +45,7 @@ fn item_map_smoke_test() {
44 45
45#[test] 46#[test]
46fn item_map_across_crates() { 47fn 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);