aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/replace_derive_with_manual_impl.rs28
-rw-r--r--crates/assists/src/utils/import_assets.rs34
-rw-r--r--crates/completion/src/completions/magic.rs74
-rw-r--r--crates/completion/src/lib.rs2
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/ide_db/src/imports_locator.rs65
6 files changed, 119 insertions, 86 deletions
diff --git a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
index 82625516c..453a6cebf 100644
--- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -62,19 +62,21 @@ pub(crate) fn replace_derive_with_manual_impl(
62 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; 62 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?;
63 let current_crate = current_module.krate(); 63 let current_crate = current_module.krate();
64 64
65 let found_traits = imports_locator::find_imports(&ctx.sema, current_crate, trait_token.text()) 65 let found_traits =
66 .into_iter() 66 imports_locator::find_exact_imports(&ctx.sema, current_crate, trait_token.text())
67 .filter_map(|candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate { 67 .filter_map(
68 either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_), 68 |candidate: either::Either<hir::ModuleDef, hir::MacroDef>| match candidate {
69 _ => None, 69 either::Either::Left(hir::ModuleDef::Trait(trait_)) => Some(trait_),
70 }) 70 _ => None,
71 .flat_map(|trait_| { 71 },
72 current_module 72 )
73 .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_)) 73 .flat_map(|trait_| {
74 .as_ref() 74 current_module
75 .map(mod_path_to_ast) 75 .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
76 .zip(Some(trait_)) 76 .as_ref()
77 }); 77 .map(mod_path_to_ast)
78 .zip(Some(trait_))
79 });
78 80
79 let mut no_traits_found = true; 81 let mut no_traits_found = true;
80 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { 82 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
diff --git a/crates/assists/src/utils/import_assets.rs b/crates/assists/src/utils/import_assets.rs
index f47edbb76..89e62ba79 100644
--- a/crates/assists/src/utils/import_assets.rs
+++ b/crates/assists/src/utils/import_assets.rs
@@ -179,21 +179,25 @@ impl ImportAssets {
179 } 179 }
180 }; 180 };
181 181
182 let mut res = imports_locator::find_imports(sema, current_crate, &self.get_search_query()) 182 let mut res =
183 .into_iter() 183 imports_locator::find_exact_imports(sema, current_crate, &self.get_search_query())
184 .filter_map(filter) 184 .filter_map(filter)
185 .filter_map(|candidate| { 185 .filter_map(|candidate| {
186 let item: hir::ItemInNs = candidate.either(Into::into, Into::into); 186 let item: hir::ItemInNs = candidate.either(Into::into, Into::into);
187 if let Some(prefix_kind) = prefixed { 187 if let Some(prefix_kind) = prefixed {
188 self.module_with_name_to_import.find_use_path_prefixed(db, item, prefix_kind) 188 self.module_with_name_to_import.find_use_path_prefixed(
189 } else { 189 db,
190 self.module_with_name_to_import.find_use_path(db, item) 190 item,
191 } 191 prefix_kind,
192 .map(|path| (path, item)) 192 )
193 }) 193 } else {
194 .filter(|(use_path, _)| !use_path.segments.is_empty()) 194 self.module_with_name_to_import.find_use_path(db, item)
195 .take(20) 195 }
196 .collect::<Vec<_>>(); 196 .map(|path| (path, item))
197 })
198 .filter(|(use_path, _)| !use_path.segments.is_empty())
199 .take(20)
200 .collect::<Vec<_>>();
197 res.sort_by_key(|(path, _)| path.clone()); 201 res.sort_by_key(|(path, _)| path.clone());
198 res 202 res
199 } 203 }
diff --git a/crates/completion/src/completions/magic.rs b/crates/completion/src/completions/magic.rs
index 34fc35847..272c9a354 100644
--- a/crates/completion/src/completions/magic.rs
+++ b/crates/completion/src/completions/magic.rs
@@ -2,8 +2,8 @@
2 2
3use assists::utils::{insert_use, mod_path_to_ast, ImportScope}; 3use assists::utils::{insert_use, mod_path_to_ast, ImportScope};
4use either::Either; 4use either::Either;
5use hir::{db::HirDatabase, MacroDef, ModuleDef, Query}; 5use hir::{db::HirDatabase, MacroDef, ModuleDef};
6use itertools::Itertools; 6use ide_db::imports_locator;
7use syntax::{algo, AstNode}; 7use syntax::{algo, AstNode};
8use text_edit::TextEdit; 8use text_edit::TextEdit;
9 9
@@ -22,42 +22,40 @@ pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) ->
22 22
23 let potential_import_name = ctx.token.to_string(); 23 let potential_import_name = ctx.token.to_string();
24 24
25 let possible_imports = ctx 25 let possible_imports =
26 .krate? 26 imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name)
27 // TODO kb use imports_locator instead? 27 .filter_map(|import_candidate| {
28 .query_external_importables(ctx.db, Query::new(&potential_import_name).limit(40)) 28 let use_path = match import_candidate {
29 .unique() 29 Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def),
30 .filter_map(|import_candidate| { 30 Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def),
31 let use_path = match import_candidate { 31 }?;
32 Either::Left(module_def) => current_module.find_use_path(ctx.db, module_def), 32 Some((use_path, additional_completion(ctx.db, import_candidate)))
33 Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def), 33 })
34 }?; 34 .filter_map(|(mod_path, additional_completion)| {
35 Some((use_path, additional_completion(ctx.db, import_candidate))) 35 let mut builder = TextEdit::builder();
36 }) 36
37 .filter_map(|(mod_path, additional_completion)| { 37 let correct_qualifier = format!(
38 let mut builder = TextEdit::builder(); 38 "{}{}",
39 39 mod_path.segments.last()?,
40 let correct_qualifier = format!( 40 additional_completion.unwrap_or_default()
41 "{}{}", 41 );
42 mod_path.segments.last()?, 42 builder.replace(anchor.syntax().text_range(), correct_qualifier);
43 additional_completion.unwrap_or_default() 43
44 ); 44 let rewriter =
45 builder.replace(anchor.syntax().text_range(), correct_qualifier); 45 insert_use(&import_scope, mod_path_to_ast(&mod_path), ctx.config.merge);
46 46 let old_ast = rewriter.rewrite_root()?;
47 let rewriter = insert_use(&import_scope, mod_path_to_ast(&mod_path), ctx.config.merge); 47 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut builder);
48 let old_ast = rewriter.rewrite_root()?; 48
49 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut builder); 49 let completion_item: CompletionItem = CompletionItem::new(
50 50 CompletionKind::Magic,
51 let completion_item: CompletionItem = CompletionItem::new( 51 ctx.source_range(),
52 CompletionKind::Magic, 52 mod_path.to_string(),
53 ctx.source_range(), 53 )
54 mod_path.to_string(), 54 .kind(CompletionItemKind::Struct)
55 ) 55 .text_edit(builder.finish())
56 .kind(CompletionItemKind::Struct) 56 .into();
57 .text_edit(builder.finish()) 57 Some(completion_item)
58 .into(); 58 });
59 Some(completion_item)
60 });
61 acc.add_all(possible_imports); 59 acc.add_all(possible_imports);
62 60
63 Some(()) 61 Some(())
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index e920fa6b5..8323af8b2 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -118,7 +118,7 @@ pub fn completions(
118 completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); 118 completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
119 completions::trait_impl::complete_trait_impl(&mut acc, &ctx); 119 completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
120 completions::mod_::complete_mod(&mut acc, &ctx); 120 completions::mod_::complete_mod(&mut acc, &ctx);
121 completions::complete_magic::complete_magic(&mut acc, &ctx); 121 completions::magic::complete_magic(&mut acc, &ctx);
122 122
123 Some(acc) 123 Some(acc)
124} 124}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ad58a7cfe..4b7ea3aa9 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -49,7 +49,7 @@ pub use hir_def::{
49 builtin_type::BuiltinType, 49 builtin_type::BuiltinType,
50 docs::Documentation, 50 docs::Documentation,
51 find_path::PrefixKind, 51 find_path::PrefixKind,
52 import_map::Query, 52 import_map::Query as ExternalImportablesQuery,
53 item_scope::ItemInNs, 53 item_scope::ItemInNs,
54 nameres::ModuleSource, 54 nameres::ModuleSource,
55 path::{ModPath, PathKind}, 55 path::{ModPath, PathKind},
diff --git a/crates/ide_db/src/imports_locator.rs b/crates/ide_db/src/imports_locator.rs
index e4f4b5427..71fb7207b 100644
--- a/crates/ide_db/src/imports_locator.rs
+++ b/crates/ide_db/src/imports_locator.rs
@@ -1,40 +1,69 @@
1//! This module contains an import search funcionality that is provided to the assists module. 1//! This module contains an import search funcionality 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 hir::{Crate, MacroDef, ModuleDef, Query as ImportMapQuery, Semantics}; 4use hir::{Crate, ExternalImportablesQuery, MacroDef, ModuleDef, Semantics};
5use syntax::{ast, AstNode, SyntaxKind::NAME}; 5use syntax::{ast, AstNode, SyntaxKind::NAME};
6 6
7use crate::{ 7use crate::{
8 defs::{Definition, NameClass}, 8 defs::{Definition, NameClass},
9 symbol_index::{self, FileSymbol, Query as SymbolQuery}, 9 symbol_index::{self, FileSymbol, Query as LocalImportablesQuery},
10 RootDatabase, 10 RootDatabase,
11}; 11};
12use either::Either; 12use either::Either;
13use rustc_hash::FxHashSet; 13use rustc_hash::FxHashSet;
14 14
15pub fn find_imports<'a>( 15pub fn find_exact_imports<'a>(
16 sema: &Semantics<'a, RootDatabase>, 16 sema: &Semantics<'a, RootDatabase>,
17 krate: Crate, 17 krate: Crate,
18 name_to_import: &str, 18 name_to_import: &str,
19) -> Vec<Either<ModuleDef, MacroDef>> { 19) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
20 let _p = profile::span("search_for_imports"); 20 let _p = profile::span("find_exact_imports");
21 find_imports(
22 sema,
23 krate,
24 {
25 let mut local_query = LocalImportablesQuery::new(name_to_import.to_string());
26 local_query.exact();
27 local_query.limit(40);
28 local_query
29 },
30 ExternalImportablesQuery::new(name_to_import).anchor_end().case_sensitive().limit(40),
31 )
32}
33
34pub fn find_similar_imports<'a>(
35 sema: &Semantics<'a, RootDatabase>,
36 krate: Crate,
37 name_to_import: &str,
38) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
39 let _p = profile::span("find_similar_imports");
40 find_imports(
41 sema,
42 krate,
43 {
44 let mut local_query = LocalImportablesQuery::new(name_to_import.to_string());
45 local_query.limit(40);
46 local_query
47 },
48 ExternalImportablesQuery::new(name_to_import).limit(40),
49 )
50}
51
52fn find_imports<'a>(
53 sema: &Semantics<'a, RootDatabase>,
54 krate: Crate,
55 local_query: LocalImportablesQuery,
56 external_query: ExternalImportablesQuery,
57) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
58 let _p = profile::span("find_similar_imports");
21 let db = sema.db; 59 let db = sema.db;
22 60
23 // Query dependencies first. 61 // Query dependencies first.
24 let mut candidates: FxHashSet<_> = krate 62 let mut candidates: FxHashSet<_> =
25 .query_external_importables( 63 krate.query_external_importables(db, external_query).collect();
26 db,
27 ImportMapQuery::new(name_to_import).anchor_end().case_sensitive().limit(40),
28 )
29 .collect();
30 64
31 // Query the local crate using the symbol index. 65 // Query the local crate using the symbol index.
32 let local_results = { 66 let local_results = symbol_index::crate_symbols(db, krate.into(), local_query);
33 let mut query = SymbolQuery::new(name_to_import.to_string());
34 query.exact();
35 query.limit(40);
36 symbol_index::crate_symbols(db, krate.into(), query)
37 };
38 67
39 candidates.extend( 68 candidates.extend(
40 local_results 69 local_results
@@ -47,7 +76,7 @@ pub fn find_imports<'a>(
47 }), 76 }),
48 ); 77 );
49 78
50 candidates.into_iter().collect() 79 candidates.into_iter()
51} 80}
52 81
53fn get_name_definition<'a>( 82fn get_name_definition<'a>(