diff options
Diffstat (limited to 'crates/completion/src/completions')
-rw-r--r-- | crates/completion/src/completions/complete_magic.rs | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/crates/completion/src/completions/complete_magic.rs b/crates/completion/src/completions/complete_magic.rs index 857a0b620..9242b860c 100644 --- a/crates/completion/src/completions/complete_magic.rs +++ b/crates/completion/src/completions/complete_magic.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour}; | 3 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour}; |
4 | use hir::Query; | 4 | use hir::Query; |
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use syntax::AstNode; | 6 | use syntax::{algo, AstNode}; |
7 | use text_edit::TextEdit; | 7 | use text_edit::TextEdit; |
8 | 8 | ||
9 | use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind}; | 9 | use crate::{context::CompletionContext, item::CompletionKind, CompletionItem, CompletionItemKind}; |
@@ -17,9 +17,6 @@ pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> | |||
17 | let current_module = ctx.scope.module()?; | 17 | let current_module = ctx.scope.module()?; |
18 | let anchor = ctx.name_ref_syntax.as_ref()?; | 18 | let anchor = ctx.name_ref_syntax.as_ref()?; |
19 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; | 19 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; |
20 | // TODO kb now this is the whole file, which is not disjoint with any other change in the same file, fix it | ||
21 | // otherwise it's impossible to correctly add the use statement and also change the completed text into something more meaningful | ||
22 | let import_syntax = import_scope.as_syntax_node(); | ||
23 | 20 | ||
24 | // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion" | 21 | // TODO kb consider heuristics, such as "don't show `hash_map` import if `HashMap` is the import for completion" |
25 | // TODO kb module functions are not completed, consider `std::io::stdin` one | 22 | // TODO kb module functions are not completed, consider `std::io::stdin` one |
@@ -35,15 +32,16 @@ pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> | |||
35 | either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def), | 32 | either::Either::Right(macro_def) => current_module.find_use_path(ctx.db, macro_def), |
36 | }) | 33 | }) |
37 | .filter_map(|mod_path| { | 34 | .filter_map(|mod_path| { |
35 | let mut builder = TextEdit::builder(); | ||
36 | |||
38 | let correct_qualifier = mod_path.segments.last()?.to_string(); | 37 | let correct_qualifier = mod_path.segments.last()?.to_string(); |
38 | builder.replace(anchor.syntax().text_range(), correct_qualifier); | ||
39 | |||
40 | // TODO kb: assists already have the merge behaviour setting, need to unite both | ||
39 | let rewriter = | 41 | let rewriter = |
40 | insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full)); | 42 | insert_use(&import_scope, mod_path_to_ast(&mod_path), Some(MergeBehaviour::Full)); |
41 | let rewritten_node = rewriter.rewrite(import_syntax); | 43 | let old_ast = rewriter.rewrite_root()?; |
42 | let insert_use_edit = | 44 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut builder); |
43 | TextEdit::replace(import_syntax.text_range(), rewritten_node.to_string()); | ||
44 | let mut completion_edit = | ||
45 | TextEdit::replace(anchor.syntax().text_range(), correct_qualifier); | ||
46 | completion_edit.union(insert_use_edit).expect("TODO kb"); | ||
47 | 45 | ||
48 | let completion_item: CompletionItem = CompletionItem::new( | 46 | let completion_item: CompletionItem = CompletionItem::new( |
49 | CompletionKind::Magic, | 47 | CompletionKind::Magic, |
@@ -51,7 +49,7 @@ pub(crate) fn complete_magic(acc: &mut Completions, ctx: &CompletionContext) -> | |||
51 | mod_path.to_string(), | 49 | mod_path.to_string(), |
52 | ) | 50 | ) |
53 | .kind(CompletionItemKind::Struct) | 51 | .kind(CompletionItemKind::Struct) |
54 | .text_edit(completion_edit) | 52 | .text_edit(builder.finish()) |
55 | .into(); | 53 | .into(); |
56 | Some(completion_item) | 54 | Some(completion_item) |
57 | }); | 55 | }); |
@@ -75,6 +73,48 @@ mod tests { | |||
75 | } | 73 | } |
76 | 74 | ||
77 | #[test] | 75 | #[test] |
76 | fn function_magic_completion() { | ||
77 | check( | ||
78 | r#" | ||
79 | //- /lib.rs crate:dep | ||
80 | pub mod io { | ||
81 | pub fn stdin() {} | ||
82 | }; | ||
83 | |||
84 | //- /main.rs crate:main deps:dep | ||
85 | fn main() { | ||
86 | stdi<|> | ||
87 | } | ||
88 | "#, | ||
89 | expect![[r#" | ||
90 | st dep::io::stdin | ||
91 | "#]], | ||
92 | ); | ||
93 | |||
94 | check_edit( | ||
95 | "dep::io::stdin", | ||
96 | r#" | ||
97 | //- /lib.rs crate:dep | ||
98 | pub mod io { | ||
99 | pub fn stdin() {} | ||
100 | }; | ||
101 | |||
102 | //- /main.rs crate:main deps:dep | ||
103 | fn main() { | ||
104 | stdi<|> | ||
105 | } | ||
106 | "#, | ||
107 | r#" | ||
108 | use dep::io::stdin; | ||
109 | |||
110 | fn main() { | ||
111 | stdin | ||
112 | } | ||
113 | "#, | ||
114 | ); | ||
115 | } | ||
116 | |||
117 | #[test] | ||
78 | fn case_insensitive_magic_completion_works() { | 118 | fn case_insensitive_magic_completion_works() { |
79 | check( | 119 | check( |
80 | r#" | 120 | r#" |