aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
authorBenjamin Coenen <[email protected]>2020-04-09 08:39:17 +0100
committerBenjamin Coenen <[email protected]>2020-04-09 08:53:53 +0100
commit585bb83e2aec9c79dae8c2e031e9165f40937003 (patch)
tree3dda062f3deb768b211e7e091dd5b29b9b6fae84 /crates/ra_ide/src/completion
parent8f1dba6f9ae1d8d314dd9d007e4c582ed1403e8d (diff)
parent080c983498afcac3eb54028af5c9f8bfe7f2c826 (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.rs96
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.
2use ra_syntax::{ast, ast::NameOwner, SmolStr};
3
4use crate::completion::{CompletionContext, Completions}; 2use crate::completion::{CompletionContext, Completions};
5 3
6pub(super) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 4pub(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
32fn 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
46fn 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)]
61mod tests { 20mod 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}