diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide/src/completion.rs | 60 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_record_literal.rs | 37 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_record_pattern.rs | 47 |
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::{ | |||
32 | pub use crate::completion::completion_item::{ | 32 | pub use crate::completion::completion_item::{ |
33 | CompletionItem, CompletionItemKind, InsertTextFormat, | 33 | CompletionItem, CompletionItemKind, InsertTextFormat, |
34 | }; | 34 | }; |
35 | use either::Either; | ||
36 | use hir::{StructField, Type}; | ||
37 | use ra_syntax::{ | ||
38 | ast::{self, NameOwner}, | ||
39 | SmolStr, | ||
40 | }; | ||
35 | 41 | ||
36 | #[derive(Clone, Debug, PartialEq, Eq)] | 42 | #[derive(Clone, Debug, PartialEq, Eq)] |
37 | pub struct CompletionConfig { | 43 | pub struct CompletionConfig { |
@@ -98,3 +104,57 @@ pub(crate) fn completions( | |||
98 | 104 | ||
99 | Some(acc) | 105 | Some(acc) |
100 | } | 106 | } |
107 | |||
108 | pub(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 | |||
134 | fn 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 | ||
3 | use super::get_missing_fields; | ||
3 | use crate::completion::{CompletionContext, Completions}; | 4 | use crate::completion::{CompletionContext, Completions}; |
4 | use ra_syntax::SmolStr; | 5 | use either::Either; |
5 | 6 | ||
6 | /// Complete fields in fields literals. | 7 | /// Complete fields in fields literals. |
7 | pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) { | 8 | pub(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 | ||
3 | use super::get_missing_fields; | ||
3 | use crate::completion::{CompletionContext, Completions}; | 4 | use crate::completion::{CompletionContext, Completions}; |
4 | use ra_syntax::{ast::NameOwner, SmolStr}; | 5 | use either::Either; |
5 | 6 | ||
6 | pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) { | 7 | pub(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", |