aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/src/find_path.rs99
-rw-r--r--crates/ra_hir_def/src/marks.rs1
2 files changed, 86 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index 8cc2fb160..43b9b124a 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -7,10 +7,39 @@ use crate::{
7 visibility::Visibility, 7 visibility::Visibility,
8 CrateId, ModuleDefId, ModuleId, 8 CrateId, ModuleDefId, ModuleId,
9}; 9};
10use hir_expand::name::Name; 10use hir_expand::name::{known, Name};
11use test_utils::tested_by;
11 12
12const MAX_PATH_LEN: usize = 15; 13const MAX_PATH_LEN: usize = 15;
13 14
15impl ModPath {
16 fn starts_with_std(&self) -> bool {
17 self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some()
18 }
19
20 // When std library is present, paths starting with `std::`
21 // should be preferred over paths starting with `core::` and `alloc::`
22 fn should_start_with_std(&self) -> bool {
23 self.segments
24 .first()
25 .filter(|&first_segment| {
26 first_segment == &known::alloc || first_segment == &known::core
27 })
28 .is_some()
29 }
30
31 fn len(&self) -> usize {
32 self.segments.len()
33 + match self.kind {
34 PathKind::Plain => 0,
35 PathKind::Super(i) => i as usize,
36 PathKind::Crate => 1,
37 PathKind::Abs => 0,
38 PathKind::DollarCrate(_) => 1,
39 }
40 }
41}
42
14// FIXME: handle local items 43// FIXME: handle local items
15 44
16/// Find a path that can be used to refer to a certain item. This can depend on 45/// Find a path that can be used to refer to a certain item. This can depend on
@@ -112,23 +141,27 @@ fn find_path_inner(
112 Some(path) => path, 141 Some(path) => path,
113 }; 142 };
114 path.segments.push(name); 143 path.segments.push(name);
115 if path_len(&path) < best_path_len { 144
116 best_path_len = path_len(&path); 145 let new_path =
117 best_path = Some(path); 146 if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path };
118 } 147 best_path_len = new_path.len();
148 best_path = Some(new_path);
119 } 149 }
120 best_path 150 best_path
121} 151}
122 152
123fn path_len(path: &ModPath) -> usize { 153fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath {
124 path.segments.len() 154 if old_path.starts_with_std() && new_path.should_start_with_std() {
125 + match path.kind { 155 tested_by!(prefer_std_paths);
126 PathKind::Plain => 0, 156 old_path
127 PathKind::Super(i) => i as usize, 157 } else if new_path.starts_with_std() && old_path.should_start_with_std() {
128 PathKind::Crate => 1, 158 tested_by!(prefer_std_paths);
129 PathKind::Abs => 0, 159 new_path
130 PathKind::DollarCrate(_) => 1, 160 } else if new_path.len() < old_path.len() {
131 } 161 new_path
162 } else {
163 old_path
164 }
132} 165}
133 166
134fn find_importable_locations( 167fn find_importable_locations(
@@ -201,6 +234,7 @@ mod tests {
201 use hir_expand::hygiene::Hygiene; 234 use hir_expand::hygiene::Hygiene;
202 use ra_db::fixture::WithFixture; 235 use ra_db::fixture::WithFixture;
203 use ra_syntax::ast::AstNode; 236 use ra_syntax::ast::AstNode;
237 use test_utils::covers;
204 238
205 /// `code` needs to contain a cursor marker; checks that `find_path` for the 239 /// `code` needs to contain a cursor marker; checks that `find_path` for the
206 /// item the `path` refers to returns that same path when called from the 240 /// item the `path` refers to returns that same path when called from the
@@ -452,4 +486,41 @@ mod tests {
452 "#; 486 "#;
453 check_found_path(code, "crate::foo::S"); 487 check_found_path(code, "crate::foo::S");
454 } 488 }
489
490 #[test]
491 fn prefer_std_paths_over_alloc() {
492 covers!(prefer_std_paths);
493 let code = r#"
494 //- /main.rs crate:main deps:alloc,std
495 <|>
496
497 //- /std.rs crate:std deps:alloc
498 pub mod sync {
499 pub use alloc::sync::Arc;
500 }
501
502 //- /zzz.rs crate:alloc
503 pub mod sync {
504 pub struct Arc;
505 }
506 "#;
507 check_found_path(code, "std::sync::Arc");
508 }
509
510 #[test]
511 fn prefer_shorter_paths_if_not_alloc() {
512 let code = r#"
513 //- /main.rs crate:main deps:megaalloc,std
514 <|>
515
516 //- /std.rs crate:std deps:megaalloc
517 pub mod sync {
518 pub use megaalloc::sync::Arc;
519 }
520
521 //- /zzz.rs crate:megaalloc
522 pub struct Arc;
523 "#;
524 check_found_path(code, "megaalloc::Arc");
525 }
455} 526}
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
index 457ba4abe..daa49d5f1 100644
--- a/crates/ra_hir_def/src/marks.rs
+++ b/crates/ra_hir_def/src/marks.rs
@@ -13,4 +13,5 @@ test_utils::marks!(
13 macro_dollar_crate_self 13 macro_dollar_crate_self
14 macro_dollar_crate_other 14 macro_dollar_crate_other
15 infer_resolve_while_let 15 infer_resolve_while_let
16 prefer_std_paths
16); 17);