]> git.lizzy.rs Git - rust.git/commitdiff
Split draft
authorKirill Bulatov <mail4score@gmail.com>
Tue, 31 Mar 2020 20:39:46 +0000 (23:39 +0300)
committerKirill Bulatov <mail4score@gmail.com>
Wed, 1 Apr 2020 09:49:31 +0000 (12:49 +0300)
crates/ra_ide/src/completion.rs
crates/ra_ide/src/completion/complete_record_literal.rs
crates/ra_ide/src/completion/complete_record_pattern.rs

index b683572fbf893c02568ff23b5000cdb0a8005e1d..67dfd6f2e6ab07ad14296cbc20e4d7f5c7f1665e 100644 (file)
 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<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(),
+    }
+}
index e4e764f58242c79dfdc4f3527790d83c48cbc21c..8b67d3ba2ab203d6c25b957675d4bde0989faed3 100644 (file)
@@ -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<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)]
index 78315eeb8663c0c94758663ed463e2a57a68ac41..f94dced045abc4e8ca67363909cedfceb04bf51b 100644 (file)
@@ -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<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)]
@@ -151,7 +134,7 @@ fn main() {
                     bar: 3,
                     baz: 4,
                 };
-                if let S { foo1, foo2, <|> } = s {}
+                if let S { foo1, foo2: a, <|> } = s {}
             }
             ",
         );
@@ -159,16 +142,16 @@ fn main() {
         [
             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",