diff options
Diffstat (limited to 'crates/ide_completion')
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 101 | ||||
-rw-r--r-- | crates/ide_completion/src/item.rs | 43 | ||||
-rw-r--r-- | crates/ide_completion/src/lib.rs | 17 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 14 |
4 files changed, 92 insertions, 83 deletions
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 | ||
90 | use hir::{AsAssocItem, ModPath, ModuleDef, ScopeDef}; | 90 | use hir::ModPath; |
91 | use ide_db::helpers::{ | 91 | use ide_db::helpers::{ |
92 | import_assets::{ImportAssets, ImportCandidate}, | 92 | import_assets::{ImportAssets, ImportCandidate}, |
93 | insert_use::ImportScope, | 93 | insert_use::ImportScope, |
94 | }; | 94 | }; |
95 | use itertools::Itertools; | ||
95 | use syntax::{AstNode, SyntaxNode, T}; | 96 | use syntax::{AstNode, SyntaxNode, T}; |
96 | 97 | ||
97 | use crate::{ | 98 | use 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#" | ||
802 | mod foo { | 798 | mod 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 | ||
810 | fn main() { | 806 | fn 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#" |
815 | use foo::bar; | 816 | use foo::bar; |
816 | 817 | ||
817 | mod 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 | ||
825 | fn 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#" | ||
837 | mod foo { | 836 | mod foo { |
838 | pub struct Item; | 837 | pub struct Item; |
839 | 838 | ||
@@ -844,8 +843,13 @@ mod foo { | |||
844 | 843 | ||
845 | fn main() { | 844 | fn 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#" |
850 | use foo::Item; | 854 | use 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#" | ||
872 | mod foo { | 874 | mod 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 | ||
882 | fn main() { | 884 | fn 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#" |
887 | use foo::bar; | 894 | use 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 { | |||
275 | pub struct ImportEdit { | 275 | pub 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 | ||
281 | impl ImportEdit { | 280 | impl 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 { | |||
303 | pub(crate) struct Builder { | 302 | pub(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 | ||
441 | impl<'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; | |||
15 | use ide_db::{ | 15 | use 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 | }; |
20 | use text_edit::TextEdit; | 20 | use 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>( | |||
53 | pub(crate) fn render_resolution_with_import<'a>( | 53 | pub(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. |