diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-10-20 18:03:19 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-10-20 18:03:19 +0100 |
commit | 989de9e3094f54dba81ae59f4bbaaf3a8c0d67d1 (patch) | |
tree | d9d931042534ef62c280b50792a29a8371266d96 /crates/assists/src/utils | |
parent | 20d369a826e8f333cba1988325480a49a730f00e (diff) | |
parent | 1d612a6ec48390c38d577cd35369e0891fe6cb6e (diff) |
Merge #6172
6172: Add qualify path assist r=matklad a=Veykril
This implements a `qualify_path` assist which works quite similar to the `auto_import` assist but instead of adding imports to the file it well, qualifies the path. This PR also moves out the `AutoImportAssets` struct and functions from `auto_import` into a utils submodule as most of this is now shared between `auto_import` and `qualify_path`.
Changes made to `AutoImportAssets` are solely in its `search_for_imports` function which now takes a prefixed parameter to discern between using `find_use_path_prefixed` and `find_use_path` as the former is the required behavior by `auto_import` and the latter by this assist.
For missing imported traits instead of importing this will qualify the path with a trait cast as in:
```rust
test_mod::TestStruct::TEST_CONST<|>
```
becomes
```rust
<test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST
```
and for trait methods ideally it would do the following:
```rust
let test_struct = test_mod::TestStruct {};
test_struct.test_meth<|>od()
```
becomes
```rust
let test_struct = test_mod::TestStruct {};
test_mod::TestTrait::test_method(&test_struct)
```
Fixes #4124.
Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/assists/src/utils')
-rw-r--r-- | crates/assists/src/utils/import_assets.rs | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/crates/assists/src/utils/import_assets.rs b/crates/assists/src/utils/import_assets.rs index 601f51098..23db3a74b 100644 --- a/crates/assists/src/utils/import_assets.rs +++ b/crates/assists/src/utils/import_assets.rs | |||
@@ -1,6 +1,4 @@ | |||
1 | //! Look up accessible paths for items. | 1 | //! Look up accessible paths for items. |
2 | use std::collections::BTreeSet; | ||
3 | |||
4 | use either::Either; | 2 | use either::Either; |
5 | use hir::{AsAssocItem, AssocItemContainer, ModuleDef, Semantics}; | 3 | use hir::{AsAssocItem, AssocItemContainer, ModuleDef, Semantics}; |
6 | use ide_db::{imports_locator, RootDatabase}; | 4 | use ide_db::{imports_locator, RootDatabase}; |
@@ -29,12 +27,12 @@ pub(crate) enum ImportCandidate { | |||
29 | #[derive(Debug)] | 27 | #[derive(Debug)] |
30 | pub(crate) struct TraitImportCandidate { | 28 | pub(crate) struct TraitImportCandidate { |
31 | pub ty: hir::Type, | 29 | pub ty: hir::Type, |
32 | pub name: String, | 30 | pub name: ast::NameRef, |
33 | } | 31 | } |
34 | 32 | ||
35 | #[derive(Debug)] | 33 | #[derive(Debug)] |
36 | pub(crate) struct PathImportCandidate { | 34 | pub(crate) struct PathImportCandidate { |
37 | pub name: String, | 35 | pub name: ast::NameRef, |
38 | } | 36 | } |
39 | 37 | ||
40 | #[derive(Debug)] | 38 | #[derive(Debug)] |
@@ -86,9 +84,9 @@ impl ImportAssets { | |||
86 | fn get_search_query(&self) -> &str { | 84 | fn get_search_query(&self) -> &str { |
87 | match &self.import_candidate { | 85 | match &self.import_candidate { |
88 | ImportCandidate::UnqualifiedName(candidate) | 86 | ImportCandidate::UnqualifiedName(candidate) |
89 | | ImportCandidate::QualifierStart(candidate) => &candidate.name, | 87 | | ImportCandidate::QualifierStart(candidate) => candidate.name.text(), |
90 | ImportCandidate::TraitAssocItem(candidate) | 88 | ImportCandidate::TraitAssocItem(candidate) |
91 | | ImportCandidate::TraitMethod(candidate) => &candidate.name, | 89 | | ImportCandidate::TraitMethod(candidate) => candidate.name.text(), |
92 | } | 90 | } |
93 | } | 91 | } |
94 | 92 | ||
@@ -96,7 +94,7 @@ impl ImportAssets { | |||
96 | &self, | 94 | &self, |
97 | sema: &Semantics<RootDatabase>, | 95 | sema: &Semantics<RootDatabase>, |
98 | config: &InsertUseConfig, | 96 | config: &InsertUseConfig, |
99 | ) -> BTreeSet<hir::ModPath> { | 97 | ) -> Vec<(hir::ModPath, hir::ItemInNs)> { |
100 | let _p = profile::span("import_assists::search_for_imports"); | 98 | let _p = profile::span("import_assists::search_for_imports"); |
101 | self.search_for(sema, Some(config.prefix_kind)) | 99 | self.search_for(sema, Some(config.prefix_kind)) |
102 | } | 100 | } |
@@ -106,7 +104,7 @@ impl ImportAssets { | |||
106 | pub(crate) fn search_for_relative_paths( | 104 | pub(crate) fn search_for_relative_paths( |
107 | &self, | 105 | &self, |
108 | sema: &Semantics<RootDatabase>, | 106 | sema: &Semantics<RootDatabase>, |
109 | ) -> BTreeSet<hir::ModPath> { | 107 | ) -> Vec<(hir::ModPath, hir::ItemInNs)> { |
110 | let _p = profile::span("import_assists::search_for_relative_paths"); | 108 | let _p = profile::span("import_assists::search_for_relative_paths"); |
111 | self.search_for(sema, None) | 109 | self.search_for(sema, None) |
112 | } | 110 | } |
@@ -115,7 +113,7 @@ impl ImportAssets { | |||
115 | &self, | 113 | &self, |
116 | sema: &Semantics<RootDatabase>, | 114 | sema: &Semantics<RootDatabase>, |
117 | prefixed: Option<hir::PrefixKind>, | 115 | prefixed: Option<hir::PrefixKind>, |
118 | ) -> BTreeSet<hir::ModPath> { | 116 | ) -> Vec<(hir::ModPath, hir::ItemInNs)> { |
119 | let db = sema.db; | 117 | let db = sema.db; |
120 | let mut trait_candidates = FxHashSet::default(); | 118 | let mut trait_candidates = FxHashSet::default(); |
121 | let current_crate = self.module_with_name_to_import.krate(); | 119 | let current_crate = self.module_with_name_to_import.krate(); |
@@ -181,7 +179,7 @@ impl ImportAssets { | |||
181 | } | 179 | } |
182 | }; | 180 | }; |
183 | 181 | ||
184 | imports_locator::find_imports(sema, current_crate, &self.get_search_query()) | 182 | let mut res = imports_locator::find_imports(sema, current_crate, &self.get_search_query()) |
185 | .into_iter() | 183 | .into_iter() |
186 | .filter_map(filter) | 184 | .filter_map(filter) |
187 | .filter_map(|candidate| { | 185 | .filter_map(|candidate| { |
@@ -191,10 +189,13 @@ impl ImportAssets { | |||
191 | } else { | 189 | } else { |
192 | self.module_with_name_to_import.find_use_path(db, item) | 190 | self.module_with_name_to_import.find_use_path(db, item) |
193 | } | 191 | } |
192 | .map(|path| (path, item)) | ||
194 | }) | 193 | }) |
195 | .filter(|use_path| !use_path.segments.is_empty()) | 194 | .filter(|(use_path, _)| !use_path.segments.is_empty()) |
196 | .take(20) | 195 | .take(20) |
197 | .collect::<BTreeSet<_>>() | 196 | .collect::<Vec<_>>(); |
197 | res.sort_by_key(|(path, _)| path.clone()); | ||
198 | res | ||
198 | } | 199 | } |
199 | 200 | ||
200 | fn assoc_to_trait(assoc: AssocItemContainer) -> Option<hir::Trait> { | 201 | fn assoc_to_trait(assoc: AssocItemContainer) -> Option<hir::Trait> { |
@@ -215,7 +216,7 @@ impl ImportCandidate { | |||
215 | Some(_) => None, | 216 | Some(_) => None, |
216 | None => Some(Self::TraitMethod(TraitImportCandidate { | 217 | None => Some(Self::TraitMethod(TraitImportCandidate { |
217 | ty: sema.type_of_expr(&method_call.receiver()?)?, | 218 | ty: sema.type_of_expr(&method_call.receiver()?)?, |
218 | name: method_call.name_ref()?.syntax().to_string(), | 219 | name: method_call.name_ref()?, |
219 | })), | 220 | })), |
220 | } | 221 | } |
221 | } | 222 | } |
@@ -243,24 +244,17 @@ impl ImportCandidate { | |||
243 | hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path)) => { | 244 | hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path)) => { |
244 | ImportCandidate::TraitAssocItem(TraitImportCandidate { | 245 | ImportCandidate::TraitAssocItem(TraitImportCandidate { |
245 | ty: assoc_item_path.ty(sema.db), | 246 | ty: assoc_item_path.ty(sema.db), |
246 | name: segment.syntax().to_string(), | 247 | name: segment.name_ref()?, |
247 | }) | 248 | }) |
248 | } | 249 | } |
249 | _ => return None, | 250 | _ => return None, |
250 | } | 251 | } |
251 | } else { | 252 | } else { |
252 | ImportCandidate::QualifierStart(PathImportCandidate { | 253 | ImportCandidate::QualifierStart(PathImportCandidate { name: qualifier_start }) |
253 | name: qualifier_start.syntax().to_string(), | ||
254 | }) | ||
255 | } | 254 | } |
256 | } else { | 255 | } else { |
257 | ImportCandidate::UnqualifiedName(PathImportCandidate { | 256 | ImportCandidate::UnqualifiedName(PathImportCandidate { |
258 | name: segment | 257 | name: segment.syntax().descendants().find_map(ast::NameRef::cast)?, |
259 | .syntax() | ||
260 | .descendants() | ||
261 | .find_map(ast::NameRef::cast)? | ||
262 | .syntax() | ||
263 | .to_string(), | ||
264 | }) | 258 | }) |
265 | }; | 259 | }; |
266 | Some(candidate) | 260 | Some(candidate) |