diff options
Diffstat (limited to 'crates/completion/src/completions')
-rw-r--r-- | crates/completion/src/completions/pattern.rs | 57 | ||||
-rw-r--r-- | crates/completion/src/completions/postfix.rs | 59 | ||||
-rw-r--r-- | crates/completion/src/completions/record.rs | 4 | ||||
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 60 |
4 files changed, 136 insertions, 44 deletions
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 7ab7f09fe..4f63ff0ef 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs | |||
@@ -4,7 +4,7 @@ use crate::{CompletionContext, Completions}; | |||
4 | 4 | ||
5 | /// Completes constats and paths in patterns. | 5 | /// Completes constats and paths in patterns. |
6 | pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | 6 | pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { |
7 | if !ctx.is_pat_binding_or_const { | 7 | if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_let_pat_binding) { |
8 | return; | 8 | return; |
9 | } | 9 | } |
10 | if ctx.record_pat_syntax.is_some() { | 10 | if ctx.record_pat_syntax.is_some() { |
@@ -14,20 +14,27 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
14 | // FIXME: ideally, we should look at the type we are matching against and | 14 | // FIXME: ideally, we should look at the type we are matching against and |
15 | // suggest variants + auto-imports | 15 | // suggest variants + auto-imports |
16 | ctx.scope.process_all_names(&mut |name, res| { | 16 | ctx.scope.process_all_names(&mut |name, res| { |
17 | match &res { | 17 | let add_resolution = match &res { |
18 | hir::ScopeDef::ModuleDef(def) => match def { | 18 | hir::ScopeDef::ModuleDef(def) => { |
19 | hir::ModuleDef::Adt(hir::Adt::Enum(..)) | 19 | if ctx.is_irrefutable_let_pat_binding { |
20 | | hir::ModuleDef::Adt(hir::Adt::Struct(..)) | 20 | matches!(def, hir::ModuleDef::Adt(hir::Adt::Struct(_))) |
21 | | hir::ModuleDef::EnumVariant(..) | 21 | } else { |
22 | | hir::ModuleDef::Const(..) | 22 | matches!( |
23 | | hir::ModuleDef::Module(..) => (), | 23 | def, |
24 | _ => return, | 24 | hir::ModuleDef::Adt(hir::Adt::Enum(..)) |
25 | }, | 25 | | hir::ModuleDef::Adt(hir::Adt::Struct(..)) |
26 | hir::ScopeDef::MacroDef(_) => (), | 26 | | hir::ModuleDef::EnumVariant(..) |
27 | _ => return, | 27 | | hir::ModuleDef::Const(..) |
28 | | hir::ModuleDef::Module(..) | ||
29 | ) | ||
30 | } | ||
31 | } | ||
32 | hir::ScopeDef::MacroDef(_) => true, | ||
33 | _ => false, | ||
28 | }; | 34 | }; |
29 | 35 | if add_resolution { | |
30 | acc.add_resolution(ctx, name.to_string(), &res) | 36 | acc.add_resolution(ctx, name.to_string(), &res); |
37 | } | ||
31 | }); | 38 | }); |
32 | } | 39 | } |
33 | 40 | ||
@@ -85,4 +92,26 @@ fn foo() { | |||
85 | "#]], | 92 | "#]], |
86 | ); | 93 | ); |
87 | } | 94 | } |
95 | |||
96 | #[test] | ||
97 | fn completes_in_irrefutable_let() { | ||
98 | check( | ||
99 | r#" | ||
100 | enum E { X } | ||
101 | use self::E::X; | ||
102 | const Z: E = E::X; | ||
103 | mod m {} | ||
104 | |||
105 | static FOO: E = E::X; | ||
106 | struct Bar { f: u32 } | ||
107 | |||
108 | fn foo() { | ||
109 | let <|> | ||
110 | } | ||
111 | "#, | ||
112 | expect![[r#" | ||
113 | st Bar | ||
114 | "#]], | ||
115 | ); | ||
116 | } | ||
88 | } | 117 | } |
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs index 7fbda7a6b..1785794cc 100644 --- a/crates/completion/src/completions/postfix.rs +++ b/crates/completion/src/completions/postfix.rs | |||
@@ -5,6 +5,7 @@ mod format_like; | |||
5 | use ide_db::ty_filter::TryEnum; | 5 | use ide_db::ty_filter::TryEnum; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | ast::{self, AstNode, AstToken}, | 7 | ast::{self, AstNode, AstToken}, |
8 | SyntaxKind::BLOCK_EXPR, | ||
8 | TextRange, TextSize, | 9 | TextRange, TextSize, |
9 | }; | 10 | }; |
10 | use text_edit::TextEdit; | 11 | use text_edit::TextEdit; |
@@ -220,6 +221,30 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
220 | ) | 221 | ) |
221 | .add_to(acc); | 222 | .add_to(acc); |
222 | 223 | ||
224 | let parent_node = dot_receiver.syntax().parent().and_then(|p| p.parent()); | ||
225 | if let Some(parent) = parent_node { | ||
226 | if parent.kind() == BLOCK_EXPR { | ||
227 | postfix_snippet( | ||
228 | ctx, | ||
229 | cap, | ||
230 | &dot_receiver, | ||
231 | "let", | ||
232 | "let", | ||
233 | &format!("let $0 = {};", receiver_text), | ||
234 | ) | ||
235 | .add_to(acc); | ||
236 | postfix_snippet( | ||
237 | ctx, | ||
238 | cap, | ||
239 | &dot_receiver, | ||
240 | "letm", | ||
241 | "let mut", | ||
242 | &format!("let mut $0 = {};", receiver_text), | ||
243 | ) | ||
244 | .add_to(acc); | ||
245 | } | ||
246 | } | ||
247 | |||
223 | if let ast::Expr::Literal(literal) = dot_receiver.clone() { | 248 | if let ast::Expr::Literal(literal) = dot_receiver.clone() { |
224 | if let Some(literal_text) = ast::String::cast(literal.token()) { | 249 | if let Some(literal_text) = ast::String::cast(literal.token()) { |
225 | add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text); | 250 | add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text); |
@@ -296,6 +321,38 @@ fn main() { | |||
296 | sn dbg dbg!(expr) | 321 | sn dbg dbg!(expr) |
297 | sn dbgr dbg!(&expr) | 322 | sn dbgr dbg!(&expr) |
298 | sn if if expr {} | 323 | sn if if expr {} |
324 | sn let let | ||
325 | sn letm let mut | ||
326 | sn match match expr {} | ||
327 | sn not !expr | ||
328 | sn ok Ok(expr) | ||
329 | sn ref &expr | ||
330 | sn refm &mut expr | ||
331 | sn some Some(expr) | ||
332 | sn while while expr {} | ||
333 | "#]], | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
338 | fn postfix_completion_works_for_function_calln() { | ||
339 | check( | ||
340 | r#" | ||
341 | fn foo(elt: bool) -> bool { | ||
342 | !elt | ||
343 | } | ||
344 | |||
345 | fn main() { | ||
346 | let bar = true; | ||
347 | foo(bar.<|>) | ||
348 | } | ||
349 | "#, | ||
350 | expect![[r#" | ||
351 | sn box Box::new(expr) | ||
352 | sn call function(expr) | ||
353 | sn dbg dbg!(expr) | ||
354 | sn dbgr dbg!(&expr) | ||
355 | sn if if expr {} | ||
299 | sn match match expr {} | 356 | sn match match expr {} |
300 | sn not !expr | 357 | sn not !expr |
301 | sn ok Ok(expr) | 358 | sn ok Ok(expr) |
@@ -321,6 +378,8 @@ fn main() { | |||
321 | sn call function(expr) | 378 | sn call function(expr) |
322 | sn dbg dbg!(expr) | 379 | sn dbg dbg!(expr) |
323 | sn dbgr dbg!(&expr) | 380 | sn dbgr dbg!(&expr) |
381 | sn let let | ||
382 | sn letm let mut | ||
324 | sn match match expr {} | 383 | sn match match expr {} |
325 | sn ok Ok(expr) | 384 | sn ok Ok(expr) |
326 | sn ref &expr | 385 | sn ref &expr |
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs index 2049b9d09..eaa44c97d 100644 --- a/crates/completion/src/completions/record.rs +++ b/crates/completion/src/completions/record.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! Complete fields in record literals and patterns. | 1 | //! Complete fields in record literals and patterns. |
2 | use assists::utils::FamousDefs; | 2 | use ide_db::helpers::FamousDefs; |
3 | use syntax::ast::Expr; | 3 | use syntax::ast::Expr; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
@@ -45,8 +45,8 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> | |||
45 | 45 | ||
46 | #[cfg(test)] | 46 | #[cfg(test)] |
47 | mod tests { | 47 | mod tests { |
48 | use assists::utils::FamousDefs; | ||
49 | use expect_test::{expect, Expect}; | 48 | use expect_test::{expect, Expect}; |
49 | use ide_db::helpers::FamousDefs; | ||
50 | 50 | ||
51 | use crate::{test_utils::completion_list, CompletionKind}; | 51 | use crate::{test_utils::completion_list, CompletionKind}; |
52 | 52 | ||
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 86c143b63..81691cd7f 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use assists::utils::ImportScope; | ||
4 | use either::Either; | 3 | use either::Either; |
5 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | 4 | use hir::{Adt, ModuleDef, ScopeDef, Type}; |
5 | use ide_db::helpers::insert_use::ImportScope; | ||
6 | use ide_db::imports_locator; | 6 | use ide_db::imports_locator; |
7 | use syntax::AstNode; | 7 | use syntax::AstNode; |
8 | use test_utils::mark; | 8 | use test_utils::mark; |
@@ -44,7 +44,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
44 | acc.add_resolution(ctx, name.to_string(), &res) | 44 | acc.add_resolution(ctx, name.to_string(), &res) |
45 | }); | 45 | }); |
46 | 46 | ||
47 | fuzzy_completion(acc, ctx).unwrap_or_default() | 47 | if ctx.config.enable_experimental_completions { |
48 | fuzzy_completion(acc, ctx).unwrap_or_default() | ||
49 | } | ||
48 | } | 50 | } |
49 | 51 | ||
50 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { | 52 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { |
@@ -79,32 +81,34 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
79 | 81 | ||
80 | let potential_import_name = ctx.token.to_string(); | 82 | let potential_import_name = ctx.token.to_string(); |
81 | 83 | ||
82 | let possible_imports = | 84 | let possible_imports = imports_locator::find_similar_imports( |
83 | imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, 400) | 85 | &ctx.sema, |
84 | .filter_map(|import_candidate| match import_candidate { | 86 | ctx.krate?, |
85 | // when completing outside the use declaration, modules are pretty useless | 87 | &potential_import_name, |
86 | // and tend to bloat the completion suggestions a lot | 88 | 50, |
87 | Either::Left(ModuleDef::Module(_)) => None, | 89 | true, |
88 | Either::Left(module_def) => Some(( | 90 | ) |
89 | current_module.find_use_path(ctx.db, module_def)?, | 91 | .filter_map(|import_candidate| { |
90 | ScopeDef::ModuleDef(module_def), | 92 | Some(match import_candidate { |
91 | )), | 93 | Either::Left(module_def) => { |
92 | Either::Right(macro_def) => Some(( | 94 | (current_module.find_use_path(ctx.db, module_def)?, ScopeDef::ModuleDef(module_def)) |
93 | current_module.find_use_path(ctx.db, macro_def)?, | 95 | } |
94 | ScopeDef::MacroDef(macro_def), | 96 | Either::Right(macro_def) => { |
95 | )), | 97 | (current_module.find_use_path(ctx.db, macro_def)?, ScopeDef::MacroDef(macro_def)) |
96 | }) | 98 | } |
97 | .filter(|(mod_path, _)| mod_path.len() > 1) | 99 | }) |
98 | .filter_map(|(import_path, definition)| { | 100 | }) |
99 | render_resolution_with_import( | 101 | .filter(|(mod_path, _)| mod_path.len() > 1) |
100 | RenderContext::new(ctx), | 102 | .take(20) |
101 | import_path.clone(), | 103 | .filter_map(|(import_path, definition)| { |
102 | import_scope.clone(), | 104 | render_resolution_with_import( |
103 | ctx.config.merge, | 105 | RenderContext::new(ctx), |
104 | &definition, | 106 | import_path.clone(), |
105 | ) | 107 | import_scope.clone(), |
106 | }) | 108 | ctx.config.merge, |
107 | .take(20); | 109 | &definition, |
110 | ) | ||
111 | }); | ||
108 | 112 | ||
109 | acc.add_all(possible_imports); | 113 | acc.add_all(possible_imports); |
110 | Some(()) | 114 | Some(()) |