Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/destructure_tuple_binding.rs')
-rw-r--r--crates/ide-assists/src/handlers/destructure_tuple_binding.rs85
1 files changed, 52 insertions, 33 deletions
diff --git a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
index e2afc0bf13..b8dc59f87d 100644
--- a/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
@@ -8,8 +8,8 @@ use ide_db::{
use itertools::Itertools;
use syntax::{
T,
- ast::{self, AstNode, FieldExpr, HasName, IdentPat, make},
- ted,
+ ast::{self, AstNode, FieldExpr, HasName, IdentPat, syntax_factory::SyntaxFactory},
+ syntax_editor::{Position, SyntaxEditor},
};
use crate::{
@@ -89,13 +89,20 @@ fn destructure_tuple_edit_impl(
data: &TupleData,
in_sub_pattern: bool,
) {
- let assignment_edit = edit_tuple_assignment(ctx, edit, data, in_sub_pattern);
- let current_file_usages_edit = edit_tuple_usages(data, edit, ctx, in_sub_pattern);
+ let mut syntax_editor = edit.make_editor(data.ident_pat.syntax());
+ let syntax_factory = SyntaxFactory::with_mappings();
- assignment_edit.apply();
+ let assignment_edit =
+ edit_tuple_assignment(ctx, edit, &mut syntax_editor, &syntax_factory, data, in_sub_pattern);
+ let current_file_usages_edit = edit_tuple_usages(data, ctx, &syntax_factory, in_sub_pattern);
+
+ assignment_edit.apply(&mut syntax_editor, &syntax_factory);
if let Some(usages_edit) = current_file_usages_edit {
- usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(edit))
+ usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(edit, &mut syntax_editor))
}
+
+ syntax_editor.add_mappings(syntax_factory.finish_with_mappings());
+ edit.add_file_edits(ctx.vfs_file_id(), syntax_editor);
}
fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleData> {
@@ -165,11 +172,11 @@ struct TupleData {
fn edit_tuple_assignment(
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
+ editor: &mut SyntaxEditor,
+ make: &SyntaxFactory,
data: &TupleData,
in_sub_pattern: bool,
) -> AssignmentEdit {
- let ident_pat = edit.make_mut(data.ident_pat.clone());
-
let tuple_pat = {
let original = &data.ident_pat;
let is_ref = original.ref_token().is_some();
@@ -177,10 +184,11 @@ fn edit_tuple_assignment(
let fields = data
.field_names
.iter()
- .map(|name| ast::Pat::from(make::ident_pat(is_ref, is_mut, make::name(name))));
- make::tuple_pat(fields).clone_for_update()
+ .map(|name| ast::Pat::from(make.ident_pat(is_ref, is_mut, make.name(name))));
+ make.tuple_pat(fields)
};
- let is_shorthand_field = ident_pat
+ let is_shorthand_field = data
+ .ident_pat
.name()
.as_ref()
.and_then(ast::RecordPatField::for_field_name)
@@ -189,14 +197,20 @@ fn edit_tuple_assignment(
if let Some(cap) = ctx.config.snippet_cap {
// place cursor on first tuple name
if let Some(ast::Pat::IdentPat(first_pat)) = tuple_pat.fields().next() {
- edit.add_tabstop_before(
- cap,
- first_pat.name().expect("first ident pattern should have a name"),
- )
+ let annotation = edit.make_tabstop_before(cap);
+ editor.add_annotation(
+ first_pat.name().expect("first ident pattern should have a name").syntax(),
+ annotation,
+ );
}
}
- AssignmentEdit { ident_pat, tuple_pat, in_sub_pattern, is_shorthand_field }
+ AssignmentEdit {
+ ident_pat: data.ident_pat.clone(),
+ tuple_pat,
+ in_sub_pattern,
+ is_shorthand_field,
+ }
}
struct AssignmentEdit {
ident_pat: ast::IdentPat,
@@ -206,23 +220,30 @@ struct AssignmentEdit {
}
impl AssignmentEdit {
- fn apply(self) {
+ fn apply(self, syntax_editor: &mut SyntaxEditor, syntax_mapping: &SyntaxFactory) {
// with sub_pattern: keep original tuple and add subpattern: `tup @ (_0, _1)`
if self.in_sub_pattern {
- self.ident_pat.set_pat(Some(self.tuple_pat.into()))
+ self.ident_pat.set_pat_with_editor(
+ Some(self.tuple_pat.into()),
+ syntax_editor,
+ syntax_mapping,
+ )
} else if self.is_shorthand_field {
- ted::insert(ted::Position::after(self.ident_pat.syntax()), self.tuple_pat.syntax());
- ted::insert_raw(ted::Position::after(self.ident_pat.syntax()), make::token(T![:]));
+ syntax_editor.insert(Position::after(self.ident_pat.syntax()), self.tuple_pat.syntax());
+ syntax_editor
+ .insert(Position::after(self.ident_pat.syntax()), syntax_mapping.whitespace(" "));
+ syntax_editor
+ .insert(Position::after(self.ident_pat.syntax()), syntax_mapping.token(T![:]));
} else {
- ted::replace(self.ident_pat.syntax(), self.tuple_pat.syntax())
+ syntax_editor.replace(self.ident_pat.syntax(), self.tuple_pat.syntax())
}
}
}
fn edit_tuple_usages(
data: &TupleData,
- edit: &mut SourceChangeBuilder,
ctx: &AssistContext<'_>,
+ make: &SyntaxFactory,
in_sub_pattern: bool,
) -> Option<Vec<EditTupleUsage>> {
// We need to collect edits first before actually applying them
@@ -238,20 +259,20 @@ fn edit_tuple_usages(
.as_ref()?
.as_slice()
.iter()
- .filter_map(|r| edit_tuple_usage(ctx, edit, r, data, in_sub_pattern))
+ .filter_map(|r| edit_tuple_usage(ctx, make, r, data, in_sub_pattern))
.collect_vec();
Some(edits)
}
fn edit_tuple_usage(
ctx: &AssistContext<'_>,
- builder: &mut SourceChangeBuilder,
+ make: &SyntaxFactory,
usage: &FileReference,
data: &TupleData,
in_sub_pattern: bool,
) -> Option<EditTupleUsage> {
match detect_tuple_index(usage, data) {
- Some(index) => Some(edit_tuple_field_usage(ctx, builder, data, index)),
+ Some(index) => Some(edit_tuple_field_usage(ctx, make, data, index)),
None if in_sub_pattern => {
cov_mark::hit!(destructure_tuple_call_with_subpattern);
None
@@ -262,20 +283,18 @@ fn edit_tuple_usage(
fn edit_tuple_field_usage(
ctx: &AssistContext<'_>,
- builder: &mut SourceChangeBuilder,
+ make: &SyntaxFactory,
data: &TupleData,
index: TupleIndex,
) -> EditTupleUsage {
let field_name = &data.field_names[index.index];
- let field_name = make::expr_path(make::ext::ident_path(field_name));
+ let field_name = make.expr_path(make.ident_path(field_name));
if data.ref_type.is_some() {
let (replace_expr, ref_data) = determine_ref_and_parens(ctx, &index.field_expr);
- let replace_expr = builder.make_mut(replace_expr);
- EditTupleUsage::ReplaceExpr(replace_expr, ref_data.wrap_expr(field_name))
+ EditTupleUsage::ReplaceExpr(replace_expr, ref_data.wrap_expr_with_factory(field_name, make))
} else {
- let field_expr = builder.make_mut(index.field_expr);
- EditTupleUsage::ReplaceExpr(field_expr.into(), field_name)
+ EditTupleUsage::ReplaceExpr(index.field_expr.into(), field_name)
}
}
enum EditTupleUsage {
@@ -291,14 +310,14 @@ enum EditTupleUsage {
}
impl EditTupleUsage {
- fn apply(self, edit: &mut SourceChangeBuilder) {
+ fn apply(self, edit: &mut SourceChangeBuilder, syntax_editor: &mut SyntaxEditor) {
match self {
EditTupleUsage::NoIndex(range) => {
edit.insert(range.start(), "/*");
edit.insert(range.end(), "*/");
}
EditTupleUsage::ReplaceExpr(target_expr, replace_with) => {
- ted::replace(target_expr.syntax(), replace_with.clone_for_update().syntax())
+ syntax_editor.replace(target_expr.syntax(), replace_with.syntax())
}
}
}