Skip to content

Commit d35b943

Browse files
Split draft
1 parent bc71631 commit d35b943

File tree

3 files changed

+85
-59
lines changed

3 files changed

+85
-59
lines changed

crates/ra_ide/src/completion.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ use crate::{
3232
pub use crate::completion::completion_item::{
3333
CompletionItem, CompletionItemKind, InsertTextFormat,
3434
};
35+
use either::Either;
36+
use hir::{StructField, Type};
37+
use ra_syntax::{
38+
ast::{self, NameOwner},
39+
SmolStr,
40+
};
3541

3642
#[derive(Clone, Debug, PartialEq, Eq)]
3743
pub struct CompletionConfig {
@@ -98,3 +104,57 @@ pub(crate) fn completions(
98104

99105
Some(acc)
100106
}
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+
}

crates/ra_ide/src/completion/complete_record_literal.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,19 @@
11
//! FIXME: write short doc here
22
3+
use super::get_missing_fields;
34
use crate::completion::{CompletionContext, Completions};
4-
use ra_syntax::SmolStr;
5+
use either::Either;
56

67
/// Complete fields in fields literals.
7-
pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
8-
let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
9-
Some((ctx.sema.type_of_expr(&it.clone().into())?, ctx.sema.resolve_record_literal(it)?))
10-
}) {
11-
Some(it) => it,
12-
_ => return,
13-
};
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-
}
8+
pub(super) fn complete_record_literal(
9+
acc: &mut Completions,
10+
ctx: &CompletionContext,
11+
) -> Option<()> {
12+
let record_lit = ctx.record_lit_syntax.as_ref()?;
13+
for (field, field_ty) in get_missing_fields(ctx, Either::Left(record_lit))? {
14+
acc.add_field(ctx, field, &field_ty);
3315
}
16+
Some(())
3417
}
3518

3619
#[cfg(test)]

crates/ra_ide/src/completion/complete_record_pattern.rs

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,18 @@
11
//! FIXME: write short doc here
22
3+
use super::get_missing_fields;
34
use crate::completion::{CompletionContext, Completions};
4-
use ra_syntax::{ast::NameOwner, SmolStr};
5+
use either::Either;
56

6-
pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) {
7-
let (ty, variant) = match ctx.record_lit_pat.as_ref().and_then(|it| {
8-
Some((ctx.sema.type_of_pat(&it.clone().into())?, ctx.sema.resolve_record_pattern(it)?))
9-
}) {
10-
Some(it) => it,
11-
_ => return,
12-
};
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-
}
7+
pub(super) fn complete_record_pattern(
8+
acc: &mut Completions,
9+
ctx: &CompletionContext,
10+
) -> Option<()> {
11+
let record_pat = ctx.record_lit_pat.as_ref()?;
12+
for (field, field_ty) in get_missing_fields(ctx, Either::Right(record_pat))? {
13+
acc.add_field(ctx, field, &field_ty);
3214
}
15+
Some(())
3316
}
3417

3518
#[cfg(test)]
@@ -151,24 +134,24 @@ mod tests {
151134
bar: 3,
152135
baz: 4,
153136
};
154-
if let S { foo1, foo2, <|> } = s {}
137+
if let S { foo1, foo2: a, <|> } = s {}
155138
}
156139
",
157140
);
158141
assert_debug_snapshot!(completions, @r###"
159142
[
160143
CompletionItem {
161144
label: "bar",
162-
source_range: [369; 369),
163-
delete: [369; 369),
145+
source_range: [372; 372),
146+
delete: [372; 372),
164147
insert: "bar",
165148
kind: Field,
166149
detail: "u32",
167150
},
168151
CompletionItem {
169152
label: "baz",
170-
source_range: [369; 369),
171-
delete: [369; 369),
153+
source_range: [372; 372),
154+
delete: [372; 372),
172155
insert: "baz",
173156
kind: Field,
174157
detail: "u32",

0 commit comments

Comments
 (0)