diff options
Diffstat (limited to 'crates/ide_completion')
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 270 | ||||
-rw-r--r-- | crates/ide_completion/src/item.rs | 43 | ||||
-rw-r--r-- | crates/ide_completion/src/lib.rs | 28 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 19 |
4 files changed, 268 insertions, 92 deletions
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index f34764b61..391a11c91 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -21,6 +21,46 @@ | |||
21 | //! ``` | 21 | //! ``` |
22 | //! | 22 | //! |
23 | //! Also completes associated items, that require trait imports. | 23 | //! Also completes associated items, that require trait imports. |
24 | //! If any unresolved and/or partially-qualified path predeces the input, it will be taken into account. | ||
25 | //! Currently, only the imports with their import path ending with the whole qialifier will be proposed | ||
26 | //! (no fuzzy matching for qualifier). | ||
27 | //! | ||
28 | //! ``` | ||
29 | //! mod foo { | ||
30 | //! pub mod bar { | ||
31 | //! pub struct Item; | ||
32 | //! | ||
33 | //! impl Item { | ||
34 | //! pub const TEST_ASSOC: usize = 3; | ||
35 | //! } | ||
36 | //! } | ||
37 | //! } | ||
38 | //! | ||
39 | //! fn main() { | ||
40 | //! bar::Item::TEST_A$0 | ||
41 | //! } | ||
42 | //! ``` | ||
43 | //! -> | ||
44 | //! ``` | ||
45 | //! use foo::bar; | ||
46 | //! | ||
47 | //! mod foo { | ||
48 | //! pub mod bar { | ||
49 | //! pub struct Item; | ||
50 | //! | ||
51 | //! impl Item { | ||
52 | //! pub const TEST_ASSOC: usize = 3; | ||
53 | //! } | ||
54 | //! } | ||
55 | //! } | ||
56 | //! | ||
57 | //! fn main() { | ||
58 | //! bar::Item::TEST_ASSOC | ||
59 | //! } | ||
60 | //! ``` | ||
61 | //! | ||
62 | //! NOTE: currently, if an assoc item comes from a trait that's not currently imported and it also has an unresolved and/or partially-qualified path, | ||
63 | //! no imports will be proposed. | ||
24 | //! | 64 | //! |
25 | //! .Fuzzy search details | 65 | //! .Fuzzy search details |
26 | //! | 66 | //! |
@@ -48,12 +88,12 @@ | |||
48 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding | 88 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding |
49 | //! capability enabled. | 89 | //! capability enabled. |
50 | 90 | ||
51 | use hir::{AsAssocItem, ModPath, ScopeDef}; | 91 | use hir::ModPath; |
52 | use ide_db::helpers::{ | 92 | use ide_db::helpers::{ |
53 | import_assets::{ImportAssets, ImportCandidate}, | 93 | import_assets::{ImportAssets, ImportCandidate}, |
54 | insert_use::ImportScope, | 94 | insert_use::ImportScope, |
55 | }; | 95 | }; |
56 | use rustc_hash::FxHashSet; | 96 | use itertools::Itertools; |
57 | use syntax::{AstNode, SyntaxNode, T}; | 97 | use syntax::{AstNode, SyntaxNode, T}; |
58 | 98 | ||
59 | use crate::{ | 99 | use crate::{ |
@@ -92,50 +132,26 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) | |||
92 | &ctx.sema, | 132 | &ctx.sema, |
93 | )?; | 133 | )?; |
94 | 134 | ||
95 | let scope_definitions = scope_definitions(ctx); | 135 | acc.add_all( |
96 | let mut all_mod_paths = import_assets | 136 | import_assets |
97 | .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) | 137 | .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) |
98 | .into_iter() | 138 | .into_iter() |
99 | .map(|(mod_path, item_in_ns)| { | 139 | .sorted_by_key(|located_import| { |
100 | let scope_item = match item_in_ns { | 140 | compute_fuzzy_completion_order_key( |
101 | hir::ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()), | 141 | &located_import.import_path, |
102 | hir::ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()), | 142 | &user_input_lowercased, |
103 | hir::ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()), | 143 | ) |
104 | }; | 144 | }) |
105 | (mod_path, scope_item) | 145 | .filter_map(|import| { |
106 | }) | 146 | render_resolution_with_import( |
107 | .filter(|(_, proposed_def)| !scope_definitions.contains(proposed_def)) | 147 | RenderContext::new(ctx), |
108 | .collect::<Vec<_>>(); | 148 | ImportEdit { import, scope: import_scope.clone() }, |
109 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { | 149 | ) |
110 | compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased) | 150 | }), |
111 | }); | 151 | ); |
112 | |||
113 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| { | ||
114 | let import_for_trait_assoc_item = match definition { | ||
115 | ScopeDef::ModuleDef(module_def) => module_def | ||
116 | .as_assoc_item(ctx.db) | ||
117 | .and_then(|assoc| assoc.containing_trait(ctx.db)) | ||
118 | .is_some(), | ||
119 | _ => false, | ||
120 | }; | ||
121 | let import_edit = ImportEdit { | ||
122 | import_path, | ||
123 | import_scope: import_scope.clone(), | ||
124 | import_for_trait_assoc_item, | ||
125 | }; | ||
126 | render_resolution_with_import(RenderContext::new(ctx), import_edit, &definition) | ||
127 | })); | ||
128 | Some(()) | 152 | Some(()) |
129 | } | 153 | } |
130 | 154 | ||
131 | fn scope_definitions(ctx: &CompletionContext) -> FxHashSet<ScopeDef> { | ||
132 | let mut scope_definitions = FxHashSet::default(); | ||
133 | ctx.scope.process_all_names(&mut |_, scope_def| { | ||
134 | scope_definitions.insert(scope_def); | ||
135 | }); | ||
136 | scope_definitions | ||
137 | } | ||
138 | |||
139 | pub(crate) fn position_for_import<'a>( | 155 | pub(crate) fn position_for_import<'a>( |
140 | ctx: &'a CompletionContext, | 156 | ctx: &'a CompletionContext, |
141 | import_candidate: Option<&ImportCandidate>, | 157 | import_candidate: Option<&ImportCandidate>, |
@@ -160,23 +176,30 @@ fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAs | |||
160 | current_module, | 176 | current_module, |
161 | ctx.sema.type_of_expr(dot_receiver)?, | 177 | ctx.sema.type_of_expr(dot_receiver)?, |
162 | fuzzy_name, | 178 | fuzzy_name, |
179 | dot_receiver.syntax().clone(), | ||
163 | ) | 180 | ) |
164 | } else { | 181 | } else { |
165 | let fuzzy_name_length = fuzzy_name.len(); | 182 | let fuzzy_name_length = fuzzy_name.len(); |
183 | let approximate_node = match current_module.definition_source(ctx.db).value { | ||
184 | hir::ModuleSource::SourceFile(s) => s.syntax().clone(), | ||
185 | hir::ModuleSource::Module(m) => m.syntax().clone(), | ||
186 | hir::ModuleSource::BlockExpr(b) => b.syntax().clone(), | ||
187 | }; | ||
166 | let assets_for_path = ImportAssets::for_fuzzy_path( | 188 | let assets_for_path = ImportAssets::for_fuzzy_path( |
167 | current_module, | 189 | current_module, |
168 | ctx.path_qual.clone(), | 190 | ctx.path_qual.clone(), |
169 | fuzzy_name, | 191 | fuzzy_name, |
170 | &ctx.sema, | 192 | &ctx.sema, |
171 | ); | 193 | approximate_node, |
194 | )?; | ||
172 | 195 | ||
173 | if matches!(assets_for_path.as_ref()?.import_candidate(), ImportCandidate::Path(_)) | 196 | if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_)) |
174 | && fuzzy_name_length < 2 | 197 | && fuzzy_name_length < 2 |
175 | { | 198 | { |
176 | cov_mark::hit!(ignore_short_input_for_path); | 199 | cov_mark::hit!(ignore_short_input_for_path); |
177 | None | 200 | None |
178 | } else { | 201 | } else { |
179 | assets_for_path | 202 | Some(assets_for_path) |
180 | } | 203 | } |
181 | } | 204 | } |
182 | } | 205 | } |
@@ -186,11 +209,11 @@ fn compute_fuzzy_completion_order_key( | |||
186 | user_input_lowercased: &str, | 209 | user_input_lowercased: &str, |
187 | ) -> usize { | 210 | ) -> usize { |
188 | cov_mark::hit!(certain_fuzzy_order_test); | 211 | cov_mark::hit!(certain_fuzzy_order_test); |
189 | let proposed_import_name = match proposed_mod_path.segments().last() { | 212 | let import_name = match proposed_mod_path.segments().last() { |
190 | Some(name) => name.to_string().to_lowercase(), | 213 | Some(name) => name.to_string().to_lowercase(), |
191 | None => return usize::MAX, | 214 | None => return usize::MAX, |
192 | }; | 215 | }; |
193 | match proposed_import_name.match_indices(user_input_lowercased).next() { | 216 | match import_name.match_indices(user_input_lowercased).next() { |
194 | Some((first_matching_index, _)) => first_matching_index, | 217 | Some((first_matching_index, _)) => first_matching_index, |
195 | None => usize::MAX, | 218 | None => usize::MAX, |
196 | } | 219 | } |
@@ -773,4 +796,155 @@ fn main() { | |||
773 | }"#, | 796 | }"#, |
774 | ); | 797 | ); |
775 | } | 798 | } |
799 | |||
800 | #[test] | ||
801 | fn unresolved_qualifier() { | ||
802 | let fixture = r#" | ||
803 | mod foo { | ||
804 | pub mod bar { | ||
805 | pub mod baz { | ||
806 | pub struct Item; | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | |||
811 | fn main() { | ||
812 | bar::baz::Ite$0 | ||
813 | }"#; | ||
814 | |||
815 | check( | ||
816 | fixture, | ||
817 | expect![[r#" | ||
818 | st foo::bar::baz::Item | ||
819 | "#]], | ||
820 | ); | ||
821 | |||
822 | check_edit( | ||
823 | "Item", | ||
824 | fixture, | ||
825 | r#" | ||
826 | use foo::bar; | ||
827 | |||
828 | mod foo { | ||
829 | pub mod bar { | ||
830 | pub mod baz { | ||
831 | pub struct Item; | ||
832 | } | ||
833 | } | ||
834 | } | ||
835 | |||
836 | fn main() { | ||
837 | bar::baz::Item | ||
838 | }"#, | ||
839 | ); | ||
840 | } | ||
841 | |||
842 | #[test] | ||
843 | fn unresolved_assoc_item_container() { | ||
844 | let fixture = r#" | ||
845 | mod foo { | ||
846 | pub struct Item; | ||
847 | |||
848 | impl Item { | ||
849 | pub const TEST_ASSOC: usize = 3; | ||
850 | } | ||
851 | } | ||
852 | |||
853 | fn main() { | ||
854 | Item::TEST_A$0 | ||
855 | }"#; | ||
856 | |||
857 | check( | ||
858 | fixture, | ||
859 | expect![[r#" | ||
860 | ct TEST_ASSOC (foo::Item) | ||
861 | "#]], | ||
862 | ); | ||
863 | |||
864 | check_edit( | ||
865 | "TEST_ASSOC", | ||
866 | fixture, | ||
867 | r#" | ||
868 | use foo::Item; | ||
869 | |||
870 | mod foo { | ||
871 | pub struct Item; | ||
872 | |||
873 | impl Item { | ||
874 | pub const TEST_ASSOC: usize = 3; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | fn main() { | ||
879 | Item::TEST_ASSOC | ||
880 | }"#, | ||
881 | ); | ||
882 | } | ||
883 | |||
884 | #[test] | ||
885 | fn unresolved_assoc_item_container_with_path() { | ||
886 | let fixture = r#" | ||
887 | mod foo { | ||
888 | pub mod bar { | ||
889 | pub struct Item; | ||
890 | |||
891 | impl Item { | ||
892 | pub const TEST_ASSOC: usize = 3; | ||
893 | } | ||
894 | } | ||
895 | } | ||
896 | |||
897 | fn main() { | ||
898 | bar::Item::TEST_A$0 | ||
899 | }"#; | ||
900 | |||
901 | check( | ||
902 | fixture, | ||
903 | expect![[r#" | ||
904 | ct TEST_ASSOC (foo::bar::Item) | ||
905 | "#]], | ||
906 | ); | ||
907 | |||
908 | check_edit( | ||
909 | "TEST_ASSOC", | ||
910 | fixture, | ||
911 | r#" | ||
912 | use foo::bar; | ||
913 | |||
914 | mod foo { | ||
915 | pub mod bar { | ||
916 | pub struct Item; | ||
917 | |||
918 | impl Item { | ||
919 | pub const TEST_ASSOC: usize = 3; | ||
920 | } | ||
921 | } | ||
922 | } | ||
923 | |||
924 | fn main() { | ||
925 | bar::Item::TEST_ASSOC | ||
926 | }"#, | ||
927 | ); | ||
928 | } | ||
929 | |||
930 | #[test] | ||
931 | fn fuzzy_unresolved_path() { | ||
932 | check( | ||
933 | r#" | ||
934 | mod foo { | ||
935 | pub mod bar { | ||
936 | pub struct Item; | ||
937 | |||
938 | impl Item { | ||
939 | pub const TEST_ASSOC: usize = 3; | ||
940 | } | ||
941 | } | ||
942 | } | ||
943 | |||
944 | fn main() { | ||
945 | bar::Ass$0 | ||
946 | }"#, | ||
947 | expect![[]], | ||
948 | ) | ||
949 | } | ||
776 | } | 950 | } |
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index 9b2435c4b..9b039e3e5 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs | |||
@@ -2,15 +2,16 @@ | |||
2 | 2 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use hir::{Documentation, ModPath, Mutability}; | 5 | use hir::{Documentation, Mutability}; |
6 | use ide_db::{ | 6 | use ide_db::{ |
7 | helpers::{ | 7 | helpers::{ |
8 | import_assets::LocatedImport, | ||
8 | insert_use::{self, ImportScope, InsertUseConfig}, | 9 | insert_use::{self, ImportScope, InsertUseConfig}, |
9 | mod_path_to_ast, SnippetCap, | 10 | mod_path_to_ast, SnippetCap, |
10 | }, | 11 | }, |
11 | SymbolKind, | 12 | SymbolKind, |
12 | }; | 13 | }; |
13 | use stdx::{impl_from, never}; | 14 | use stdx::{format_to, impl_from, never}; |
14 | use syntax::{algo, TextRange}; | 15 | use syntax::{algo, TextRange}; |
15 | use text_edit::TextEdit; | 16 | use text_edit::TextEdit; |
16 | 17 | ||
@@ -272,9 +273,8 @@ impl CompletionItem { | |||
272 | /// An extra import to add after the completion is applied. | 273 | /// An extra import to add after the completion is applied. |
273 | #[derive(Debug, Clone)] | 274 | #[derive(Debug, Clone)] |
274 | pub struct ImportEdit { | 275 | pub struct ImportEdit { |
275 | pub import_path: ModPath, | 276 | pub import: LocatedImport, |
276 | pub import_scope: ImportScope, | 277 | pub scope: ImportScope, |
277 | pub import_for_trait_assoc_item: bool, | ||
278 | } | 278 | } |
279 | 279 | ||
280 | impl ImportEdit { | 280 | impl ImportEdit { |
@@ -284,7 +284,7 @@ impl ImportEdit { | |||
284 | let _p = profile::span("ImportEdit::to_text_edit"); | 284 | let _p = profile::span("ImportEdit::to_text_edit"); |
285 | 285 | ||
286 | let rewriter = | 286 | let rewriter = |
287 | insert_use::insert_use(&self.import_scope, mod_path_to_ast(&self.import_path), cfg); | 287 | insert_use::insert_use(&self.scope, mod_path_to_ast(&self.import.import_path), cfg); |
288 | let old_ast = rewriter.rewrite_root()?; | 288 | let old_ast = rewriter.rewrite_root()?; |
289 | let mut import_insert = TextEdit::builder(); | 289 | let mut import_insert = TextEdit::builder(); |
290 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | 290 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); |
@@ -322,20 +322,19 @@ impl Builder { | |||
322 | let mut lookup = self.lookup; | 322 | let mut lookup = self.lookup; |
323 | let mut insert_text = self.insert_text; | 323 | let mut insert_text = self.insert_text; |
324 | 324 | ||
325 | if let Some(import_to_add) = self.import_to_add.as_ref() { | 325 | if let Some(original_path) = self |
326 | if import_to_add.import_for_trait_assoc_item { | 326 | .import_to_add |
327 | lookup = lookup.or_else(|| Some(label.clone())); | 327 | .as_ref() |
328 | insert_text = insert_text.or_else(|| Some(label.clone())); | 328 | .and_then(|import_edit| import_edit.import.original_path.as_ref()) |
329 | label = format!("{} ({})", label, import_to_add.import_path); | 329 | { |
330 | lookup = lookup.or_else(|| Some(label.clone())); | ||
331 | insert_text = insert_text.or_else(|| Some(label.clone())); | ||
332 | |||
333 | let original_path_label = original_path.to_string(); | ||
334 | if original_path_label.ends_with(&label) { | ||
335 | label = original_path_label; | ||
330 | } else { | 336 | } else { |
331 | let mut import_path_without_last_segment = import_to_add.import_path.to_owned(); | 337 | format_to!(label, " ({})", original_path) |
332 | let _ = import_path_without_last_segment.pop_segment(); | ||
333 | |||
334 | if !import_path_without_last_segment.segments().is_empty() { | ||
335 | lookup = lookup.or_else(|| Some(label.clone())); | ||
336 | insert_text = insert_text.or_else(|| Some(label.clone())); | ||
337 | label = format!("{}::{}", import_path_without_last_segment, label); | ||
338 | } | ||
339 | } | 338 | } |
340 | } | 339 | } |
341 | 340 | ||
@@ -439,9 +438,3 @@ impl Builder { | |||
439 | self | 438 | self |
440 | } | 439 | } |
441 | } | 440 | } |
442 | |||
443 | impl<'a> Into<CompletionItem> for Builder { | ||
444 | fn into(self) -> CompletionItem { | ||
445 | self.build() | ||
446 | } | ||
447 | } | ||
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index b0b809791..a0c8c374d 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs | |||
@@ -13,7 +13,9 @@ mod completions; | |||
13 | 13 | ||
14 | use completions::flyimport::position_for_import; | 14 | use completions::flyimport::position_for_import; |
15 | use ide_db::{ | 15 | use ide_db::{ |
16 | base_db::FilePosition, helpers::insert_use::ImportScope, imports_locator, RootDatabase, | 16 | base_db::FilePosition, |
17 | helpers::{import_assets::LocatedImport, insert_use::ImportScope}, | ||
18 | items_locator, RootDatabase, | ||
17 | }; | 19 | }; |
18 | use text_edit::TextEdit; | 20 | use text_edit::TextEdit; |
19 | 21 | ||
@@ -139,25 +141,27 @@ pub fn resolve_completion_edits( | |||
139 | position: FilePosition, | 141 | position: FilePosition, |
140 | full_import_path: &str, | 142 | full_import_path: &str, |
141 | imported_name: String, | 143 | imported_name: String, |
142 | import_for_trait_assoc_item: bool, | ||
143 | ) -> Option<Vec<TextEdit>> { | 144 | ) -> Option<Vec<TextEdit>> { |
144 | let ctx = CompletionContext::new(db, position, config)?; | 145 | let ctx = CompletionContext::new(db, position, config)?; |
145 | let position_for_import = position_for_import(&ctx, None)?; | 146 | let position_for_import = position_for_import(&ctx, None)?; |
146 | let import_scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?; | 147 | let scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?; |
147 | 148 | ||
148 | let current_module = ctx.sema.scope(position_for_import).module()?; | 149 | let current_module = ctx.sema.scope(position_for_import).module()?; |
149 | let current_crate = current_module.krate(); | 150 | let current_crate = current_module.krate(); |
150 | 151 | ||
151 | let import_path = imports_locator::find_exact_imports(&ctx.sema, current_crate, imported_name) | 152 | let (import_path, item_to_import) = |
152 | .filter_map(|candidate| { | 153 | items_locator::with_exact_name(&ctx.sema, current_crate, imported_name) |
153 | let item: hir::ItemInNs = candidate.either(Into::into, Into::into); | 154 | .into_iter() |
154 | current_module.find_use_path_prefixed(db, item, config.insert_use.prefix_kind) | 155 | .filter_map(|candidate| { |
155 | }) | 156 | current_module |
156 | .find(|mod_path| mod_path.to_string() == full_import_path)?; | 157 | .find_use_path_prefixed(db, candidate, config.insert_use.prefix_kind) |
158 | .zip(Some(candidate)) | ||
159 | }) | ||
160 | .find(|(mod_path, _)| mod_path.to_string() == full_import_path)?; | ||
161 | let import = | ||
162 | LocatedImport::new(import_path.clone(), item_to_import, item_to_import, Some(import_path)); | ||
157 | 163 | ||
158 | ImportEdit { import_path, import_scope, import_for_trait_assoc_item } | 164 | ImportEdit { import, scope }.to_text_edit(config.insert_use).map(|edit| vec![edit]) |
159 | .to_text_edit(config.insert_use) | ||
160 | .map(|edit| vec![edit]) | ||
161 | } | 165 | } |
162 | 166 | ||
163 | #[cfg(test)] | 167 | #[cfg(test)] |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index dcfac23c5..fae5685e2 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -13,7 +13,10 @@ mod builder_ext; | |||
13 | use hir::{ | 13 | use hir::{ |
14 | AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, | 14 | AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, |
15 | }; | 15 | }; |
16 | use ide_db::{helpers::SnippetCap, RootDatabase, SymbolKind}; | 16 | use ide_db::{ |
17 | helpers::{item_name, SnippetCap}, | ||
18 | RootDatabase, SymbolKind, | ||
19 | }; | ||
17 | use syntax::TextRange; | 20 | use syntax::TextRange; |
18 | 21 | ||
19 | use crate::{ | 22 | use crate::{ |
@@ -50,18 +53,20 @@ pub(crate) fn render_resolution<'a>( | |||
50 | pub(crate) fn render_resolution_with_import<'a>( | 53 | pub(crate) fn render_resolution_with_import<'a>( |
51 | ctx: RenderContext<'a>, | 54 | ctx: RenderContext<'a>, |
52 | import_edit: ImportEdit, | 55 | import_edit: ImportEdit, |
53 | resolution: &ScopeDef, | ||
54 | ) -> Option<CompletionItem> { | 56 | ) -> Option<CompletionItem> { |
57 | let resolution = ScopeDef::from(import_edit.import.original_item); | ||
55 | let local_name = match resolution { | 58 | let local_name = match resolution { |
56 | 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(), |
57 | 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(), |
58 | 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(), |
59 | _ => import_edit.import_path.segments().last()?.to_string(), | 62 | _ => item_name(ctx.db(), import_edit.import.original_item)?.to_string(), |
60 | }; | 63 | }; |
61 | 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( |
62 | item.completion_kind = CompletionKind::Magic; | 65 | |mut item| { |
63 | item | 66 | item.completion_kind = CompletionKind::Magic; |
64 | }) | 67 | item |
68 | }, | ||
69 | ) | ||
65 | } | 70 | } |
66 | 71 | ||
67 | /// Interface for data and methods required for items rendering. | 72 | /// Interface for data and methods required for items rendering. |