aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r--crates/ide_completion/src/completions/pattern.rs116
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs88
-rw-r--r--crates/ide_completion/src/context.rs2
-rw-r--r--crates/ide_completion/src/render.rs60
-rw-r--r--crates/ide_completion/src/render/function.rs17
-rw-r--r--crates/ide_completion/src/render/pattern.rs36
6 files changed, 196 insertions, 123 deletions
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
index 9282c3827..46cef58f0 100644
--- a/crates/ide_completion/src/completions/pattern.rs
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -11,10 +11,13 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
11 return; 11 return;
12 } 12 }
13 13
14 if let Some(ty) = &ctx.expected_type { 14 if !ctx.is_irrefutable_pat_binding {
15 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { 15 if let Some(ty) = ctx.expected_type.as_ref() {
16 acc.add_qualified_variant_pat(ctx, variant, path) 16 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| {
17 }); 17 acc.add_qualified_variant_pat(ctx, variant, path.clone());
18 acc.add_qualified_enum_variant(ctx, variant, path);
19 });
20 }
18 } 21 }
19 22
20 // FIXME: ideally, we should look at the type we are matching against and 23 // FIXME: ideally, we should look at the type we are matching against and
@@ -85,7 +88,7 @@ static FOO: E = E::X;
85struct Bar { f: u32 } 88struct Bar { f: u32 }
86 89
87fn foo() { 90fn foo() {
88 match E::X { $0 } 91 match E::X { a$0 }
89} 92}
90"#, 93"#,
91 expect![[r#" 94 expect![[r#"
@@ -106,10 +109,11 @@ macro_rules! m { ($e:expr) => { $e } }
106enum E { X } 109enum E { X }
107 110
108fn foo() { 111fn foo() {
109 m!(match E::X { $0 }) 112 m!(match E::X { a$0 })
110} 113}
111"#, 114"#,
112 expect![[r#" 115 expect![[r#"
116 ev E::X ()
113 en E 117 en E
114 ma m!(…) macro_rules! m 118 ma m!(…) macro_rules! m
115 "#]], 119 "#]],
@@ -129,7 +133,7 @@ static FOO: E = E::X;
129struct Bar { f: u32 } 133struct Bar { f: u32 }
130 134
131fn foo() { 135fn foo() {
132 let $0 136 let a$0
133} 137}
134"#, 138"#,
135 expect![[r#" 139 expect![[r#"
@@ -147,7 +151,7 @@ enum E { X }
147static FOO: E = E::X; 151static FOO: E = E::X;
148struct Bar { f: u32 } 152struct Bar { f: u32 }
149 153
150fn foo($0) { 154fn foo(a$0) {
151} 155}
152"#, 156"#,
153 expect![[r#" 157 expect![[r#"
@@ -163,7 +167,7 @@ fn foo($0) {
163struct Bar { f: u32 } 167struct Bar { f: u32 }
164 168
165fn foo() { 169fn foo() {
166 let $0 170 let a$0
167} 171}
168"#, 172"#,
169 expect![[r#" 173 expect![[r#"
@@ -179,7 +183,7 @@ fn foo() {
179struct Foo { bar: String, baz: String } 183struct Foo { bar: String, baz: String }
180struct Bar(String, String); 184struct Bar(String, String);
181struct Baz; 185struct Baz;
182fn outer($0) {} 186fn outer(a$0) {}
183"#, 187"#,
184 expect![[r#" 188 expect![[r#"
185 bn Foo Foo { bar$1, baz$2 }: Foo$0 189 bn Foo Foo { bar$1, baz$2 }: Foo$0
@@ -196,7 +200,7 @@ struct Foo { bar: String, baz: String }
196struct Bar(String, String); 200struct Bar(String, String);
197struct Baz; 201struct Baz;
198fn outer() { 202fn outer() {
199 let $0 203 let a$0
200} 204}
201"#, 205"#,
202 expect![[r#" 206 expect![[r#"
@@ -215,7 +219,7 @@ struct Bar(String, String);
215struct Baz; 219struct Baz;
216fn outer() { 220fn outer() {
217 match () { 221 match () {
218 $0 222 a$0
219 } 223 }
220} 224}
221"#, 225"#,
@@ -239,7 +243,7 @@ use foo::*;
239 243
240fn outer() { 244fn outer() {
241 match () { 245 match () {
242 $0 246 a$0
243 } 247 }
244} 248}
245"#, 249"#,
@@ -258,7 +262,7 @@ fn outer() {
258struct Foo(i32); 262struct Foo(i32);
259fn main() { 263fn main() {
260 match Foo(92) { 264 match Foo(92) {
261 $0(92) => (), 265 a$0(92) => (),
262 } 266 }
263} 267}
264"#, 268"#,
@@ -281,7 +285,7 @@ struct Foo(i32);
281impl Foo { 285impl Foo {
282 fn foo() { 286 fn foo() {
283 match () { 287 match () {
284 $0 288 a$0
285 } 289 }
286 } 290 }
287} 291}
@@ -314,4 +318,86 @@ impl Foo {
314 "#]], 318 "#]],
315 ) 319 )
316 } 320 }
321
322 #[test]
323 fn completes_enum_variant_matcharm() {
324 check(
325 r#"
326enum Foo { Bar, Baz, Quux }
327
328fn main() {
329 let foo = Foo::Quux;
330 match foo { Qu$0 }
331}
332"#,
333 expect![[r#"
334 ev Foo::Bar ()
335 ev Foo::Baz ()
336 ev Foo::Quux ()
337 en Foo
338 "#]],
339 )
340 }
341
342 #[test]
343 fn completes_enum_variant_matcharm_ref() {
344 check(
345 r#"
346enum Foo { Bar, Baz, Quux }
347
348fn main() {
349 let foo = Foo::Quux;
350 match &foo { Qu$0 }
351}
352"#,
353 expect![[r#"
354 ev Foo::Bar ()
355 ev Foo::Baz ()
356 ev Foo::Quux ()
357 en Foo
358 "#]],
359 )
360 }
361
362 #[test]
363 fn completes_enum_variant_iflet() {
364 check(
365 r#"
366enum Foo { Bar, Baz, Quux }
367
368fn main() {
369 let foo = Foo::Quux;
370 if let Qu$0 = foo { }
371}
372"#,
373 expect![[r#"
374 ev Foo::Bar ()
375 ev Foo::Baz ()
376 ev Foo::Quux ()
377 en Foo
378 "#]],
379 )
380 }
381
382 #[test]
383 fn completes_enum_variant_impl() {
384 check(
385 r#"
386enum Foo { Bar, Baz, Quux }
387impl Foo {
388 fn foo() { match Foo::Bar { Q$0 } }
389}
390"#,
391 expect![[r#"
392 ev Self::Bar ()
393 ev Self::Baz ()
394 ev Self::Quux ()
395 ev Foo::Bar ()
396 ev Foo::Baz ()
397 ev Foo::Quux ()
398 sp Self
399 en Foo
400 "#]],
401 )
402 }
317} 403}
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 044dfd160..5ef80f6a7 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -6,7 +6,7 @@ use syntax::AstNode;
6use crate::{CompletionContext, Completions}; 6use crate::{CompletionContext, Completions};
7 7
8pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 8pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
9 if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) { 9 if !ctx.is_trivial_path {
10 return; 10 return;
11 } 11 }
12 if ctx.record_lit_syntax.is_some() 12 if ctx.record_lit_syntax.is_some()
@@ -23,10 +23,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
23 }); 23 });
24 } 24 }
25 25
26 if ctx.is_pat_binding_or_const {
27 return;
28 }
29
30 ctx.scope.process_all_names(&mut |name, res| { 26 ctx.scope.process_all_names(&mut |name, res| {
31 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { 27 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
32 cov_mark::hit!(skip_lifetime_completion); 28 cov_mark::hit!(skip_lifetime_completion);
@@ -609,66 +605,6 @@ fn main() { $0 }
609 } 605 }
610 606
611 #[test] 607 #[test]
612 fn completes_enum_variant_matcharm() {
613 check(
614 r#"
615enum Foo { Bar, Baz, Quux }
616
617fn main() {
618 let foo = Foo::Quux;
619 match foo { Qu$0 }
620}
621"#,
622 expect![[r#"
623 ev Foo::Bar ()
624 ev Foo::Baz ()
625 ev Foo::Quux ()
626 en Foo
627 "#]],
628 )
629 }
630
631 #[test]
632 fn completes_enum_variant_matcharm_ref() {
633 check(
634 r#"
635enum Foo { Bar, Baz, Quux }
636
637fn main() {
638 let foo = Foo::Quux;
639 match &foo { Qu$0 }
640}
641"#,
642 expect![[r#"
643 ev Foo::Bar ()
644 ev Foo::Baz ()
645 ev Foo::Quux ()
646 en Foo
647 "#]],
648 )
649 }
650
651 #[test]
652 fn completes_enum_variant_iflet() {
653 check(
654 r#"
655enum Foo { Bar, Baz, Quux }
656
657fn main() {
658 let foo = Foo::Quux;
659 if let Qu$0 = foo { }
660}
661"#,
662 expect![[r#"
663 ev Foo::Bar ()
664 ev Foo::Baz ()
665 ev Foo::Quux ()
666 en Foo
667 "#]],
668 )
669 }
670
671 #[test]
672 fn completes_enum_variant_basic_expr() { 608 fn completes_enum_variant_basic_expr() {
673 check( 609 check(
674 r#" 610 r#"
@@ -701,28 +637,6 @@ fn f() -> m::E { V$0 }
701 } 637 }
702 638
703 #[test] 639 #[test]
704 fn completes_enum_variant_impl() {
705 check(
706 r#"
707enum Foo { Bar, Baz, Quux }
708impl Foo {
709 fn foo() { match Foo::Bar { Q$0 } }
710}
711"#,
712 expect![[r#"
713 ev Self::Bar ()
714 ev Self::Baz ()
715 ev Self::Quux ()
716 ev Foo::Bar ()
717 ev Foo::Baz ()
718 ev Foo::Quux ()
719 sp Self
720 en Foo
721 "#]],
722 )
723 }
724
725 #[test]
726 fn dont_complete_attr() { 640 fn dont_complete_attr() {
727 check( 641 check(
728 r#" 642 r#"
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 89e9bda78..e6cc6329c 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -350,7 +350,6 @@ impl<'a> CompletionContext<'a> {
350 }, 350 },
351 ast::IdentPat(it) => { 351 ast::IdentPat(it) => {
352 cov_mark::hit!(expected_type_if_let_with_leading_char); 352 cov_mark::hit!(expected_type_if_let_with_leading_char);
353 cov_mark::hit!(expected_type_if_let_without_leading_char);
354 cov_mark::hit!(expected_type_match_arm_with_leading_char); 353 cov_mark::hit!(expected_type_match_arm_with_leading_char);
355 let ty = self.sema.type_of_pat(&ast::Pat::from(it)); 354 let ty = self.sema.type_of_pat(&ast::Pat::from(it));
356 355
@@ -748,7 +747,6 @@ fn foo() {
748 747
749 #[test] 748 #[test]
750 fn expected_type_if_let_without_leading_char() { 749 fn expected_type_if_let_without_leading_char() {
751 cov_mark::check!(expected_type_if_let_without_leading_char);
752 check_expected_type_and_name( 750 check_expected_type_and_name(
753 r#" 751 r#"
754enum Foo { Bar, Baz, Quux } 752enum Foo { Bar, Baz, Quux }
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 670563e50..2514dda7c 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -928,6 +928,66 @@ fn f(foo: &Foo) { f(foo, w$0) }
928 } 928 }
929 929
930 #[test] 930 #[test]
931 fn score_fn_type_and_name_match() {
932 check_relevance(
933 r#"
934struct A { bar: u8 }
935fn baz() -> u8 { 0 }
936fn bar() -> u8 { 0 }
937fn f() { A { bar: b$0 }; }
938"#,
939 expect![[r#"
940 fn baz() [type]
941 st A []
942 fn bar() [type+name]
943 fn f() []
944 "#]],
945 );
946 }
947
948 #[test]
949 fn score_method_type_and_name_match() {
950 check_relevance(
951 r#"
952fn baz(aaa: u32){}
953struct Foo;
954impl Foo {
955fn aaa(&self) -> u32 { 0 }
956fn bbb(&self) -> u32 { 0 }
957fn ccc(&self) -> u64 { 0 }
958}
959fn f() {
960 baz(Foo.$0
961}
962"#,
963 expect![[r#"
964 me aaa() [type+name]
965 me bbb() [type]
966 me ccc() []
967 "#]],
968 );
969 }
970
971 #[test]
972 fn score_method_name_match_only() {
973 check_relevance(
974 r#"
975fn baz(aaa: u32){}
976struct Foo;
977impl Foo {
978fn aaa(&self) -> u64 { 0 }
979}
980fn f() {
981 baz(Foo.$0
982}
983"#,
984 expect![[r#"
985 me aaa() [name]
986 "#]],
987 );
988 }
989
990 #[test]
931 fn suggest_ref_mut() { 991 fn suggest_ref_mut() {
932 cov_mark::check!(suggest_ref); 992 cov_mark::check!(suggest_ref);
933 check( 993 check(
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index f4dabe3d1..47e26a5d8 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -5,7 +5,7 @@ use ide_db::SymbolKind;
5use syntax::ast::Fn; 5use syntax::ast::Fn;
6 6
7use crate::{ 7use crate::{
8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportEdit}, 8 item::{CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, ImportEdit},
9 render::{builder_ext::Params, RenderContext}, 9 render::{builder_ext::Params, RenderContext},
10}; 10};
11 11
@@ -55,6 +55,21 @@ impl<'a> FunctionRender<'a> {
55 .add_call_parens(self.ctx.completion, self.name, params) 55 .add_call_parens(self.ctx.completion, self.name, params)
56 .add_import(import_to_add); 56 .add_import(import_to_add);
57 57
58 let mut relevance = CompletionRelevance::default();
59 if let Some(expected_type) = &self.ctx.completion.expected_type {
60 let ret_ty = self.func.ret_type(self.ctx.db());
61
62 // We don't ever consider a function which returns unit type to be an
63 // exact type match, since nearly always this is not meaningful to the
64 // user.
65 relevance.exact_type_match = &ret_ty == expected_type && !ret_ty.is_unit();
66 }
67 if let Some(expected_name) = &self.ctx.completion.expected_name {
68 relevance.exact_name_match =
69 expected_name == &self.func.name(self.ctx.db()).to_string();
70 }
71 item.set_relevance(relevance);
72
58 item.build() 73 item.build()
59 } 74 }
60 75
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index ca2926125..b4e80f424 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -6,24 +6,6 @@ use itertools::Itertools;
6 6
7use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind}; 7use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind};
8 8
9fn visible_fields(
10 ctx: &RenderContext<'_>,
11 fields: &[hir::Field],
12 item: impl HasAttrs,
13) -> Option<(Vec<hir::Field>, bool)> {
14 let module = ctx.completion.scope.module()?;
15 let n_fields = fields.len();
16 let fields = fields
17 .into_iter()
18 .filter(|field| field.is_visible_from(ctx.db(), module))
19 .copied()
20 .collect::<Vec<_>>();
21
22 let fields_omitted =
23 n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists();
24 Some((fields, fields_omitted))
25}
26
27pub(crate) fn render_struct_pat( 9pub(crate) fn render_struct_pat(
28 ctx: RenderContext<'_>, 10 ctx: RenderContext<'_>,
29 strukt: hir::Struct, 11 strukt: hir::Struct,
@@ -148,3 +130,21 @@ fn render_tuple_as_pat(fields: &[hir::Field], name: &str, fields_omitted: bool)
148 name = name 130 name = name
149 ) 131 )
150} 132}
133
134fn visible_fields(
135 ctx: &RenderContext<'_>,
136 fields: &[hir::Field],
137 item: impl HasAttrs,
138) -> Option<(Vec<hir::Field>, bool)> {
139 let module = ctx.completion.scope.module()?;
140 let n_fields = fields.len();
141 let fields = fields
142 .into_iter()
143 .filter(|field| field.is_visible_from(ctx.db(), module))
144 .copied()
145 .collect::<Vec<_>>();
146
147 let fields_omitted =
148 n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists();
149 Some((fields, fields_omitted))
150}