aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/find_path.rs
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-01-28 15:19:41 +0000
committerKirill Bulatov <[email protected]>2020-01-28 15:19:41 +0000
commit762d2935818bbd2639a19b1994b2ddfeac5529b2 (patch)
tree49f4f5f3589a5a60d73e0ea662b5edac6c6700d2 /crates/ra_hir_def/src/find_path.rs
parent7a2e449424227c7f6cebe0581513287023297999 (diff)
Apply the proposed refactoring
Diffstat (limited to 'crates/ra_hir_def/src/find_path.rs')
-rw-r--r--crates/ra_hir_def/src/find_path.rs81
1 files changed, 43 insertions, 38 deletions
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index d9e67607f..ebfd6e211 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -11,6 +11,34 @@ use hir_expand::name::{known, Name};
11 11
12const MAX_PATH_LEN: usize = 15; 12const MAX_PATH_LEN: usize = 15;
13 13
14impl ModPath {
15 fn starts_with_std(&self) -> bool {
16 self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some()
17 }
18
19 // When std library is present, paths starting with `std::`
20 // should be preferred over paths starting with `core::` and `alloc::`
21 fn should_start_with_std(&self) -> bool {
22 self.segments
23 .first()
24 .filter(|&first_segment| {
25 first_segment == &known::alloc || first_segment == &known::core
26 })
27 .is_some()
28 }
29
30 fn len(&self) -> usize {
31 self.segments.len()
32 + match self.kind {
33 PathKind::Plain => 0,
34 PathKind::Super(i) => i as usize,
35 PathKind::Crate => 1,
36 PathKind::Abs => 0,
37 PathKind::DollarCrate(_) => 1,
38 }
39 }
40}
41
14// FIXME: handle local items 42// FIXME: handle local items
15 43
16/// Find a path that can be used to refer to a certain item. This can depend on 44/// Find a path that can be used to refer to a certain item. This can depend on
@@ -102,7 +130,7 @@ fn find_path_inner(
102 let mut best_path = None; 130 let mut best_path = None;
103 let mut best_path_len = max_len; 131 let mut best_path_len = max_len;
104 for (module_id, name) in importable_locations { 132 for (module_id, name) in importable_locations {
105 let mut new_path = match find_path_inner( 133 let mut path = match find_path_inner(
106 db, 134 db,
107 ItemInNs::Types(ModuleDefId::ModuleId(module_id)), 135 ItemInNs::Types(ModuleDefId::ModuleId(module_id)),
108 from, 136 from,
@@ -111,51 +139,28 @@ fn find_path_inner(
111 None => continue, 139 None => continue,
112 Some(path) => path, 140 Some(path) => path,
113 }; 141 };
114 new_path.segments.push(name); 142 path.segments.push(name);
115 143
116 if prefer_new_path(best_path_len, best_path.as_ref(), &new_path) { 144 let new_path =
117 best_path_len = path_len(&new_path); 145 if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path };
118 best_path = Some(new_path); 146 best_path_len = new_path.len();
119 } 147 best_path = Some(new_path);
120 } 148 }
121 best_path 149 best_path
122} 150}
123 151
124fn prefer_new_path(old_path_len: usize, old_path: Option<&ModPath>, new_path: &ModPath) -> bool { 152fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath {
125 match (old_path.and_then(|mod_path| mod_path.segments.first()), new_path.segments.first()) { 153 if old_path.starts_with_std() && new_path.should_start_with_std() {
126 (Some(old_path_start), Some(new_path_start)) 154 old_path
127 if old_path_start == &known::std && use_std_instead(new_path_start) => 155 } else if new_path.starts_with_std() && old_path.should_start_with_std() {
128 { 156 new_path
129 false 157 } else if new_path.len() < old_path.len() {
130 } 158 new_path
131 (Some(old_path_start), Some(new_path_start)) 159 } else {
132 if new_path_start == &known::std && use_std_instead(old_path_start) => 160 old_path
133 {
134 true
135 }
136 (None, Some(_)) => true,
137 (Some(_), None) => false,
138 _ => path_len(new_path) < old_path_len,
139 } 161 }
140} 162}
141 163
142// When std library is present, paths starting with `std::`
143// should be preferred over paths starting with `core::` and `alloc::`
144fn use_std_instead(name: &Name) -> bool {
145 name == &known::core || name == &known::alloc
146}
147
148fn path_len(path: &ModPath) -> usize {
149 path.segments.len()
150 + match path.kind {
151 PathKind::Plain => 0,
152 PathKind::Super(i) => i as usize,
153 PathKind::Crate => 1,
154 PathKind::Abs => 0,
155 PathKind::DollarCrate(_) => 1,
156 }
157}
158
159fn find_importable_locations( 164fn find_importable_locations(
160 db: &impl DefDatabase, 165 db: &impl DefDatabase,
161 item: ItemInNs, 166 item: ItemInNs,