diff options
author | Benjamin Coenen <[email protected]> | 2020-04-09 08:39:17 +0100 |
---|---|---|
committer | Benjamin Coenen <[email protected]> | 2020-04-09 08:53:53 +0100 |
commit | 585bb83e2aec9c79dae8c2e031e9165f40937003 (patch) | |
tree | 3dda062f3deb768b211e7e091dd5b29b9b6fae84 /crates/ra_ide/src/completion | |
parent | 8f1dba6f9ae1d8d314dd9d007e4c582ed1403e8d (diff) | |
parent | 080c983498afcac3eb54028af5c9f8bfe7f2c826 (diff) |
feat: add attributes support on struct fields and method #3870
Signed-off-by: Benjamin Coenen <[email protected]>
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_record.rs | 96 |
1 files changed, 44 insertions, 52 deletions
diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs index 79f5c8c8f..f46bcee5c 100644 --- a/crates/ra_ide/src/completion/complete_record.rs +++ b/crates/ra_ide/src/completion/complete_record.rs | |||
@@ -1,65 +1,24 @@ | |||
1 | //! Complete fields in record literals and patterns. | 1 | //! Complete fields in record literals and patterns. |
2 | use ra_syntax::{ast, ast::NameOwner, SmolStr}; | ||
3 | |||
4 | use crate::completion::{CompletionContext, Completions}; | 2 | use crate::completion::{CompletionContext, Completions}; |
5 | 3 | ||
6 | pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { | 4 | pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { |
7 | let (ty, variant, already_present_fields) = | 5 | let missing_fields = match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) { |
8 | match (ctx.record_lit_pat.as_ref(), ctx.record_lit_syntax.as_ref()) { | 6 | (None, None) => return None, |
9 | (None, None) => return None, | 7 | (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"), |
10 | (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"), | 8 | (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat), |
11 | (Some(record_pat), _) => ( | 9 | (_, Some(record_lit)) => ctx.sema.record_literal_missing_fields(record_lit), |
12 | ctx.sema.type_of_pat(&record_pat.clone().into())?, | 10 | }; |
13 | ctx.sema.resolve_record_pattern(record_pat)?, | ||
14 | pattern_ascribed_fields(record_pat), | ||
15 | ), | ||
16 | (_, Some(record_lit)) => ( | ||
17 | ctx.sema.type_of_expr(&record_lit.clone().into())?, | ||
18 | ctx.sema.resolve_record_literal(record_lit)?, | ||
19 | literal_ascribed_fields(record_lit), | ||
20 | ), | ||
21 | }; | ||
22 | 11 | ||
23 | for (field, field_ty) in ty.variant_fields(ctx.db, variant).into_iter().filter(|(field, _)| { | 12 | for (field, ty) in missing_fields { |
24 | // FIXME: already_present_names better be `Vec<hir::Name>` | 13 | acc.add_field(ctx, field, &ty) |
25 | !already_present_fields.contains(&SmolStr::from(field.name(ctx.db).to_string())) | ||
26 | }) { | ||
27 | acc.add_field(ctx, field, &field_ty); | ||
28 | } | 14 | } |
29 | Some(()) | ||
30 | } | ||
31 | |||
32 | fn literal_ascribed_fields(record_lit: &ast::RecordLit) -> Vec<SmolStr> { | ||
33 | record_lit | ||
34 | .record_field_list() | ||
35 | .map(|field_list| field_list.fields()) | ||
36 | .map(|fields| { | ||
37 | fields | ||
38 | .into_iter() | ||
39 | .filter_map(|field| field.name_ref()) | ||
40 | .map(|name_ref| name_ref.text().clone()) | ||
41 | .collect() | ||
42 | }) | ||
43 | .unwrap_or_default() | ||
44 | } | ||
45 | 15 | ||
46 | fn pattern_ascribed_fields(record_pat: &ast::RecordPat) -> Vec<SmolStr> { | 16 | Some(()) |
47 | record_pat | ||
48 | .record_field_pat_list() | ||
49 | .map(|pat_list| { | ||
50 | pat_list | ||
51 | .record_field_pats() | ||
52 | .filter_map(|fild_pat| fild_pat.name()) | ||
53 | .chain(pat_list.bind_pats().filter_map(|bind_pat| bind_pat.name())) | ||
54 | .map(|name| name.text().clone()) | ||
55 | .collect() | ||
56 | }) | ||
57 | .unwrap_or_default() | ||
58 | } | 17 | } |
59 | 18 | ||
60 | #[cfg(test)] | 19 | #[cfg(test)] |
61 | mod tests { | 20 | mod tests { |
62 | mod record_lit_tests { | 21 | mod record_pat_tests { |
63 | use insta::assert_debug_snapshot; | 22 | use insta::assert_debug_snapshot; |
64 | 23 | ||
65 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | 24 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
@@ -205,7 +164,7 @@ mod tests { | |||
205 | } | 164 | } |
206 | } | 165 | } |
207 | 166 | ||
208 | mod record_pat_tests { | 167 | mod record_lit_tests { |
209 | use insta::assert_debug_snapshot; | 168 | use insta::assert_debug_snapshot; |
210 | 169 | ||
211 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | 170 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
@@ -410,5 +369,38 @@ mod tests { | |||
410 | ] | 369 | ] |
411 | "###); | 370 | "###); |
412 | } | 371 | } |
372 | |||
373 | #[test] | ||
374 | fn completes_functional_update() { | ||
375 | let completions = complete( | ||
376 | r" | ||
377 | struct S { | ||
378 | foo1: u32, | ||
379 | foo2: u32, | ||
380 | } | ||
381 | |||
382 | fn main() { | ||
383 | let foo1 = 1; | ||
384 | let s = S { | ||
385 | foo1, | ||
386 | <|> | ||
387 | .. loop {} | ||
388 | } | ||
389 | } | ||
390 | ", | ||
391 | ); | ||
392 | assert_debug_snapshot!(completions, @r###" | ||
393 | [ | ||
394 | CompletionItem { | ||
395 | label: "foo2", | ||
396 | source_range: [221; 221), | ||
397 | delete: [221; 221), | ||
398 | insert: "foo2", | ||
399 | kind: Field, | ||
400 | detail: "u32", | ||
401 | }, | ||
402 | ] | ||
403 | "###); | ||
404 | } | ||
413 | } | 405 | } |
414 | } | 406 | } |