Skip to content

Commit aded72f

Browse files
authored
Merge pull request #19572 from snprajwal/expand-rest-pattern
refactor: migrate `expand_rest_pattern` to editor
2 parents 6c589ef + c7e5e33 commit aded72f

File tree

1 file changed

+66
-53
lines changed

1 file changed

+66
-53
lines changed

crates/ide-assists/src/handlers/expand_rest_pattern.rs

+66-53
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,12 @@ use hir::{PathResolution, StructKind};
22
use ide_db::syntax_helpers::suggest_name::NameGenerator;
33
use syntax::{
44
AstNode, ToSmolStr,
5-
ast::{self, make},
5+
ast::{self, syntax_factory::SyntaxFactory},
66
match_ast,
77
};
88

99
use crate::{AssistContext, AssistId, Assists};
1010

11-
pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
12-
let rest_pat = ctx.find_node_at_offset::<ast::RestPat>()?;
13-
let parent = rest_pat.syntax().parent()?;
14-
match_ast! {
15-
match parent {
16-
ast::RecordPatFieldList(it) => expand_record_rest_pattern(acc, ctx, it.syntax().parent().and_then(ast::RecordPat::cast)?, rest_pat),
17-
ast::TupleStructPat(it) => expand_tuple_struct_rest_pattern(acc, ctx, it, rest_pat),
18-
// FIXME
19-
// ast::TuplePat(it) => (),
20-
// FIXME
21-
// ast::SlicePat(it) => (),
22-
_ => return None,
23-
}
24-
}
25-
}
26-
2711
// Assist: expand_record_rest_pattern
2812
//
2913
// Fills fields by replacing rest pattern in record patterns.
@@ -50,7 +34,6 @@ fn expand_record_rest_pattern(
5034
rest_pat: ast::RestPat,
5135
) -> Option<()> {
5236
let missing_fields = ctx.sema.record_pattern_missing_fields(&record_pat);
53-
5437
if missing_fields.is_empty() {
5538
cov_mark::hit!(no_missing_fields);
5639
return None;
@@ -62,24 +45,30 @@ fn expand_record_rest_pattern(
6245
return None;
6346
}
6447

65-
let new_field_list =
66-
make::record_pat_field_list(old_field_list.fields(), None).clone_for_update();
67-
for (f, _) in missing_fields.iter() {
68-
let edition = ctx.sema.scope(record_pat.syntax())?.krate().edition(ctx.db());
69-
let field = make::record_pat_field_shorthand(make::name_ref(
70-
&f.name(ctx.sema.db).display_no_db(edition).to_smolstr(),
71-
));
72-
new_field_list.add_field(field.clone_for_update());
73-
}
74-
75-
let target_range = rest_pat.syntax().text_range();
48+
let edition = ctx.sema.scope(record_pat.syntax())?.krate().edition(ctx.db());
7649
acc.add(
7750
AssistId::refactor_rewrite("expand_record_rest_pattern"),
7851
"Fill struct fields",
79-
target_range,
80-
move |builder| builder.replace_ast(old_field_list, new_field_list),
52+
rest_pat.syntax().text_range(),
53+
|builder| {
54+
let make = SyntaxFactory::with_mappings();
55+
let mut editor = builder.make_editor(rest_pat.syntax());
56+
let new_field_list = make.record_pat_field_list(old_field_list.fields(), None);
57+
for (f, _) in missing_fields.iter() {
58+
let field = make.record_pat_field_shorthand(
59+
make.name_ref(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()),
60+
);
61+
new_field_list.add_field(field);
62+
}
63+
64+
editor.replace(old_field_list.syntax(), new_field_list.syntax());
65+
66+
editor.add_mappings(make.finish_with_mappings());
67+
builder.add_file_edits(ctx.file_id(), editor);
68+
},
8169
)
8270
}
71+
8372
// Assist: expand_tuple_struct_rest_pattern
8473
//
8574
// Fills fields by replacing rest pattern in tuple struct patterns.
@@ -134,34 +123,58 @@ fn expand_tuple_struct_rest_pattern(
134123
return None;
135124
}
136125

137-
let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax()));
138-
let new_pat = make::tuple_struct_pat(
139-
path,
140-
pat.fields()
141-
.take(prefix_count)
142-
.chain(fields[prefix_count..fields.len() - suffix_count].iter().map(|f| {
143-
make::ident_pat(
144-
false,
145-
false,
146-
match name_gen.for_type(&f.ty(ctx.sema.db), ctx.sema.db, ctx.edition()) {
147-
Some(name) => make::name(&name),
148-
None => make::name(&format!("_{}", f.index())),
149-
},
150-
)
151-
.into()
152-
}))
153-
.chain(pat.fields().skip(prefix_count + 1)),
154-
);
155-
156-
let target_range = rest_pat.syntax().text_range();
157126
acc.add(
158127
AssistId::refactor_rewrite("expand_tuple_struct_rest_pattern"),
159128
"Fill tuple struct fields",
160-
target_range,
161-
move |builder| builder.replace_ast(pat, new_pat),
129+
rest_pat.syntax().text_range(),
130+
|builder| {
131+
let make = SyntaxFactory::with_mappings();
132+
let mut editor = builder.make_editor(rest_pat.syntax());
133+
134+
let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax()));
135+
let new_pat = make.tuple_struct_pat(
136+
path,
137+
pat.fields()
138+
.take(prefix_count)
139+
.chain(fields[prefix_count..fields.len() - suffix_count].iter().map(|f| {
140+
make.ident_pat(
141+
false,
142+
false,
143+
match name_gen.for_type(&f.ty(ctx.sema.db), ctx.sema.db, ctx.edition())
144+
{
145+
Some(name) => make.name(&name),
146+
None => make.name(&format!("_{}", f.index())),
147+
},
148+
)
149+
.into()
150+
}))
151+
.chain(pat.fields().skip(prefix_count + 1)),
152+
);
153+
154+
editor.replace(pat.syntax(), new_pat.syntax());
155+
156+
editor.add_mappings(make.finish_with_mappings());
157+
builder.add_file_edits(ctx.file_id(), editor);
158+
},
162159
)
163160
}
164161

162+
pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
163+
let rest_pat = ctx.find_node_at_offset::<ast::RestPat>()?;
164+
let parent = rest_pat.syntax().parent()?;
165+
match_ast! {
166+
match parent {
167+
ast::RecordPatFieldList(it) => expand_record_rest_pattern(acc, ctx, it.syntax().parent().and_then(ast::RecordPat::cast)?, rest_pat),
168+
ast::TupleStructPat(it) => expand_tuple_struct_rest_pattern(acc, ctx, it, rest_pat),
169+
// FIXME
170+
// ast::TuplePat(it) => (),
171+
// FIXME
172+
// ast::SlicePat(it) => (),
173+
_ => return None,
174+
}
175+
}
176+
}
177+
165178
#[cfg(test)]
166179
mod tests {
167180
use super::*;

0 commit comments

Comments
 (0)