aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/completions
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/completions')
-rw-r--r--crates/completion/src/completions/pattern.rs57
-rw-r--r--crates/completion/src/completions/postfix.rs59
-rw-r--r--crates/completion/src/completions/record.rs4
-rw-r--r--crates/completion/src/completions/unqualified_path.rs60
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.
6pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { 6pub(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#"
100enum E { X }
101use self::E::X;
102const Z: E = E::X;
103mod m {}
104
105static FOO: E = E::X;
106struct Bar { f: u32 }
107
108fn 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;
5use ide_db::ty_filter::TryEnum; 5use ide_db::ty_filter::TryEnum;
6use syntax::{ 6use syntax::{
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 SyntaxKind::BLOCK_EXPR,
8 TextRange, TextSize, 9 TextRange, TextSize,
9}; 10};
10use text_edit::TextEdit; 11use 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#"
341fn foo(elt: bool) -> bool {
342 !elt
343}
344
345fn 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.
2use assists::utils::FamousDefs; 2use ide_db::helpers::FamousDefs;
3use syntax::ast::Expr; 3use syntax::ast::Expr;
4 4
5use crate::{ 5use crate::{
@@ -45,8 +45,8 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
45 45
46#[cfg(test)] 46#[cfg(test)]
47mod tests { 47mod 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
3use assists::utils::ImportScope;
4use either::Either; 3use either::Either;
5use hir::{Adt, ModuleDef, ScopeDef, Type}; 4use hir::{Adt, ModuleDef, ScopeDef, Type};
5use ide_db::helpers::insert_use::ImportScope;
6use ide_db::imports_locator; 6use ide_db::imports_locator;
7use syntax::AstNode; 7use syntax::AstNode;
8use test_utils::mark; 8use 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
50fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { 52fn 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(())