From d35b94352090c201f7e0cceae43035ee0e72df98 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 31 Mar 2020 23:39:46 +0300 Subject: Split draft --- crates/ra_ide/src/completion.rs | 60 ++++++++++++++++++++++ .../src/completion/complete_record_literal.rs | 37 ++++--------- .../src/completion/complete_record_pattern.rs | 47 ++++++----------- 3 files changed, 85 insertions(+), 59 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index b683572fb..67dfd6f2e 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -32,6 +32,12 @@ use crate::{ 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 { @@ -98,3 +104,57 @@ pub(crate) fn completions( Some(acc) } + +pub(crate) fn get_missing_fields( + ctx: &CompletionContext, + record: Either<&ast::RecordLit, &ast::RecordPat>, +) -> Option> { + 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 { + // 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(), + } +} diff --git a/crates/ra_ide/src/completion/complete_record_literal.rs b/crates/ra_ide/src/completion/complete_record_literal.rs index e4e764f58..8b67d3ba2 100644 --- a/crates/ra_ide/src/completion/complete_record_literal.rs +++ b/crates/ra_ide/src/completion/complete_record_literal.rs @@ -1,36 +1,19 @@ //! 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 = 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)] diff --git a/crates/ra_ide/src/completion/complete_record_pattern.rs b/crates/ra_ide/src/completion/complete_record_pattern.rs index 78315eeb8..f94dced04 100644 --- a/crates/ra_ide/src/completion/complete_record_pattern.rs +++ b/crates/ra_ide/src/completion/complete_record_pattern.rs @@ -1,35 +1,18 @@ //! 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 = 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)] @@ -151,7 +134,7 @@ mod tests { bar: 3, baz: 4, }; - if let S { foo1, foo2, <|> } = s {} + if let S { foo1, foo2: a, <|> } = s {} } ", ); @@ -159,16 +142,16 @@ mod tests { [ 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", -- cgit v1.2.3