aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/completion/complete_record.rs59
1 files changed, 9 insertions, 50 deletions
diff --git a/crates/ra_ide/src/completion/complete_record.rs b/crates/ra_ide/src/completion/complete_record.rs
index 2352ced5f..f46bcee5c 100644
--- a/crates/ra_ide/src/completion/complete_record.rs
+++ b/crates/ra_ide/src/completion/complete_record.rs
@@ -1,60 +1,19 @@
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 15
32fn literal_ascribed_fields(record_lit: &ast::RecordLit) -> Vec<SmolStr> { 16 Some(())
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
46fn pattern_ascribed_fields(record_pat: &ast::RecordPat) -> Vec<SmolStr> {
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)]