diff options
author | Jonas Schievink <[email protected]> | 2020-06-12 12:01:20 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2020-06-12 12:01:20 +0100 |
commit | 0231e4ac77dacf6ca30f6b68c6081415f2da54ba (patch) | |
tree | 21b1df550c05bae5b9d9ff23107e69727605c552 /crates/ra_hir_def/src/import_map.rs | |
parent | 36353bb1827dbd2efcde2d18c8598c4cc5e2e296 (diff) |
find_path: return shorter paths for external items
If a containing module is already in scope, there's no need to
use the full path to the item.
Diffstat (limited to 'crates/ra_hir_def/src/import_map.rs')
-rw-r--r-- | crates/ra_hir_def/src/import_map.rs | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/crates/ra_hir_def/src/import_map.rs b/crates/ra_hir_def/src/import_map.rs index 36b4fdd81..68e20d06b 100644 --- a/crates/ra_hir_def/src/import_map.rs +++ b/crates/ra_hir_def/src/import_map.rs | |||
@@ -17,6 +17,15 @@ use crate::{ | |||
17 | 17 | ||
18 | type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; | 18 | type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; |
19 | 19 | ||
20 | /// Item import details stored in the `ImportMap`. | ||
21 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
22 | pub struct ImportInfo { | ||
23 | /// A path that can be used to import the item, relative to the crate's root. | ||
24 | pub path: ModPath, | ||
25 | /// The module containing this item. | ||
26 | pub container: ModuleId, | ||
27 | } | ||
28 | |||
20 | /// A map from publicly exported items to the path needed to import/name them from a downstream | 29 | /// A map from publicly exported items to the path needed to import/name them from a downstream |
21 | /// crate. | 30 | /// crate. |
22 | /// | 31 | /// |
@@ -26,7 +35,7 @@ type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; | |||
26 | /// Note that all paths are relative to the containing crate's root, so the crate name still needs | 35 | /// Note that all paths are relative to the containing crate's root, so the crate name still needs |
27 | /// to be prepended to the `ModPath` before the path is valid. | 36 | /// to be prepended to the `ModPath` before the path is valid. |
28 | pub struct ImportMap { | 37 | pub struct ImportMap { |
29 | map: FxIndexMap<ItemInNs, ModPath>, | 38 | map: FxIndexMap<ItemInNs, ImportInfo>, |
30 | 39 | ||
31 | /// List of keys stored in `map`, sorted lexicographically by their `ModPath`. Indexed by the | 40 | /// List of keys stored in `map`, sorted lexicographically by their `ModPath`. Indexed by the |
32 | /// values returned by running `fst`. | 41 | /// values returned by running `fst`. |
@@ -78,12 +87,12 @@ impl ImportMap { | |||
78 | let path = mk_path(); | 87 | let path = mk_path(); |
79 | match import_map.entry(item) { | 88 | match import_map.entry(item) { |
80 | Entry::Vacant(entry) => { | 89 | Entry::Vacant(entry) => { |
81 | entry.insert(path); | 90 | entry.insert(ImportInfo { path, container: module }); |
82 | } | 91 | } |
83 | Entry::Occupied(mut entry) => { | 92 | Entry::Occupied(mut entry) => { |
84 | // If the new path is shorter, prefer that one. | 93 | // If the new path is shorter, prefer that one. |
85 | if path.len() < entry.get().len() { | 94 | if path.len() < entry.get().path.len() { |
86 | *entry.get_mut() = path; | 95 | *entry.get_mut() = ImportInfo { path, container: module }; |
87 | } else { | 96 | } else { |
88 | continue; | 97 | continue; |
89 | } | 98 | } |
@@ -119,7 +128,7 @@ impl ImportMap { | |||
119 | let start = last_batch_start; | 128 | let start = last_batch_start; |
120 | last_batch_start = idx + 1; | 129 | last_batch_start = idx + 1; |
121 | 130 | ||
122 | let key = fst_path(&importables[start].1); | 131 | let key = fst_path(&importables[start].1.path); |
123 | 132 | ||
124 | builder.insert(key, start as u64).unwrap(); | 133 | builder.insert(key, start as u64).unwrap(); |
125 | } | 134 | } |
@@ -132,6 +141,10 @@ impl ImportMap { | |||
132 | 141 | ||
133 | /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. | 142 | /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. |
134 | pub fn path_of(&self, item: ItemInNs) -> Option<&ModPath> { | 143 | pub fn path_of(&self, item: ItemInNs) -> Option<&ModPath> { |
144 | Some(&self.map.get(&item)?.path) | ||
145 | } | ||
146 | |||
147 | pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> { | ||
135 | self.map.get(&item) | 148 | self.map.get(&item) |
136 | } | 149 | } |
137 | } | 150 | } |
@@ -150,13 +163,13 @@ impl fmt::Debug for ImportMap { | |||
150 | let mut importable_paths: Vec<_> = self | 163 | let mut importable_paths: Vec<_> = self |
151 | .map | 164 | .map |
152 | .iter() | 165 | .iter() |
153 | .map(|(item, modpath)| { | 166 | .map(|(item, info)| { |
154 | let ns = match item { | 167 | let ns = match item { |
155 | ItemInNs::Types(_) => "t", | 168 | ItemInNs::Types(_) => "t", |
156 | ItemInNs::Values(_) => "v", | 169 | ItemInNs::Values(_) => "v", |
157 | ItemInNs::Macros(_) => "m", | 170 | ItemInNs::Macros(_) => "m", |
158 | }; | 171 | }; |
159 | format!("- {} ({})", modpath, ns) | 172 | format!("- {} ({})", info.path, ns) |
160 | }) | 173 | }) |
161 | .collect(); | 174 | .collect(); |
162 | 175 | ||
@@ -171,9 +184,9 @@ fn fst_path(path: &ModPath) -> String { | |||
171 | s | 184 | s |
172 | } | 185 | } |
173 | 186 | ||
174 | fn cmp((_, lhs): &(&ItemInNs, &ModPath), (_, rhs): &(&ItemInNs, &ModPath)) -> Ordering { | 187 | fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo)) -> Ordering { |
175 | let lhs_str = fst_path(lhs); | 188 | let lhs_str = fst_path(&lhs.path); |
176 | let rhs_str = fst_path(rhs); | 189 | let rhs_str = fst_path(&rhs.path); |
177 | lhs_str.cmp(&rhs_str) | 190 | lhs_str.cmp(&rhs_str) |
178 | } | 191 | } |
179 | 192 | ||
@@ -243,7 +256,7 @@ pub fn search_dependencies<'a>( | |||
243 | let importables = &import_map.importables[indexed_value.value as usize..]; | 256 | let importables = &import_map.importables[indexed_value.value as usize..]; |
244 | 257 | ||
245 | // Path shared by the importable items in this group. | 258 | // Path shared by the importable items in this group. |
246 | let path = &import_map.map[&importables[0]]; | 259 | let path = &import_map.map[&importables[0]].path; |
247 | 260 | ||
248 | if query.anchor_end { | 261 | if query.anchor_end { |
249 | // Last segment must match query. | 262 | // Last segment must match query. |
@@ -256,14 +269,14 @@ pub fn search_dependencies<'a>( | |||
256 | // Add the items from this `ModPath` group. Those are all subsequent items in | 269 | // Add the items from this `ModPath` group. Those are all subsequent items in |
257 | // `importables` whose paths match `path`. | 270 | // `importables` whose paths match `path`. |
258 | let iter = importables.iter().copied().take_while(|item| { | 271 | let iter = importables.iter().copied().take_while(|item| { |
259 | let item_path = &import_map.map[item]; | 272 | let item_path = &import_map.map[item].path; |
260 | fst_path(item_path) == fst_path(path) | 273 | fst_path(item_path) == fst_path(path) |
261 | }); | 274 | }); |
262 | 275 | ||
263 | if query.case_sensitive { | 276 | if query.case_sensitive { |
264 | // FIXME: This does not do a subsequence match. | 277 | // FIXME: This does not do a subsequence match. |
265 | res.extend(iter.filter(|item| { | 278 | res.extend(iter.filter(|item| { |
266 | let item_path = &import_map.map[item]; | 279 | let item_path = &import_map.map[item].path; |
267 | item_path.to_string().contains(&query.query) | 280 | item_path.to_string().contains(&query.query) |
268 | })); | 281 | })); |
269 | } else { | 282 | } else { |