pub use crate::completion::completion_item::{
CompletionItem, CompletionItemKind, InsertTextFormat,
};
+use either::Either;
+use hir::{StructField, Type};
+use ra_syntax::{
+ ast::{self, NameOwner},
+ SmolStr,
+};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionConfig {
Some(acc)
}
+
+pub(crate) fn get_missing_fields(
+ ctx: &CompletionContext,
+ record: Either<&ast::RecordLit, &ast::RecordPat>,
+) -> Option<Vec<(StructField, Type)>> {
+ let (ty, variant) = match record {
+ Either::Left(record_lit) => (
+ ctx.sema.type_of_expr(&record_lit.clone().into())?,
+ ctx.sema.resolve_record_literal(record_lit)?,
+ ),
+ Either::Right(record_pat) => (
+ ctx.sema.type_of_pat(&record_pat.clone().into())?,
+ ctx.sema.resolve_record_pattern(record_pat)?,
+ ),
+ };
+
+ let already_present_names = get_already_present_names(record);
+ Some(
+ ty.variant_fields(ctx.db, variant)
+ .into_iter()
+ .filter(|(field, _)| {
+ !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string()))
+ })
+ .collect(),
+ )
+}
+
+fn get_already_present_names(record: Either<&ast::RecordLit, &ast::RecordPat>) -> Vec<SmolStr> {
+ // TODO kb have a single match
+ match record {
+ Either::Left(record_lit) => record_lit
+ .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(),
+ Either::Right(record_pat) => record_pat
+ .record_field_pat_list()
+ .map(|pat_list| pat_list.bind_pats())
+ .map(|bind_pats| {
+ bind_pats
+ .into_iter()
+ .filter_map(|pat| pat.name())
+ .map(|name| name.text().clone())
+ .collect()
+ })
+ .unwrap_or_default(),
+ }
+}
//! FIXME: write short doc here
+use super::get_missing_fields;
use crate::completion::{CompletionContext, Completions};
-use ra_syntax::SmolStr;
+use either::Either;
/// Complete fields in fields literals.
-pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
- let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
- Some((ctx.sema.type_of_expr(&it.clone().into())?, ctx.sema.resolve_record_literal(it)?))
- }) {
- Some(it) => it,
- _ => return,
- };
-
- let already_present_names: Vec<SmolStr> = 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) {
- if !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string())) {
- acc.add_field(ctx, field, &field_ty);
- }
+pub(super) fn complete_record_literal(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+) -> Option<()> {
+ let record_lit = ctx.record_lit_syntax.as_ref()?;
+ for (field, field_ty) in get_missing_fields(ctx, Either::Left(record_lit))? {
+ acc.add_field(ctx, field, &field_ty);
}
+ Some(())
}
#[cfg(test)]
//! FIXME: write short doc here
+use super::get_missing_fields;
use crate::completion::{CompletionContext, Completions};
-use ra_syntax::{ast::NameOwner, SmolStr};
+use either::Either;
-pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) {
- let (ty, variant) = match ctx.record_lit_pat.as_ref().and_then(|it| {
- Some((ctx.sema.type_of_pat(&it.clone().into())?, ctx.sema.resolve_record_pattern(it)?))
- }) {
- Some(it) => it,
- _ => return,
- };
-
- let already_present_names: Vec<SmolStr> = ctx
- .record_lit_pat
- .as_ref()
- .and_then(|record_pat| record_pat.record_field_pat_list())
- .map(|pat_list| pat_list.bind_pats())
- .map(|bind_pats| {
- bind_pats
- .into_iter()
- .filter_map(|pat| pat.name())
- .map(|name| name.text().clone())
- .collect()
- })
- .unwrap_or_default();
-
- for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
- if !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string())) {
- acc.add_field(ctx, field, &field_ty);
- }
+pub(super) fn complete_record_pattern(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+) -> Option<()> {
+ let record_pat = ctx.record_lit_pat.as_ref()?;
+ for (field, field_ty) in get_missing_fields(ctx, Either::Right(record_pat))? {
+ acc.add_field(ctx, field, &field_ty);
}
+ Some(())
}
#[cfg(test)]
bar: 3,
baz: 4,
};
- if let S { foo1, foo2, <|> } = s {}
+ if let S { foo1, foo2: a, <|> } = s {}
}
",
);
[
CompletionItem {
label: "bar",
- source_range: [369; 369),
- delete: [369; 369),
+ source_range: [372; 372),
+ delete: [372; 372),
insert: "bar",
kind: Field,
detail: "u32",
},
CompletionItem {
label: "baz",
- source_range: [369; 369),
- delete: [369; 369),
+ source_range: [372; 372),
+ delete: [372; 372),
insert: "baz",
kind: Field,
detail: "u32",