diff options
-rw-r--r-- | crates/ra_hir_def/src/find_path.rs | 23 |
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 | ||
16 | pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 15 | pub 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 | ||
77 | fn find_importable_locations(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Vec<(ModuleId, Name)> { | 76 | fn 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 | } |