aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/find_path.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index afcf04280..f7fd0c00a 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -10,7 +10,6 @@ use hir_expand::name::Name;
10 10
11// TODO don't import from super imports? or at least deprioritize 11// TODO don't import from super imports? or at least deprioritize
12// TODO use super? 12// TODO use super?
13// TODO use shortest path
14// TODO performance / memoize 13// TODO performance / memoize
15 14
16pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 15pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
@@ -61,7 +60,7 @@ pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Optio
61 60
62 // - otherwise, look for modules containing (reexporting) it and import it from one of those 61 // - otherwise, look for modules containing (reexporting) it and import it from one of those
63 let importable_locations = find_importable_locations(db, item, from); 62 let importable_locations = find_importable_locations(db, item, from);
64 // XXX going in order for now 63 let mut candidate_paths = Vec::new();
65 for (module_id, name) in importable_locations { 64 for (module_id, name) in importable_locations {
66 // TODO prevent infinite loops 65 // TODO prevent infinite loops
67 let mut path = match find_path(db, ItemInNs::Types(ModuleDefId::ModuleId(module_id)), from) { 66 let mut path = match find_path(db, ItemInNs::Types(ModuleDefId::ModuleId(module_id)), from) {
@@ -69,9 +68,9 @@ pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Optio
69 Some(path) => path, 68 Some(path) => path,
70 }; 69 };
71 path.segments.push(name); 70 path.segments.push(name);
72 return Some(path); 71 candidate_paths.push(path);
73 } 72 }
74 None 73 candidate_paths.into_iter().min_by_key(|path| path.segments.len())
75} 74}
76 75
77fn find_importable_locations(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Vec<(ModuleId, Name)> { 76fn find_importable_locations(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Vec<(ModuleId, Name)> {
@@ -275,4 +274,20 @@ mod tests {
275 check_found_path(code, "None"); 274 check_found_path(code, "None");
276 check_found_path(code, "Some"); 275 check_found_path(code, "Some");
277 } 276 }
277
278 #[test]
279 fn shortest_path() {
280 let code = r#"
281 //- /main.rs
282 pub mod foo;
283 pub mod baz;
284 struct S;
285 <|>
286 //- /foo.rs
287 pub mod bar { pub struct S; }
288 //- /baz.rs
289 pub use crate::foo::bar::S;
290 "#;
291 check_found_path(code, "baz::S");
292 }
278} 293}