aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/find_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/find_path.rs')
-rw-r--r--crates/ra_hir_def/src/find_path.rs59
1 files changed, 51 insertions, 8 deletions
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index a7f59e028..06701a830 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -159,10 +159,16 @@ fn find_path_inner(
159 let crate_graph = db.crate_graph(); 159 let crate_graph = db.crate_graph();
160 let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| { 160 let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| {
161 let import_map = db.import_map(dep.crate_id); 161 let import_map = db.import_map(dep.crate_id);
162 import_map.path_of(item).map(|modpath| { 162 import_map.import_info_for(item).and_then(|info| {
163 let mut modpath = modpath.clone(); 163 // Determine best path for containing module and append last segment from `info`.
164 modpath.segments.insert(0, dep.as_name()); 164 let mut path = find_path_inner(
165 modpath 165 db,
166 ItemInNs::Types(ModuleDefId::ModuleId(info.container)),
167 from,
168 best_path_len - 1,
169 )?;
170 path.segments.push(info.path.segments.last().unwrap().clone());
171 Some(path)
166 }) 172 })
167 }); 173 });
168 174
@@ -299,8 +305,8 @@ mod tests {
299 /// `code` needs to contain a cursor marker; checks that `find_path` for the 305 /// `code` needs to contain a cursor marker; checks that `find_path` for the
300 /// item the `path` refers to returns that same path when called from the 306 /// item the `path` refers to returns that same path when called from the
301 /// module the cursor is in. 307 /// module the cursor is in.
302 fn check_found_path(code: &str, path: &str) { 308 fn check_found_path(ra_fixture: &str, path: &str) {
303 let (db, pos) = TestDB::with_position(code); 309 let (db, pos) = TestDB::with_position(ra_fixture);
304 let module = db.module_for_file(pos.file_id); 310 let module = db.module_for_file(pos.file_id);
305 let parsed_path_file = ra_syntax::SourceFile::parse(&format!("use {};", path)); 311 let parsed_path_file = ra_syntax::SourceFile::parse(&format!("use {};", path));
306 let ast_path = parsed_path_file 312 let ast_path = parsed_path_file
@@ -420,7 +426,6 @@ mod tests {
420 426
421 #[test] 427 #[test]
422 fn different_crate_renamed() { 428 fn different_crate_renamed() {
423 // Even if a local path exists, if the item is defined externally, prefer an external path.
424 let code = r#" 429 let code = r#"
425 //- /main.rs crate:main deps:std 430 //- /main.rs crate:main deps:std
426 extern crate std as std_renamed; 431 extern crate std as std_renamed;
@@ -428,7 +433,45 @@ mod tests {
428 //- /std.rs crate:std 433 //- /std.rs crate:std
429 pub struct S; 434 pub struct S;
430 "#; 435 "#;
431 check_found_path(code, "std::S"); 436 check_found_path(code, "std_renamed::S");
437 }
438
439 #[test]
440 fn partially_imported() {
441 // Tests that short paths are used even for external items, when parts of the path are
442 // already in scope.
443 check_found_path(
444 r#"
445 //- /main.rs crate:main deps:ra_syntax
446
447 use ra_syntax::ast;
448 <|>
449
450 //- /lib.rs crate:ra_syntax
451 pub mod ast {
452 pub enum ModuleItem {
453 A, B, C,
454 }
455 }
456 "#,
457 "ast::ModuleItem",
458 );
459
460 check_found_path(
461 r#"
462 //- /main.rs crate:main deps:ra_syntax
463
464 <|>
465
466 //- /lib.rs crate:ra_syntax
467 pub mod ast {
468 pub enum ModuleItem {
469 A, B, C,
470 }
471 }
472 "#,
473 "ra_syntax::ast::ModuleItem",
474 );
432 } 475 }
433 476
434 #[test] 477 #[test]