diff --git a/crates/ra_ide/src/completion/complete_record_literal.rs b/crates/ra_ide/src/completion/complete_record_literal.rs index 83ed1d52c7..e4e764f582 100644 --- a/crates/ra_ide/src/completion/complete_record_literal.rs +++ b/crates/ra_ide/src/completion/complete_record_literal.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here use crate::completion::{CompletionContext, Completions}; +use ra_syntax::SmolStr; /// Complete fields in fields literals. pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) { @@ -11,8 +12,24 @@ pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionCon _ => return, }; + let already_present_names: Vec = ctx + .record_lit_syntax + .as_ref() + .and_then(|record_literal| record_literal.record_field_list()) + .map(|field_list| field_list.fields()) + .map(|fields| { + fields + .into_iter() + .filter_map(|field| field.name_ref()) + .map(|name_ref| name_ref.text().clone()) + .collect() + }) + .unwrap_or_default(); + for (field, field_ty) in ty.variant_fields(ctx.db, variant) { - acc.add_field(ctx, field, &field_ty); + if !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string())) { + acc.add_field(ctx, field, &field_ty); + } } } @@ -178,4 +195,47 @@ mod tests { ] "###); } + + #[test] + fn only_missing_fields_are_completed() { + let completions = complete( + r" + struct S { + foo1: u32, + foo2: u32, + bar: u32, + baz: u32, + } + + fn main() { + let foo1 = 1; + let s = S { + foo1, + foo2: 5, + <|> + } + } + ", + ); + assert_debug_snapshot!(completions, @r###" + [ + CompletionItem { + label: "bar", + source_range: [302; 302), + delete: [302; 302), + insert: "bar", + kind: Field, + detail: "u32", + }, + CompletionItem { + label: "baz", + source_range: [302; 302), + delete: [302; 302), + insert: "baz", + kind: Field, + detail: "u32", + }, + ] + "###); + } }