aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion.rs')
-rw-r--r--crates/ra_ide/src/completion.rs60
1 files changed, 60 insertions, 0 deletions
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::{
32pub use crate::completion::completion_item::{ 32pub use crate::completion::completion_item::{
33 CompletionItem, CompletionItemKind, InsertTextFormat, 33 CompletionItem, CompletionItemKind, InsertTextFormat,
34}; 34};
35use either::Either;
36use hir::{StructField, Type};
37use ra_syntax::{
38 ast::{self, NameOwner},
39 SmolStr,
40};
35 41
36#[derive(Clone, Debug, PartialEq, Eq)] 42#[derive(Clone, Debug, PartialEq, Eq)]
37pub struct CompletionConfig { 43pub struct CompletionConfig {
@@ -98,3 +104,57 @@ pub(crate) fn completions(
98 104
99 Some(acc) 105 Some(acc)
100} 106}
107
108pub(crate) fn get_missing_fields(
109 ctx: &CompletionContext,
110 record: Either<&ast::RecordLit, &ast::RecordPat>,
111) -> Option<Vec<(StructField, Type)>> {
112 let (ty, variant) = match record {
113 Either::Left(record_lit) => (
114 ctx.sema.type_of_expr(&record_lit.clone().into())?,
115 ctx.sema.resolve_record_literal(record_lit)?,
116 ),
117 Either::Right(record_pat) => (
118 ctx.sema.type_of_pat(&record_pat.clone().into())?,
119 ctx.sema.resolve_record_pattern(record_pat)?,
120 ),
121 };
122
123 let already_present_names = get_already_present_names(record);
124 Some(
125 ty.variant_fields(ctx.db, variant)
126 .into_iter()
127 .filter(|(field, _)| {
128 !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string()))
129 })
130 .collect(),
131 )
132}
133
134fn get_already_present_names(record: Either<&ast::RecordLit, &ast::RecordPat>) -> Vec<SmolStr> {
135 // TODO kb have a single match
136 match record {
137 Either::Left(record_lit) => record_lit
138 .record_field_list()
139 .map(|field_list| field_list.fields())
140 .map(|fields| {
141 fields
142 .into_iter()
143 .filter_map(|field| field.name_ref())
144 .map(|name_ref| name_ref.text().clone())
145 .collect()
146 })
147 .unwrap_or_default(),
148 Either::Right(record_pat) => record_pat
149 .record_field_pat_list()
150 .map(|pat_list| pat_list.bind_pats())
151 .map(|bind_pats| {
152 bind_pats
153 .into_iter()
154 .filter_map(|pat| pat.name())
155 .map(|name| name.text().clone())
156 .collect()
157 })
158 .unwrap_or_default(),
159 }
160}