aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2021-03-02 23:26:53 +0000
committerKirill Bulatov <[email protected]>2021-03-08 21:59:20 +0000
commit33c83e72b9b48177a6171fd06a26676679963a4d (patch)
treeb787206319b2cf0050e4ce7c89ad4365b9a43c11
parent4d4ac1d4fa0aba107a27d3fd2d209304dfe69b9f (diff)
Work towards better import labels
-rw-r--r--crates/hir_def/src/import_map.rs23
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs13
-rw-r--r--crates/ide_assists/src/handlers/qualify_path.rs22
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs10
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs101
-rw-r--r--crates/ide_completion/src/item.rs43
-rw-r--r--crates/ide_completion/src/lib.rs17
-rw-r--r--crates/ide_completion/src/render.rs14
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs155
-rw-r--r--crates/ide_db/src/items_locator.rs (renamed from crates/ide_db/src/imports_locator.rs)75
-rw-r--r--crates/ide_db/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/handlers.rs5
13 files changed, 243 insertions, 239 deletions
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index 369bc3350..07ee7bdfd 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -1094,4 +1094,27 @@ mod tests {
1094 expect![[r#""#]], 1094 expect![[r#""#]],
1095 ); 1095 );
1096 } 1096 }
1097
1098 #[test]
1099 fn search_with_path() {
1100 check_search(
1101 r#"
1102//- /main.rs crate:main deps:dep
1103//- /dep.rs crate:dep
1104pub mod foo {
1105 pub mod bar {
1106 pub mod baz {
1107 pub trait Display {
1108 fn fmt();
1109 }
1110 }
1111 }
1112}"#,
1113 "main",
1114 Query::new("baz::fmt".to_string()).search_mode(SearchMode::Fuzzy),
1115 expect![[r#"
1116 dep::foo::bar::baz::Display::fmt (a)
1117 "#]],
1118 );
1119 }
1097} 1120}
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index b600178ee..f83ed65d5 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -478,7 +478,6 @@ impl Analysis {
478 position: FilePosition, 478 position: FilePosition,
479 full_import_path: &str, 479 full_import_path: &str,
480 imported_name: String, 480 imported_name: String,
481 import_for_trait_assoc_item: bool,
482 ) -> Cancelable<Vec<TextEdit>> { 481 ) -> Cancelable<Vec<TextEdit>> {
483 Ok(self 482 Ok(self
484 .with_db(|db| { 483 .with_db(|db| {
@@ -488,7 +487,6 @@ impl Analysis {
488 position, 487 position,
489 full_import_path, 488 full_import_path,
490 imported_name, 489 imported_name,
491 import_for_trait_assoc_item,
492 ) 490 )
493 })? 491 })?
494 .unwrap_or_default()) 492 .unwrap_or_default())
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 182547589..f3c969eee 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -93,17 +93,18 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
93 let group = import_group_message(import_assets.import_candidate()); 93 let group = import_group_message(import_assets.import_candidate());
94 let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?; 94 let scope = ImportScope::find_insert_use_container(&syntax_under_caret, &ctx.sema)?;
95 for import in proposed_imports { 95 for import in proposed_imports {
96 let name = match import.original_item_name(ctx.db()) {
97 Some(name) => name,
98 None => continue,
99 };
96 acc.add_group( 100 acc.add_group(
97 &group, 101 &group,
98 AssistId("auto_import", AssistKind::QuickFix), 102 AssistId("auto_import", AssistKind::QuickFix),
99 format!("Import `{}`", import.display_path()), 103 format!("Import `{}`", name),
100 range, 104 range,
101 |builder| { 105 |builder| {
102 let rewriter = insert_use( 106 let rewriter =
103 &scope, 107 insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use);
104 mod_path_to_ast(import.import_path()),
105 ctx.config.insert_use,
106 );
107 builder.rewrite(rewriter); 108 builder.rewrite(rewriter);
108 }, 109 },
109 ); 110 );
diff --git a/crates/ide_assists/src/handlers/qualify_path.rs b/crates/ide_assists/src/handlers/qualify_path.rs
index 261178448..407ba47be 100644
--- a/crates/ide_assists/src/handlers/qualify_path.rs
+++ b/crates/ide_assists/src/handlers/qualify_path.rs
@@ -2,7 +2,7 @@ use std::iter;
2 2
3use hir::AsAssocItem; 3use hir::AsAssocItem;
4use ide_db::helpers::{ 4use ide_db::helpers::{
5 import_assets::{ImportCandidate, Qualifier}, 5 import_assets::{ImportCandidate, LocatedImport, Qualifier},
6 mod_path_to_ast, 6 mod_path_to_ast,
7}; 7};
8use ide_db::RootDatabase; 8use ide_db::RootDatabase;
@@ -78,13 +78,13 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
78 acc.add_group( 78 acc.add_group(
79 &group_label, 79 &group_label,
80 AssistId("qualify_path", AssistKind::QuickFix), 80 AssistId("qualify_path", AssistKind::QuickFix),
81 label(candidate, import.display_path()), 81 label(ctx.db(), candidate, &import),
82 range, 82 range,
83 |builder| { 83 |builder| {
84 qualify_candidate.qualify( 84 qualify_candidate.qualify(
85 |replace_with: String| builder.replace(range, replace_with), 85 |replace_with: String| builder.replace(range, replace_with),
86 import.import_path(), 86 &import.import_path,
87 import.item_to_import(), 87 import.item_to_import,
88 ) 88 )
89 }, 89 },
90 ); 90 );
@@ -197,17 +197,21 @@ fn group_label(candidate: &ImportCandidate) -> GroupLabel {
197 GroupLabel(format!("Qualify {}", name)) 197 GroupLabel(format!("Qualify {}", name))
198} 198}
199 199
200fn label(candidate: &ImportCandidate, import: &hir::ModPath) -> String { 200fn label(db: &RootDatabase, candidate: &ImportCandidate, import: &LocatedImport) -> String {
201 let display_path = match import.original_item_name(db) {
202 Some(display_path) => display_path.to_string(),
203 None => "{unknown}".to_string(),
204 };
201 match candidate { 205 match candidate {
202 ImportCandidate::Path(candidate) => { 206 ImportCandidate::Path(candidate) => {
203 if !matches!(candidate.qualifier, Qualifier::Absent) { 207 if !matches!(candidate.qualifier, Qualifier::Absent) {
204 format!("Qualify with `{}`", &import) 208 format!("Qualify with `{}`", display_path)
205 } else { 209 } else {
206 format!("Qualify as `{}`", &import) 210 format!("Qualify as `{}`", display_path)
207 } 211 }
208 } 212 }
209 ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", &import), 213 ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", display_path),
210 ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", &import), 214 ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", display_path),
211 } 215 }
212} 216}
213 217
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index c69bc5cac..93a03e8b2 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1,5 +1,6 @@
1use hir::ModuleDef;
1use ide_db::helpers::mod_path_to_ast; 2use ide_db::helpers::mod_path_to_ast;
2use ide_db::imports_locator; 3use ide_db::items_locator;
3use itertools::Itertools; 4use itertools::Itertools;
4use syntax::{ 5use syntax::{
5 ast::{self, make, AstNode, NameOwner}, 6 ast::{self, make, AstNode, NameOwner},
@@ -64,13 +65,14 @@ pub(crate) fn replace_derive_with_manual_impl(
64 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; 65 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?;
65 let current_crate = current_module.krate(); 66 let current_crate = current_module.krate();
66 67
67 let found_traits = imports_locator::find_exact_imports( 68 let found_traits = items_locator::with_for_exact_name(
68 &ctx.sema, 69 &ctx.sema,
69 current_crate, 70 current_crate,
70 trait_token.text().to_string(), 71 trait_token.text().to_string(),
71 ) 72 )
72 .filter_map(|candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate { 73 .into_iter()
73 either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_), 74 .filter_map(|item| match ModuleDef::from(item.as_module_def_id()?) {
75 ModuleDef::Trait(trait_) => Some(trait_),
74 _ => None, 76 _ => None,
75 }) 77 })
76 .flat_map(|trait_| { 78 .flat_map(|trait_| {
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 1ef6f8afb..c1e3f091f 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -87,11 +87,12 @@
87//! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding 87//! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
88//! capability enabled. 88//! capability enabled.
89 89
90use hir::{AsAssocItem, ModPath, ModuleDef, ScopeDef}; 90use hir::ModPath;
91use ide_db::helpers::{ 91use ide_db::helpers::{
92 import_assets::{ImportAssets, ImportCandidate}, 92 import_assets::{ImportAssets, ImportCandidate},
93 insert_use::ImportScope, 93 insert_use::ImportScope,
94}; 94};
95use itertools::Itertools;
95use syntax::{AstNode, SyntaxNode, T}; 96use syntax::{AstNode, SyntaxNode, T};
96 97
97use crate::{ 98use crate::{
@@ -130,27 +131,23 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
130 &ctx.sema, 131 &ctx.sema,
131 )?; 132 )?;
132 133
133 let mut all_imports = 134 acc.add_all(
134 import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind); 135 import_assets
135 all_imports.sort_by_cached_key(|import| { 136 .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
136 compute_fuzzy_completion_order_key(import.display_path(), &user_input_lowercased) 137 .into_iter()
137 }); 138 .sorted_by_key(|located_import| {
138 139 compute_fuzzy_completion_order_key(
139 acc.add_all(all_imports.into_iter().filter_map(|import| { 140 &located_import.import_path,
140 let import_for_trait_assoc_item = import 141 &user_input_lowercased,
141 .item_to_display() 142 )
142 .as_module_def_id()
143 .and_then(|module_def_id| {
144 ModuleDef::from(module_def_id).as_assoc_item(ctx.db)?.containing_trait(ctx.db)
145 }) 143 })
146 .is_some(); 144 .filter_map(|import| {
147 let def_to_display = ScopeDef::from(import.item_to_display()); 145 render_resolution_with_import(
148 render_resolution_with_import( 146 RenderContext::new(ctx),
149 RenderContext::new(ctx), 147 ImportEdit { import, import_scope: import_scope.clone() },
150 ImportEdit { import, import_scope: import_scope.clone(), import_for_trait_assoc_item }, 148 )
151 &def_to_display, 149 }),
152 ) 150 );
153 }));
154 Some(()) 151 Some(())
155} 152}
156 153
@@ -190,6 +187,7 @@ fn import_assets<'a>(ctx: &'a CompletionContext, fuzzy_name: String) -> Option<I
190 ctx.scope.clone(), 187 ctx.scope.clone(),
191 )?; 188 )?;
192 189
190 // TODO kb bad: with the path prefix, the "min 3 symbols" limit applies. Fix in a separate PR on the symbol_index level
193 if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_)) 191 if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_))
194 && fuzzy_name_length < 2 192 && fuzzy_name_length < 2
195 { 193 {
@@ -796,9 +794,7 @@ fn main() {
796 794
797 #[test] 795 #[test]
798 fn unresolved_qualifier() { 796 fn unresolved_qualifier() {
799 check_edit( 797 let fixture = r#"
800 "Item",
801 r#"
802mod foo { 798mod foo {
803 pub mod bar { 799 pub mod bar {
804 pub mod baz { 800 pub mod baz {
@@ -809,31 +805,34 @@ mod foo {
809 805
810fn main() { 806fn main() {
811 bar::baz::Ite$0 807 bar::baz::Ite$0
812} 808}"#;
813"#, 809
810 check(fixture, expect![["st Item (foo::bar::baz::Item)"]]);
811
812 check_edit(
813 "Item",
814 fixture,
814 r#" 815 r#"
815use foo::bar; 816 use foo::bar;
816 817
817mod foo { 818 mod foo {
818 pub mod bar { 819 pub mod bar {
819 pub mod baz { 820 pub mod baz {
820 pub struct Item; 821 pub struct Item;
822 }
823 }
821 } 824 }
822 }
823}
824 825
825fn main() { 826 fn main() {
826 bar::baz::Item 827 bar::baz::Item
827} 828 }
828"#, 829 "#,
829 ); 830 );
830 } 831 }
831 832
832 #[test] 833 #[test]
833 fn unresolved_assoc_item_container() { 834 fn unresolved_assoc_item_container() {
834 check_edit( 835 let fixture = r#"
835 "TEST_ASSOC",
836 r#"
837mod foo { 836mod foo {
838 pub struct Item; 837 pub struct Item;
839 838
@@ -844,8 +843,13 @@ mod foo {
844 843
845fn main() { 844fn main() {
846 Item::TEST_A$0 845 Item::TEST_A$0
847} 846}"#;
848"#, 847
848 check(fixture, expect![["ct TEST_ASSOC (foo::bar::baz::Item)"]]);
849
850 check_edit(
851 "TEST_ASSOC",
852 fixture,
849 r#" 853 r#"
850use foo::Item; 854use foo::Item;
851 855
@@ -866,9 +870,7 @@ fn main() {
866 870
867 #[test] 871 #[test]
868 fn unresolved_assoc_item_container_with_path() { 872 fn unresolved_assoc_item_container_with_path() {
869 check_edit( 873 let fixture = r#"
870 "TEST_ASSOC",
871 r#"
872mod foo { 874mod foo {
873 pub mod bar { 875 pub mod bar {
874 pub struct Item; 876 pub struct Item;
@@ -881,8 +883,13 @@ mod foo {
881 883
882fn main() { 884fn main() {
883 bar::Item::TEST_A$0 885 bar::Item::TEST_A$0
884} 886}"#;
885"#, 887
888 check(fixture, expect![["ct TEST_ASSOC (foo::bar::baz::Item)"]]);
889
890 check_edit(
891 "TEST_ASSOC",
892 fixture,
886 r#" 893 r#"
887use foo::bar; 894use foo::bar;
888 895
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 0390fe226..d01620500 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -275,7 +275,6 @@ impl CompletionItem {
275pub struct ImportEdit { 275pub struct ImportEdit {
276 pub import: LocatedImport, 276 pub import: LocatedImport,
277 pub import_scope: ImportScope, 277 pub import_scope: ImportScope,
278 pub import_for_trait_assoc_item: bool,
279} 278}
280 279
281impl ImportEdit { 280impl ImportEdit {
@@ -286,7 +285,7 @@ impl ImportEdit {
286 285
287 let rewriter = insert_use::insert_use( 286 let rewriter = insert_use::insert_use(
288 &self.import_scope, 287 &self.import_scope,
289 mod_path_to_ast(self.import.import_path()), 288 mod_path_to_ast(&self.import.import_path),
290 cfg, 289 cfg,
291 ); 290 );
292 let old_ast = rewriter.rewrite_root()?; 291 let old_ast = rewriter.rewrite_root()?;
@@ -303,6 +302,7 @@ impl ImportEdit {
303pub(crate) struct Builder { 302pub(crate) struct Builder {
304 source_range: TextRange, 303 source_range: TextRange,
305 completion_kind: CompletionKind, 304 completion_kind: CompletionKind,
305 // TODO kb also add a db here, to resolve the completion label?
306 import_to_add: Option<ImportEdit>, 306 import_to_add: Option<ImportEdit>,
307 label: String, 307 label: String,
308 insert_text: Option<String>, 308 insert_text: Option<String>,
@@ -322,19 +322,22 @@ impl Builder {
322 pub(crate) fn build(self) -> CompletionItem { 322 pub(crate) fn build(self) -> CompletionItem {
323 let _p = profile::span("item::Builder::build"); 323 let _p = profile::span("item::Builder::build");
324 324
325 let mut label = self.label; 325 let label = self.label;
326 let mut lookup = self.lookup; 326 let lookup = self.lookup;
327 let mut insert_text = self.insert_text; 327 let insert_text = self.insert_text;
328 328
329 if let Some(import_to_add) = self.import_to_add.as_ref() { 329 if let Some(_import_to_add) = self.import_to_add.as_ref() {
330 lookup = lookup.or_else(|| Some(label.clone())); 330 todo!("todo kb")
331 insert_text = insert_text.or_else(|| Some(label.clone())); 331 // let import = &import_to_add.import;
332 let display_path = import_to_add.import.display_path(); 332 // let item_to_import = import.item_to_import();
333 if import_to_add.import_for_trait_assoc_item { 333 // lookup = lookup.or_else(|| Some(label.clone()));
334 label = format!("{} ({})", label, display_path); 334 // insert_text = insert_text.or_else(|| Some(label.clone()));
335 } else { 335 // let display_path = import_to_add.import.display_path();
336 label = display_path.to_string(); 336 // if import_to_add.import {
337 } 337 // label = format!("{} ({})", label, display_path);
338 // } else {
339 // label = display_path.to_string();
340 // }
338 } 341 }
339 342
340 let text_edit = match self.text_edit { 343 let text_edit = match self.text_edit {
@@ -438,8 +441,8 @@ impl Builder {
438 } 441 }
439} 442}
440 443
441impl<'a> Into<CompletionItem> for Builder { 444// impl<'a> Into<CompletionItem> for Builder {
442 fn into(self) -> CompletionItem { 445// fn into(self) -> CompletionItem {
443 self.build() 446// self.build()
444 } 447// }
445} 448// }
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index ca2e5e706..d19368de0 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -15,7 +15,7 @@ use completions::flyimport::position_for_import;
15use ide_db::{ 15use ide_db::{
16 base_db::FilePosition, 16 base_db::FilePosition,
17 helpers::{import_assets::LocatedImport, insert_use::ImportScope}, 17 helpers::{import_assets::LocatedImport, insert_use::ImportScope},
18 imports_locator, RootDatabase, 18 items_locator, RootDatabase,
19}; 19};
20use text_edit::TextEdit; 20use text_edit::TextEdit;
21 21
@@ -141,7 +141,6 @@ pub fn resolve_completion_edits(
141 position: FilePosition, 141 position: FilePosition,
142 full_import_path: &str, 142 full_import_path: &str,
143 imported_name: String, 143 imported_name: String,
144 import_for_trait_assoc_item: bool,
145) -> Option<Vec<TextEdit>> { 144) -> Option<Vec<TextEdit>> {
146 let ctx = CompletionContext::new(db, position, config)?; 145 let ctx = CompletionContext::new(db, position, config)?;
147 let position_for_import = position_for_import(&ctx, None)?; 146 let position_for_import = position_for_import(&ctx, None)?;
@@ -151,19 +150,17 @@ pub fn resolve_completion_edits(
151 let current_crate = current_module.krate(); 150 let current_crate = current_module.krate();
152 151
153 let (import_path, item_to_import) = 152 let (import_path, item_to_import) =
154 imports_locator::find_exact_imports(&ctx.sema, current_crate, imported_name) 153 items_locator::with_for_exact_name(&ctx.sema, current_crate, imported_name)
154 .into_iter()
155 .filter_map(|candidate| { 155 .filter_map(|candidate| {
156 let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
157 current_module 156 current_module
158 .find_use_path_prefixed(db, item, config.insert_use.prefix_kind) 157 .find_use_path_prefixed(db, candidate, config.insert_use.prefix_kind)
159 .zip(Some(item)) 158 .zip(Some(candidate))
160 }) 159 })
161 .find(|(mod_path, _)| mod_path.to_string() == full_import_path)?; 160 .find(|(mod_path, _)| mod_path.to_string() == full_import_path)?;
162 let import = LocatedImport::new(import_path, item_to_import, None); 161 let import = LocatedImport::new(import_path, item_to_import, item_to_import);
163 162
164 ImportEdit { import_path, import_scope, import_for_trait_assoc_item } 163 ImportEdit { import, import_scope }.to_text_edit(config.insert_use).map(|edit| vec![edit])
165 .to_text_edit(config.insert_use)
166 .map(|edit| vec![edit])
167} 164}
168 165
169#[cfg(test)] 166#[cfg(test)]
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 4bddc3957..fae5685e2 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -53,18 +53,20 @@ pub(crate) fn render_resolution<'a>(
53pub(crate) fn render_resolution_with_import<'a>( 53pub(crate) fn render_resolution_with_import<'a>(
54 ctx: RenderContext<'a>, 54 ctx: RenderContext<'a>,
55 import_edit: ImportEdit, 55 import_edit: ImportEdit,
56 resolution: &ScopeDef,
57) -> Option<CompletionItem> { 56) -> Option<CompletionItem> {
57 let resolution = ScopeDef::from(import_edit.import.original_item);
58 let local_name = match resolution { 58 let local_name = match resolution {
59 ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(), 59 ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(),
60 ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(), 60 ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(),
61 ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(), 61 ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(),
62 _ => item_name(ctx.db(), import_edit.import.item_to_display())?.to_string(), 62 _ => item_name(ctx.db(), import_edit.import.original_item)?.to_string(),
63 }; 63 };
64 Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| { 64 Render::new(ctx).render_resolution(local_name, Some(import_edit), &resolution).map(
65 item.completion_kind = CompletionKind::Magic; 65 |mut item| {
66 item 66 item.completion_kind = CompletionKind::Magic;
67 }) 67 item
68 },
69 )
68} 70}
69 71
70/// Interface for data and methods required for items rendering. 72/// Interface for data and methods required for items rendering.
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index a30a4dd9d..8d16c011e 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -1,14 +1,13 @@
1//! Look up accessible paths for items. 1//! Look up accessible paths for items.
2use either::Either;
3use hir::{ 2use hir::{
4 AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module, 3 AsAssocItem, AssocItem, AssocItemContainer, Crate, ItemInNs, MacroDef, ModPath, Module,
5 ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type, 4 ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Type,
6}; 5};
7use rustc_hash::FxHashSet; 6use rustc_hash::FxHashSet;
8use syntax::{ast, AstNode}; 7use syntax::{ast, AstNode};
9 8
10use crate::{ 9use crate::{
11 imports_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT}, 10 items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
12 RootDatabase, 11 RootDatabase,
13}; 12};
14 13
@@ -130,34 +129,23 @@ impl<'a> ImportAssets<'a> {
130 129
131#[derive(Debug, Clone, PartialEq, Eq, Hash)] 130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
132pub struct LocatedImport { 131pub struct LocatedImport {
133 import_path: ModPath, 132 pub import_path: ModPath,
134 item_to_import: ItemInNs, 133 pub item_to_import: ItemInNs,
135 data_to_display: Option<(ModPath, ItemInNs)>, 134 pub original_item: ItemInNs,
136} 135}
137 136
138impl LocatedImport { 137impl LocatedImport {
139 pub fn new( 138 pub fn new(import_path: ModPath, item_to_import: ItemInNs, original_item: ItemInNs) -> Self {
140 import_path: ModPath, 139 Self { import_path, item_to_import, original_item }
141 item_to_import: ItemInNs,
142 data_to_display: Option<(ModPath, ItemInNs)>,
143 ) -> Self {
144 Self { import_path, item_to_import, data_to_display }
145 } 140 }
146 141
147 pub fn display_path(&self) -> &ModPath { 142 pub fn original_item_name(&self, db: &RootDatabase) -> Option<Name> {
148 self.data_to_display.as_ref().map(|(mod_path, _)| mod_path).unwrap_or(&self.import_path) 143 match self.original_item {
149 } 144 ItemInNs::Types(module_def_id) | ItemInNs::Values(module_def_id) => {
150 145 ModuleDef::from(module_def_id).name(db)
151 pub fn import_path(&self) -> &ModPath { 146 }
152 &self.import_path 147 ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).name(db),
153 } 148 }
154
155 pub fn item_to_display(&self) -> ItemInNs {
156 self.data_to_display.as_ref().map(|&(_, item)| item).unwrap_or(self.item_to_import)
157 }
158
159 pub fn item_to_import(&self) -> ItemInNs {
160 self.item_to_import
161 } 149 }
162} 150}
163 151
@@ -166,25 +154,20 @@ impl<'a> ImportAssets<'a> {
166 &self.import_candidate 154 &self.import_candidate
167 } 155 }
168 156
169 fn name_to_import(&self) -> &NameToImport {
170 match &self.import_candidate {
171 ImportCandidate::Path(candidate) => &candidate.name,
172 ImportCandidate::TraitAssocItem(candidate)
173 | ImportCandidate::TraitMethod(candidate) => &candidate.name,
174 }
175 }
176
177 pub fn search_for_imports( 157 pub fn search_for_imports(
178 &self, 158 &self,
179 sema: &Semantics<RootDatabase>, 159 sema: &Semantics<RootDatabase>,
180 prefix_kind: PrefixKind, 160 prefix_kind: PrefixKind,
181 ) -> Vec<LocatedImport> { 161 ) -> FxHashSet<LocatedImport> {
182 let _p = profile::span("import_assets::search_for_imports"); 162 let _p = profile::span("import_assets::search_for_imports");
183 self.search_for(sema, Some(prefix_kind)) 163 self.search_for(sema, Some(prefix_kind))
184 } 164 }
185 165
186 /// This may return non-absolute paths if a part of the returned path is already imported into scope. 166 /// This may return non-absolute paths if a part of the returned path is already imported into scope.
187 pub fn search_for_relative_paths(&self, sema: &Semantics<RootDatabase>) -> Vec<LocatedImport> { 167 pub fn search_for_relative_paths(
168 &self,
169 sema: &Semantics<RootDatabase>,
170 ) -> FxHashSet<LocatedImport> {
188 let _p = profile::span("import_assets::search_for_relative_paths"); 171 let _p = profile::span("import_assets::search_for_relative_paths");
189 self.search_for(sema, None) 172 self.search_for(sema, None)
190 } 173 }
@@ -193,14 +176,13 @@ impl<'a> ImportAssets<'a> {
193 &self, 176 &self,
194 sema: &Semantics<RootDatabase>, 177 sema: &Semantics<RootDatabase>,
195 prefixed: Option<PrefixKind>, 178 prefixed: Option<PrefixKind>,
196 ) -> Vec<LocatedImport> { 179 ) -> FxHashSet<LocatedImport> {
197 let current_crate = self.module_with_candidate.krate(); 180 let items_with_candidate_name = match self.name_to_import() {
198 let scope_definitions = self.scope_definitions(); 181 NameToImport::Exact(exact_name) => items_locator::with_for_exact_name(
199 182 sema,
200 let defs_for_candidate_name = match self.name_to_import() { 183 self.module_with_candidate.krate(),
201 NameToImport::Exact(exact_name) => { 184 exact_name.clone(),
202 imports_locator::find_exact_imports(sema, current_crate, exact_name.clone()) 185 ),
203 }
204 // FIXME: ideally, we should avoid using `fst` for seacrhing trait imports for assoc items: 186 // FIXME: ideally, we should avoid using `fst` for seacrhing trait imports for assoc items:
205 // instead, we need to look up all trait impls for a certain struct and search through them only 187 // instead, we need to look up all trait impls for a certain struct and search through them only
206 // see https://github.com/rust-analyzer/rust-analyzer/pull/7293#issuecomment-761585032 188 // see https://github.com/rust-analyzer/rust-analyzer/pull/7293#issuecomment-761585032
@@ -213,9 +195,9 @@ impl<'a> ImportAssets<'a> {
213 (AssocItemSearch::Include, Some(DEFAULT_QUERY_SEARCH_LIMIT)) 195 (AssocItemSearch::Include, Some(DEFAULT_QUERY_SEARCH_LIMIT))
214 }; 196 };
215 197
216 imports_locator::find_similar_imports( 198 items_locator::with_similar_name(
217 sema, 199 sema,
218 current_crate, 200 self.module_with_candidate.krate(),
219 fuzzy_name.clone(), 201 fuzzy_name.clone(),
220 assoc_item_search, 202 assoc_item_search,
221 limit, 203 limit,
@@ -223,10 +205,11 @@ impl<'a> ImportAssets<'a> {
223 } 205 }
224 }; 206 };
225 207
226 self.applicable_defs(sema.db, prefixed, defs_for_candidate_name) 208 let scope_definitions = self.scope_definitions();
209 self.applicable_defs(sema.db, prefixed, items_with_candidate_name)
227 .into_iter() 210 .into_iter()
228 .filter(|import| import.import_path().len() > 1) 211 .filter(|import| import.import_path.len() > 1)
229 .filter(|import| !scope_definitions.contains(&ScopeDef::from(import.item_to_import()))) 212 .filter(|import| !scope_definitions.contains(&ScopeDef::from(import.item_to_import)))
230 .collect() 213 .collect()
231 } 214 }
232 215
@@ -238,11 +221,19 @@ impl<'a> ImportAssets<'a> {
238 scope_definitions 221 scope_definitions
239 } 222 }
240 223
224 fn name_to_import(&self) -> &NameToImport {
225 match &self.import_candidate {
226 ImportCandidate::Path(candidate) => &candidate.name,
227 ImportCandidate::TraitAssocItem(candidate)
228 | ImportCandidate::TraitMethod(candidate) => &candidate.name,
229 }
230 }
231
241 fn applicable_defs( 232 fn applicable_defs(
242 &self, 233 &self,
243 db: &RootDatabase, 234 db: &RootDatabase,
244 prefixed: Option<PrefixKind>, 235 prefixed: Option<PrefixKind>,
245 defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, 236 items_with_candidate_name: FxHashSet<ItemInNs>,
246 ) -> FxHashSet<LocatedImport> { 237 ) -> FxHashSet<LocatedImport> {
247 let _p = profile::span("import_assets::applicable_defs"); 238 let _p = profile::span("import_assets::applicable_defs");
248 let current_crate = self.module_with_candidate.krate(); 239 let current_crate = self.module_with_candidate.krate();
@@ -251,7 +242,7 @@ impl<'a> ImportAssets<'a> {
251 242
252 match &self.import_candidate { 243 match &self.import_candidate {
253 ImportCandidate::Path(path_candidate) => { 244 ImportCandidate::Path(path_candidate) => {
254 path_applicable_imports(db, path_candidate, mod_path, defs_for_candidate_name) 245 path_applicable_imports(db, path_candidate, mod_path, items_with_candidate_name)
255 } 246 }
256 ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items( 247 ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items(
257 db, 248 db,
@@ -259,7 +250,7 @@ impl<'a> ImportAssets<'a> {
259 trait_candidate, 250 trait_candidate,
260 true, 251 true,
261 mod_path, 252 mod_path,
262 defs_for_candidate_name, 253 items_with_candidate_name,
263 ), 254 ),
264 ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( 255 ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items(
265 db, 256 db,
@@ -267,7 +258,7 @@ impl<'a> ImportAssets<'a> {
267 trait_candidate, 258 trait_candidate,
268 false, 259 false,
269 mod_path, 260 mod_path,
270 defs_for_candidate_name, 261 items_with_candidate_name,
271 ), 262 ),
272 } 263 }
273 } 264 }
@@ -277,17 +268,15 @@ fn path_applicable_imports(
277 db: &RootDatabase, 268 db: &RootDatabase,
278 path_candidate: &PathImportCandidate, 269 path_candidate: &PathImportCandidate,
279 mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy, 270 mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy,
280 defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, 271 items_with_candidate_name: FxHashSet<ItemInNs>,
281) -> FxHashSet<LocatedImport> { 272) -> FxHashSet<LocatedImport> {
282 let _p = profile::span("import_assets::path_applicable_imports"); 273 let _p = profile::span("import_assets::path_applicable_imports");
283 274
284 let items_for_candidate_name =
285 defs_for_candidate_name.map(|def| def.either(ItemInNs::from, ItemInNs::from));
286
287 let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier { 275 let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier {
288 Qualifier::Absent => { 276 Qualifier::Absent => {
289 return items_for_candidate_name 277 return items_with_candidate_name
290 .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, None))) 278 .into_iter()
279 .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, item)))
291 .collect(); 280 .collect();
292 } 281 }
293 Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { 282 Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => {
@@ -295,7 +284,8 @@ fn path_applicable_imports(
295 } 284 }
296 }; 285 };
297 286
298 items_for_candidate_name 287 items_with_candidate_name
288 .into_iter()
299 .filter_map(|item| { 289 .filter_map(|item| {
300 import_for_item(db, mod_path, &unresolved_first_segment, &unresolved_qualifier, item) 290 import_for_item(db, mod_path, &unresolved_first_segment, &unresolved_qualifier, item)
301 }) 291 })
@@ -336,7 +326,6 @@ fn import_for_item(
336 } 326 }
337 327
338 let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?; 328 let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?;
339 let data_to_display = Some((import_path_candidate.clone(), original_item));
340 Some(match (segment_import == item_candidate, trait_to_import) { 329 Some(match (segment_import == item_candidate, trait_to_import) {
341 (true, Some(_)) => { 330 (true, Some(_)) => {
342 // FIXME we should be able to import both the trait and the segment, 331 // FIXME we should be able to import both the trait and the segment,
@@ -345,11 +334,11 @@ fn import_for_item(
345 return None; 334 return None;
346 } 335 }
347 (false, Some(trait_to_import)) => { 336 (false, Some(trait_to_import)) => {
348 LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, data_to_display) 337 LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, original_item)
349 } 338 }
350 (true, None) => LocatedImport::new(import_path_candidate, item_candidate, data_to_display), 339 (true, None) => LocatedImport::new(import_path_candidate, item_candidate, original_item),
351 (false, None) => { 340 (false, None) => {
352 LocatedImport::new(mod_path(segment_import)?, segment_import, data_to_display) 341 LocatedImport::new(mod_path(segment_import)?, segment_import, original_item)
353 } 342 }
354 }) 343 })
355} 344}
@@ -399,16 +388,14 @@ fn trait_applicable_items(
399 trait_candidate: &TraitImportCandidate, 388 trait_candidate: &TraitImportCandidate,
400 trait_assoc_item: bool, 389 trait_assoc_item: bool,
401 mod_path: impl Fn(ItemInNs) -> Option<ModPath>, 390 mod_path: impl Fn(ItemInNs) -> Option<ModPath>,
402 defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, 391 items_with_candidate_name: FxHashSet<ItemInNs>,
403) -> FxHashSet<LocatedImport> { 392) -> FxHashSet<LocatedImport> {
404 let _p = profile::span("import_assets::trait_applicable_items"); 393 let _p = profile::span("import_assets::trait_applicable_items");
405 let mut required_assoc_items = FxHashSet::default(); 394 let mut required_assoc_items = FxHashSet::default();
406 395
407 let trait_candidates = defs_for_candidate_name 396 let trait_candidates = items_with_candidate_name
408 .filter_map(|input| match input { 397 .into_iter()
409 Either::Left(module_def) => module_def.as_assoc_item(db), 398 .filter_map(|input| ModuleDef::from(input.as_module_def_id()?).as_assoc_item(db))
410 _ => None,
411 })
412 .filter_map(|assoc| { 399 .filter_map(|assoc| {
413 let assoc_item_trait = assoc.containing_trait(db)?; 400 let assoc_item_trait = assoc.containing_trait(db)?;
414 required_assoc_items.insert(assoc); 401 required_assoc_items.insert(assoc);
@@ -433,20 +420,10 @@ fn trait_applicable_items(
433 } 420 }
434 421
435 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); 422 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
436 let item_path = mod_path(item)?;
437
438 let assoc_item = assoc_to_item(assoc);
439 let assoc_item_path = match assoc.container(db) {
440 AssocItemContainer::Trait(_) => item_path.clone(),
441 AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from(
442 ModuleDef::from(impl_.target_ty(db).as_adt()?),
443 ))?,
444 };
445
446 located_imports.insert(LocatedImport::new( 423 located_imports.insert(LocatedImport::new(
447 item_path, 424 mod_path(item)?,
448 item, 425 item,
449 Some((assoc_item_path, assoc_item)), 426 assoc_to_item(assoc),
450 )); 427 ));
451 } 428 }
452 None::<()> 429 None::<()>
@@ -462,20 +439,10 @@ fn trait_applicable_items(
462 let assoc = function.as_assoc_item(db)?; 439 let assoc = function.as_assoc_item(db)?;
463 if required_assoc_items.contains(&assoc) { 440 if required_assoc_items.contains(&assoc) {
464 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); 441 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?));
465 let item_path = mod_path(item)?;
466
467 let assoc_item = assoc_to_item(assoc);
468 let assoc_item_path = match assoc.container(db) {
469 AssocItemContainer::Trait(_) => item_path.clone(),
470 AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from(
471 ModuleDef::from(impl_.target_ty(db).as_adt()?),
472 ))?,
473 };
474
475 located_imports.insert(LocatedImport::new( 442 located_imports.insert(LocatedImport::new(
476 item_path, 443 mod_path(item)?,
477 item, 444 item,
478 Some((assoc_item_path, assoc_item)), 445 assoc_to_item(assoc),
479 )); 446 ));
480 } 447 }
481 None::<()> 448 None::<()>
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/items_locator.rs
index fd700e04f..b81c14618 100644
--- a/crates/ide_db/src/imports_locator.rs
+++ b/crates/ide_db/src/items_locator.rs
@@ -1,9 +1,10 @@
1//! This module contains an import search functionality that is provided to the assists module. 1//! This module contains an import search functionality that is provided to the assists module.
2//! Later, this should be moved away to a separate crate that is accessible from the assists module. 2//! Later, this should be moved away to a separate crate that is accessible from the assists module.
3 3
4use either::Either;
4use hir::{ 5use hir::{
5 import_map::{self, ImportKind}, 6 import_map::{self, ImportKind},
6 AsAssocItem, Crate, MacroDef, ModuleDef, Semantics, 7 AsAssocItem, Crate, ItemInNs, ModuleDef, Semantics,
7}; 8};
8use syntax::{ast, AstNode, SyntaxKind::NAME}; 9use syntax::{ast, AstNode, SyntaxKind::NAME};
9 10
@@ -12,32 +13,31 @@ use crate::{
12 symbol_index::{self, FileSymbol}, 13 symbol_index::{self, FileSymbol},
13 RootDatabase, 14 RootDatabase,
14}; 15};
15use either::Either;
16use rustc_hash::FxHashSet; 16use rustc_hash::FxHashSet;
17 17
18pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40; 18pub(crate) const DEFAULT_QUERY_SEARCH_LIMIT: usize = 40;
19 19
20pub fn find_exact_imports( 20pub fn with_for_exact_name(
21 sema: &Semantics<'_, RootDatabase>, 21 sema: &Semantics<'_, RootDatabase>,
22 krate: Crate, 22 krate: Crate,
23 name_to_import: String, 23 exact_name: String,
24) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>>> { 24) -> FxHashSet<ItemInNs> {
25 let _p = profile::span("find_exact_imports"); 25 let _p = profile::span("find_exact_imports");
26 Box::new(find_imports( 26 find_items(
27 sema, 27 sema,
28 krate, 28 krate,
29 { 29 {
30 let mut local_query = symbol_index::Query::new(name_to_import.clone()); 30 let mut local_query = symbol_index::Query::new(exact_name.clone());
31 local_query.exact(); 31 local_query.exact();
32 local_query.limit(DEFAULT_QUERY_SEARCH_LIMIT); 32 local_query.limit(DEFAULT_QUERY_SEARCH_LIMIT);
33 local_query 33 local_query
34 }, 34 },
35 import_map::Query::new(name_to_import) 35 import_map::Query::new(exact_name)
36 .limit(DEFAULT_QUERY_SEARCH_LIMIT) 36 .limit(DEFAULT_QUERY_SEARCH_LIMIT)
37 .name_only() 37 .name_only()
38 .search_mode(import_map::SearchMode::Equals) 38 .search_mode(import_map::SearchMode::Equals)
39 .case_sensitive(), 39 .case_sensitive(),
40 )) 40 )
41} 41}
42 42
43#[derive(Debug)] 43#[derive(Debug)]
@@ -47,13 +47,13 @@ pub enum AssocItemSearch {
47 AssocItemsOnly, 47 AssocItemsOnly,
48} 48}
49 49
50pub fn find_similar_imports<'a>( 50pub fn with_similar_name(
51 sema: &'a Semantics<'a, RootDatabase>, 51 sema: &Semantics<'_, RootDatabase>,
52 krate: Crate, 52 krate: Crate,
53 fuzzy_search_string: String, 53 fuzzy_search_string: String,
54 assoc_item_search: AssocItemSearch, 54 assoc_item_search: AssocItemSearch,
55 limit: Option<usize>, 55 limit: Option<usize>,
56) -> Box<dyn Iterator<Item = Either<ModuleDef, MacroDef>> + 'a> { 56) -> FxHashSet<ItemInNs> {
57 let _p = profile::span("find_similar_imports"); 57 let _p = profile::span("find_similar_imports");
58 58
59 let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) 59 let mut external_query = import_map::Query::new(fuzzy_search_string.clone())
@@ -77,36 +77,39 @@ pub fn find_similar_imports<'a>(
77 local_query.limit(limit); 77 local_query.limit(limit);
78 } 78 }
79 79
80 Box::new(find_imports(sema, krate, local_query, external_query).filter( 80 find_items(sema, krate, local_query, external_query)
81 move |import_candidate| match assoc_item_search { 81 .into_iter()
82 .filter(move |&item| match assoc_item_search {
82 AssocItemSearch::Include => true, 83 AssocItemSearch::Include => true,
83 AssocItemSearch::Exclude => !is_assoc_item(import_candidate, sema.db), 84 AssocItemSearch::Exclude => !is_assoc_item(item, sema.db),
84 AssocItemSearch::AssocItemsOnly => is_assoc_item(import_candidate, sema.db), 85 AssocItemSearch::AssocItemsOnly => is_assoc_item(item, sema.db),
85 }, 86 })
86 )) 87 .collect()
87} 88}
88 89
89fn is_assoc_item(import_candidate: &Either<ModuleDef, MacroDef>, db: &RootDatabase) -> bool { 90fn is_assoc_item(item: ItemInNs, db: &RootDatabase) -> bool {
90 match import_candidate { 91 item.as_module_def_id()
91 Either::Left(ModuleDef::Function(function)) => function.as_assoc_item(db).is_some(), 92 .and_then(|module_def_id| ModuleDef::from(module_def_id).as_assoc_item(db))
92 Either::Left(ModuleDef::Const(const_)) => const_.as_assoc_item(db).is_some(), 93 .is_some()
93 Either::Left(ModuleDef::TypeAlias(type_alias)) => type_alias.as_assoc_item(db).is_some(),
94 _ => false,
95 }
96} 94}
97 95
98fn find_imports<'a>( 96fn find_items(
99 sema: &Semantics<'a, RootDatabase>, 97 sema: &Semantics<'_, RootDatabase>,
100 krate: Crate, 98 krate: Crate,
101 local_query: symbol_index::Query, 99 local_query: symbol_index::Query,
102 external_query: import_map::Query, 100 external_query: import_map::Query,
103) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { 101) -> FxHashSet<ItemInNs> {
104 let _p = profile::span("find_similar_imports"); 102 let _p = profile::span("find_similar_imports");
105 let db = sema.db; 103 let db = sema.db;
106 104
107 // Query dependencies first. 105 // Query dependencies first.
108 let mut candidates: FxHashSet<_> = 106 let mut candidates = krate
109 krate.query_external_importables(db, external_query).collect(); 107 .query_external_importables(db, external_query)
108 .map(|external_importable| match external_importable {
109 Either::Left(module_def) => ItemInNs::from(module_def),
110 Either::Right(macro_def) => ItemInNs::from(macro_def),
111 })
112 .collect::<FxHashSet<_>>();
110 113
111 // Query the local crate using the symbol index. 114 // Query the local crate using the symbol index.
112 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query); 115 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query);
@@ -114,19 +117,19 @@ fn find_imports<'a>(
114 candidates.extend( 117 candidates.extend(
115 local_results 118 local_results
116 .into_iter() 119 .into_iter()
117 .filter_map(|import_candidate| get_name_definition(sema, &import_candidate)) 120 .filter_map(|local_candidate| get_name_definition(sema, &local_candidate))
118 .filter_map(|name_definition_to_import| match name_definition_to_import { 121 .filter_map(|name_definition_to_import| match name_definition_to_import {
119 Definition::ModuleDef(module_def) => Some(Either::Left(module_def)), 122 Definition::ModuleDef(module_def) => Some(ItemInNs::from(module_def)),
120 Definition::Macro(macro_def) => Some(Either::Right(macro_def)), 123 Definition::Macro(macro_def) => Some(ItemInNs::from(macro_def)),
121 _ => None, 124 _ => None,
122 }), 125 }),
123 ); 126 );
124 127
125 candidates.into_iter() 128 candidates
126} 129}
127 130
128fn get_name_definition<'a>( 131fn get_name_definition(
129 sema: &Semantics<'a, RootDatabase>, 132 sema: &Semantics<'_, RootDatabase>,
130 import_candidate: &FileSymbol, 133 import_candidate: &FileSymbol,
131) -> Option<Definition> { 134) -> Option<Definition> {
132 let _p = profile::span("get_name_definition"); 135 let _p = profile::span("get_name_definition");
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 6eb34b06b..88ee4a87d 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -8,7 +8,7 @@ pub mod line_index;
8pub mod symbol_index; 8pub mod symbol_index;
9pub mod defs; 9pub mod defs;
10pub mod search; 10pub mod search;
11pub mod imports_locator; 11pub mod items_locator;
12pub mod source_change; 12pub mod source_change;
13pub mod ty_filter; 13pub mod ty_filter;
14pub mod traits; 14pub mod traits;
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index d479d826f..2c4c339cb 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -697,7 +697,6 @@ pub(crate) fn handle_completion_resolve(
697 FilePosition { file_id, offset }, 697 FilePosition { file_id, offset },
698 &resolve_data.full_import_path, 698 &resolve_data.full_import_path,
699 resolve_data.imported_name, 699 resolve_data.imported_name,
700 resolve_data.import_for_trait_assoc_item,
701 )? 700 )?
702 .into_iter() 701 .into_iter()
703 .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel))) 702 .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel)))
@@ -1525,7 +1524,6 @@ struct CompletionResolveData {
1525 position: lsp_types::TextDocumentPositionParams, 1524 position: lsp_types::TextDocumentPositionParams,
1526 full_import_path: String, 1525 full_import_path: String,
1527 imported_name: String, 1526 imported_name: String,
1528 import_for_trait_assoc_item: bool,
1529} 1527}
1530 1528
1531fn fill_resolve_data( 1529fn fill_resolve_data(
@@ -1534,14 +1532,13 @@ fn fill_resolve_data(
1534 position: &TextDocumentPositionParams, 1532 position: &TextDocumentPositionParams,
1535) -> Option<()> { 1533) -> Option<()> {
1536 let import_edit = item.import_to_add()?; 1534 let import_edit = item.import_to_add()?;
1537 let import_path = import_edit.import.import_path(); 1535 let import_path = &import_edit.import.import_path;
1538 1536
1539 *resolve_data = Some( 1537 *resolve_data = Some(
1540 to_value(CompletionResolveData { 1538 to_value(CompletionResolveData {
1541 position: position.to_owned(), 1539 position: position.to_owned(),
1542 full_import_path: import_path.to_string(), 1540 full_import_path: import_path.to_string(),
1543 imported_name: import_path.segments().last()?.to_string(), 1541 imported_name: import_path.segments().last()?.to_string(),
1544 import_for_trait_assoc_item: import_edit.import_for_trait_assoc_item,
1545 }) 1542 })
1546 .unwrap(), 1543 .unwrap(),
1547 ); 1544 );