diff options
-rw-r--r-- | crates/assists/src/handlers/replace_derive_with_manual_impl.rs | 28 | ||||
-rw-r--r-- | crates/assists/src/utils/import_assets.rs | 34 | ||||
-rw-r--r-- | crates/completion/src/completions/magic.rs | 74 | ||||
-rw-r--r-- | crates/completion/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ide_db/src/imports_locator.rs | 65 |
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 | ||
3 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope}; | 3 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope}; |
4 | use either::Either; | 4 | use either::Either; |
5 | use hir::{db::HirDatabase, MacroDef, ModuleDef, Query}; | 5 | use hir::{db::HirDatabase, MacroDef, ModuleDef}; |
6 | use itertools::Itertools; | 6 | use ide_db::imports_locator; |
7 | use syntax::{algo, AstNode}; | 7 | use syntax::{algo, AstNode}; |
8 | use text_edit::TextEdit; | 8 | use 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 | ||
4 | use hir::{Crate, MacroDef, ModuleDef, Query as ImportMapQuery, Semantics}; | 4 | use hir::{Crate, ExternalImportablesQuery, MacroDef, ModuleDef, Semantics}; |
5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; | 5 | use syntax::{ast, AstNode, SyntaxKind::NAME}; |
6 | 6 | ||
7 | use crate::{ | 7 | use 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 | }; |
12 | use either::Either; | 12 | use either::Either; |
13 | use rustc_hash::FxHashSet; | 13 | use rustc_hash::FxHashSet; |
14 | 14 | ||
15 | pub fn find_imports<'a>( | 15 | pub 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 | |||
34 | pub 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 | |||
52 | fn 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 | ||
53 | fn get_name_definition<'a>( | 82 | fn get_name_definition<'a>( |