aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/completion.rs60
-rw-r--r--crates/ra_ide/src/completion/complete_record_literal.rs37
-rw-r--r--crates/ra_ide/src/completion/complete_record_pattern.rs47
3 files changed, 85 insertions, 59 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}
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 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use super::get_missing_fields;
3use crate::completion::{CompletionContext, Completions}; 4use crate::completion::{CompletionContext, Completions};
4use ra_syntax::SmolStr; 5use either::Either;
5 6
6/// Complete fields in fields literals. 7/// Complete fields in fields literals.
7pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) { 8pub(super) fn complete_record_literal(
8 let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| { 9 acc: &mut Completions,
9 Some((ctx.sema.type_of_expr(&it.clone().into())?, ctx.sema.resolve_record_literal(it)?)) 10 ctx: &CompletionContext,
10 }) { 11) -> Option<()> {
11 Some(it) => it, 12 let record_lit = ctx.record_lit_syntax.as_ref()?;
12 _ => return, 13 for (field, field_ty) in get_missing_fields(ctx, Either::Left(record_lit))? {
13 }; 14 acc.add_field(ctx, field, &field_ty);
14
15 let already_present_names: Vec<SmolStr> = ctx
16 .record_lit_syntax
17 .as_ref()
18 .and_then(|record_literal| record_literal.record_field_list())
19 .map(|field_list| field_list.fields())
20 .map(|fields| {
21 fields
22 .into_iter()
23 .filter_map(|field| field.name_ref())
24 .map(|name_ref| name_ref.text().clone())
25 .collect()
26 })
27 .unwrap_or_default();
28
29 for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
30 if !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string())) {
31 acc.add_field(ctx, field, &field_ty);
32 }
33 } 15 }
16 Some(())
34} 17}
35 18
36#[cfg(test)] 19#[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 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use super::get_missing_fields;
3use crate::completion::{CompletionContext, Completions}; 4use crate::completion::{CompletionContext, Completions};
4use ra_syntax::{ast::NameOwner, SmolStr}; 5use either::Either;
5 6
6pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) { 7pub(super) fn complete_record_pattern(
7 let (ty, variant) = match ctx.record_lit_pat.as_ref().and_then(|it| { 8 acc: &mut Completions,
8 Some((ctx.sema.type_of_pat(&it.clone().into())?, ctx.sema.resolve_record_pattern(it)?)) 9 ctx: &CompletionContext,
9 }) { 10) -> Option<()> {
10 Some(it) => it, 11 let record_pat = ctx.record_lit_pat.as_ref()?;
11 _ => return, 12 for (field, field_ty) in get_missing_fields(ctx, Either::Right(record_pat))? {
12 }; 13 acc.add_field(ctx, field, &field_ty);
13
14 let already_present_names: Vec<SmolStr> = ctx
15 .record_lit_pat
16 .as_ref()
17 .and_then(|record_pat| record_pat.record_field_pat_list())
18 .map(|pat_list| pat_list.bind_pats())
19 .map(|bind_pats| {
20 bind_pats
21 .into_iter()
22 .filter_map(|pat| pat.name())
23 .map(|name| name.text().clone())
24 .collect()
25 })
26 .unwrap_or_default();
27
28 for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
29 if !already_present_names.contains(&SmolStr::from(field.name(ctx.db).to_string())) {
30 acc.add_field(ctx, field, &field_ty);
31 }
32 } 14 }
15 Some(())
33} 16}
34 17
35#[cfg(test)] 18#[cfg(test)]
@@ -151,7 +134,7 @@ mod tests {
151 bar: 3, 134 bar: 3,
152 baz: 4, 135 baz: 4,
153 }; 136 };
154 if let S { foo1, foo2, <|> } = s {} 137 if let S { foo1, foo2: a, <|> } = s {}
155 } 138 }
156 ", 139 ",
157 ); 140 );
@@ -159,16 +142,16 @@ mod tests {
159 [ 142 [
160 CompletionItem { 143 CompletionItem {
161 label: "bar", 144 label: "bar",
162 source_range: [369; 369), 145 source_range: [372; 372),
163 delete: [369; 369), 146 delete: [372; 372),
164 insert: "bar", 147 insert: "bar",
165 kind: Field, 148 kind: Field,
166 detail: "u32", 149 detail: "u32",
167 }, 150 },
168 CompletionItem { 151 CompletionItem {
169 label: "baz", 152 label: "baz",
170 source_range: [369; 369), 153 source_range: [372; 372),
171 delete: [369; 369), 154 delete: [372; 372),
172 insert: "baz", 155 insert: "baz",
173 kind: Field, 156 kind: Field,
174 detail: "u32", 157 detail: "u32",