Merge pull request #22049 from Shourya742/2026-04-15-move-syntax-factory-inside-syntax-editor

Move syntax factory inside syntax editor
This commit is contained in:
Chayim Refael Friedman
2026-04-15 19:09:18 +00:00
committed by GitHub
95 changed files with 908 additions and 1141 deletions
@@ -22,7 +22,7 @@
use syntax::{
ast::{
self, AstNode, FieldList, HasAttrs, HasGenericArgs, HasGenericParams, HasModuleItem,
HasName, HasTypeBounds, make, syntax_factory::SyntaxFactory,
HasName, HasTypeBounds, make,
},
syntax_editor::{GetOrCreateWhereClause, SyntaxEditor},
ted,
@@ -1294,10 +1294,8 @@ fn coerce_pointee_expand(
));
}
let (mut editor, strukt) = SyntaxEditor::with_ast_node(strukt);
let make = SyntaxFactory::with_mappings();
strukt.get_or_create_where_clause(&mut editor, &make, new_predicates.into_iter());
editor.add_mappings(make.finish_with_mappings());
let (editor, strukt) = SyntaxEditor::with_ast_node(strukt);
strukt.get_or_create_where_clause(&editor, new_predicates.into_iter());
let edit = editor.finish();
let strukt = ast::Struct::cast(edit.new_root().clone()).unwrap();
let adt = ast::Adt::Struct(strukt.clone());
@@ -1,7 +1,7 @@
use either::Either;
use syntax::{
AstNode, T,
ast::{self, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
ast::{self, edit::AstNodeEdit},
match_ast,
};
@@ -56,15 +56,13 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
},
expr.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(expr.syntax());
let editor = builder.make_editor(expr.syntax());
let make = editor.make();
let new_expr = expr.reset_indent().indent(1.into());
let block_expr = make.block_expr(None, Some(new_expr));
editor.replace(expr.syntax(), block_expr.indent(expr.indent_level()).syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -53,18 +53,18 @@ pub(crate) fn add_explicit_method_call_deref(
"Insert explicit method call derefs",
dot_token.text_range(),
|builder| {
let mut edit = builder.make_editor(method_call_expr.syntax());
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(method_call_expr.syntax());
let make = editor.make();
let mut expr = receiver.clone();
for adjust_kind in adjustments {
expr = adjust_kind.wrap_expr(expr, &make);
expr = adjust_kind.wrap_expr(expr, make);
}
expr = make.expr_paren(expr).into();
edit.replace(receiver.syntax(), expr.syntax());
editor.replace(receiver.syntax(), expr.syntax());
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -3,7 +3,7 @@
};
use syntax::{
SyntaxToken, T,
ast::{self, AstNode, HasLoopBody, syntax_factory::SyntaxFactory},
ast::{self, AstNode, HasLoopBody},
syntax_editor::{Position, SyntaxEditor},
};
@@ -42,8 +42,8 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
"Add Label",
loop_expr.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(loop_expr.syntax());
let editor = builder.make_editor(loop_expr.syntax());
let make = editor.make();
let label = make.lifetime("'l");
let elements = vec![
@@ -65,11 +65,10 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
_ => return,
};
if let Some(token) = token {
insert_label_after_token(&mut editor, &make, &token, ctx, builder);
insert_label_after_token(&editor, &token, ctx, builder);
}
});
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
builder.rename();
},
@@ -85,12 +84,12 @@ fn loop_token(loop_expr: &ast::AnyHasLoopBody) -> Option<syntax::SyntaxToken> {
}
fn insert_label_after_token(
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
token: &SyntaxToken,
ctx: &AssistContext<'_>,
builder: &mut SourceChangeBuilder,
) {
let make = editor.make();
let label = make.lifetime("'l");
let elements = vec![make.whitespace(" ").into(), label.syntax().clone().into()];
editor.insert_all(Position::after(token), elements);
@@ -148,9 +148,10 @@ fn add_missing_impl_members_inner(
let target = impl_def.syntax().text_range();
acc.add(AssistId::quick_fix(assist_id), label, target, |edit| {
let make = SyntaxFactory::with_mappings();
let editor = edit.make_editor(impl_def.syntax());
let make = editor.make();
let new_item = add_trait_assoc_items_to_impl(
&make,
make,
&ctx.sema,
ctx.config,
&missing_items,
@@ -166,7 +167,7 @@ fn add_missing_impl_members_inner(
let mut first_new_item = if let DefaultMethods::No = mode
&& let ast::AssocItem::Fn(func) = &first_new_item
&& let Some(body) = try_gen_trait_body(
&make,
make,
ctx,
func,
trait_ref,
@@ -175,7 +176,7 @@ fn add_missing_impl_members_inner(
)
&& let Some(func_body) = func.body()
{
let (mut func_editor, _) = SyntaxEditor::new(first_new_item.syntax().clone());
let (func_editor, _) = SyntaxEditor::new(first_new_item.syntax().clone());
func_editor.replace(func_body.syntax(), body.syntax());
ast::AssocItem::cast(func_editor.finish().new_root().clone())
} else {
@@ -188,9 +189,8 @@ fn add_missing_impl_members_inner(
.chain(other_items.iter().cloned())
.collect::<Vec<_>>();
let mut editor = edit.make_editor(impl_def.syntax());
if let Some(assoc_item_list) = impl_def.assoc_item_list() {
assoc_item_list.add_items(&mut editor, new_assoc_items);
assoc_item_list.add_items(&editor, new_assoc_items);
} else {
let assoc_item_list = make.assoc_item_list(new_assoc_items);
editor.insert_all(
@@ -218,7 +218,6 @@ fn add_missing_impl_members_inner(
editor.add_annotation(first_new_item.syntax(), tabstop);
};
};
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
})
}
@@ -74,7 +74,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
.filter(|pat| !matches!(pat, Pat::WildcardPat(_)))
.collect();
let make = SyntaxFactory::with_mappings();
let make = SyntaxFactory::without_mappings();
let scope = ctx.sema.scope(expr.syntax())?;
let module = scope.module();
@@ -271,12 +271,12 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
}
};
let mut editor = builder.make_editor(&old_place);
let editor = builder.make_editor(&old_place);
let mut arms_edit = ArmsEdit { match_arm_list, place: old_place, last_arm: None };
arms_edit.remove_wildcard_arms(ctx, &mut editor);
arms_edit.add_comma_after_last_arm(ctx, &make, &mut editor);
arms_edit.append_arms(&missing_arms, &make, &mut editor);
arms_edit.remove_wildcard_arms(ctx, &editor);
arms_edit.add_comma_after_last_arm(ctx, &make, &editor);
arms_edit.append_arms(&missing_arms, &make, &editor);
if let Some(cap) = ctx.config.snippet_cap {
if let Some(it) = missing_arms
@@ -297,7 +297,6 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
}
}
editor.add_mappings(make.take());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -358,7 +357,7 @@ struct ArmsEdit {
}
impl ArmsEdit {
fn remove_wildcard_arms(&mut self, ctx: &AssistContext<'_>, editor: &mut SyntaxEditor) {
fn remove_wildcard_arms(&mut self, ctx: &AssistContext<'_>, editor: &SyntaxEditor) {
for arm in self.match_arm_list.arms() {
if !matches!(arm.pat(), Some(Pat::WildcardPat(_))) {
self.last_arm = Some(arm);
@@ -387,7 +386,7 @@ fn remove_wildcard_arms(&mut self, ctx: &AssistContext<'_>, editor: &mut SyntaxE
}
}
fn append_arms(&self, arms: &[ast::MatchArm], make: &SyntaxFactory, editor: &mut SyntaxEditor) {
fn append_arms(&self, arms: &[ast::MatchArm], make: &SyntaxFactory, editor: &SyntaxEditor) {
let Some(mut before) = self.place.last_token() else {
stdx::never!("match arm list not contain any token");
return;
@@ -420,7 +419,7 @@ fn add_comma_after_last_arm(
&self,
ctx: &AssistContext<'_>,
make: &SyntaxFactory,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
) {
if let Some(last_arm) = &self.last_arm
&& last_arm.comma_token().is_none()
@@ -93,8 +93,8 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
"Add `: _` before assignment operator",
ident.text_range(),
|builder| {
let mut editor = builder.make_editor(let_stmt.syntax());
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(let_stmt.syntax());
let make = editor.make();
if let_stmt.semicolon_token().is_none() {
editor.insert(
@@ -103,6 +103,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
);
}
let make = editor.make();
let placeholder_ty = make.ty_placeholder();
if let Some(pat) = let_stmt.pat() {
@@ -141,14 +142,12 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
ident.text_range(),
|builder| {
builder.trigger_parameter_hints();
let make = SyntaxFactory::with_mappings();
let mut editor = match &turbofish_target {
let editor = match &turbofish_target {
Either::Left(it) => builder.make_editor(it.syntax()),
Either::Right(it) => builder.make_editor(it.syntax()),
};
let fish_head = get_fish_head(&make, number_of_arguments);
let fish_head = get_fish_head(editor.make(), number_of_arguments);
match turbofish_target {
Either::Left(path_segment) => {
@@ -180,8 +179,6 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
editor.add_annotation(arg.syntax(), builder.make_placeholder_snippet(cap));
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -80,9 +80,8 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
_ => return None,
};
let make = SyntaxFactory::with_mappings();
let (mut editor, demorganed) = SyntaxEditor::with_ast_node(&bin_expr);
let (editor, demorganed) = SyntaxEditor::with_ast_node(&bin_expr);
let make = editor.make();
editor.replace(demorganed.op_token()?, make.token(inv_token));
let mut exprs = VecDeque::from([
@@ -98,7 +97,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
exprs.push_back((bin_expr.lhs()?, cbin_expr.lhs()?, prec));
exprs.push_back((bin_expr.rhs()?, cbin_expr.rhs()?, prec));
} else {
let mut inv = invert_boolean_expression(&make, expr);
let mut inv = invert_boolean_expression(make, expr);
if precedence(&inv).needs_parentheses_in(prec) {
inv = make.expr_paren(inv).into();
}
@@ -108,7 +107,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
return None;
}
} else {
let mut inv = invert_boolean_expression(&make, demorganed.clone());
let mut inv = invert_boolean_expression(make, demorganed.clone());
if precedence(&inv).needs_parentheses_in(prec) {
inv = make.expr_paren(inv).into();
}
@@ -116,7 +115,6 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
}
}
editor.add_mappings(make.finish_with_mappings());
let edit = editor.finish();
let demorganed = ast::Expr::cast(edit.new_root().clone())?;
@@ -126,7 +124,9 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
"Apply De Morgan's law",
op_range,
|builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(bin_expr.syntax());
let make = editor.make();
let (target_node, result_expr) = if let Some(neg_expr) = bin_expr
.syntax()
.parent()
@@ -141,9 +141,9 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
bin_expr.syntax().parent().and_then(ast::ParenExpr::cast)
{
cov_mark::hit!(demorgan_double_parens);
(paren_expr.syntax().clone(), add_bang_paren(&make, demorganed))
(paren_expr.syntax().clone(), add_bang_paren(make, demorganed))
} else {
(bin_expr.syntax().clone(), add_bang_paren(&make, demorganed))
(bin_expr.syntax().clone(), add_bang_paren(make, demorganed))
};
let final_expr = if target_node
@@ -156,9 +156,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
result_expr
};
let mut editor = builder.make_editor(&target_node);
editor.replace(&target_node, final_expr.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -206,8 +204,8 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
label,
op_range,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(method_call.syntax());
let editor = builder.make_editor(method_call.syntax());
let make = editor.make();
// replace the method name
let new_name = match name.text().as_str() {
"all" => make.name_ref("any"),
@@ -217,7 +215,7 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
editor.replace(name.syntax(), new_name.syntax());
// negate all tail expressions in the closure body
let tail_cb = &mut |e: &_| tail_cb_impl(&mut editor, &make, e);
let tail_cb = &mut |e: &_| tail_cb_impl(&editor, e);
walk_expr(&closure_body, &mut |expr| {
if let ast::Expr::ReturnExpr(ret_expr) = expr
&& let Some(ret_expr_arg) = &ret_expr.expr()
@@ -240,8 +238,6 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
} else {
editor.insert(Position::before(method_call.syntax()), make.token(SyntaxKind::BANG));
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -269,18 +265,18 @@ fn validate_method_call_expr(
it_type.impls_trait(sema.db, iter_trait, &[]).then_some((name_ref, arg_expr))
}
fn tail_cb_impl(editor: &mut SyntaxEditor, make: &SyntaxFactory, e: &ast::Expr) {
fn tail_cb_impl(editor: &SyntaxEditor, e: &ast::Expr) {
match e {
ast::Expr::BreakExpr(break_expr) => {
if let Some(break_expr_arg) = break_expr.expr() {
for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(editor, make, e))
for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(editor, e))
}
}
ast::Expr::ReturnExpr(_) => {
// all return expressions have already been handled by the walk loop
}
e => {
let inverted_body = invert_boolean_expression(make, e.clone());
let inverted_body = invert_boolean_expression(editor.make(), e.clone());
editor.replace(e.syntax(), inverted_body.syntax());
}
}
@@ -77,7 +77,7 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
"Convert `if` expression to `bool::then` call",
target,
|builder| {
let (mut editor, closure_body) = SyntaxEditor::with_ast_node(&closure_body);
let (editor, closure_body) = SyntaxEditor::with_ast_node(&closure_body);
// Rewrite all `Some(e)` in tail position to `e`
for_each_tail_expr(&closure_body, &mut |e| {
let e = match e {
@@ -95,13 +95,13 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
let edit = editor.finish();
let closure_body = ast::Expr::cast(edit.new_root().clone()).unwrap();
let mut editor = builder.make_editor(expr.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(expr.syntax());
let make = editor.make();
let closure_body = match closure_body {
ast::Expr::BlockExpr(block) => unwrap_trivial_block(block),
e => e,
};
let cond = if invert_cond { invert_boolean_expression(&make, cond) } else { cond };
let cond = if invert_cond { invert_boolean_expression(make, cond) } else { cond };
let parenthesize = matches!(
cond,
@@ -128,8 +128,6 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
let arg_list = make.arg_list(Some(make.expr_closure(None, closure_body).into()));
let mcall = make.expr_method_call(cond, make.name_ref("then"), arg_list);
editor.replace(expr.syntax(), mcall.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -187,7 +185,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
e => mapless_make.block_expr(None, Some(e)),
};
let (mut editor, closure_body) = SyntaxEditor::with_ast_node(&closure_body);
let (editor, closure_body) = SyntaxEditor::with_ast_node(&closure_body);
// Wrap all tails in `Some(...)`
let none_path = mapless_make.expr_path(mapless_make.ident_path("None"));
let some_path = mapless_make.expr_path(mapless_make.ident_path("Some"));
@@ -210,14 +208,15 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
let edit = editor.finish();
let closure_body = ast::BlockExpr::cast(edit.new_root().clone()).unwrap();
let mut editor = builder.make_editor(mcall.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(mcall.syntax());
let make = editor.make();
let cond = match &receiver {
ast::Expr::ParenExpr(expr) => expr.expr().unwrap_or(receiver),
_ => receiver,
};
let if_expr = make
let if_expr = editor
.make()
.expr_if(
cond,
closure_body,
@@ -225,8 +224,6 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
)
.indent(mcall.indent_level());
editor.replace(mcall.syntax().clone(), if_expr.syntax().clone());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -2,7 +2,7 @@
use ide_db::{famous_defs::FamousDefs, syntax_helpers::suggest_name};
use syntax::{
AstNode,
ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel, syntax_factory::SyntaxFactory},
ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel},
syntax_editor::Position,
};
@@ -48,8 +48,8 @@ pub(crate) fn convert_for_loop_to_while_let(
"Replace this for loop with `while let`",
for_loop.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(for_loop.syntax());
let editor = builder.make_editor(for_loop.syntax());
let make = editor.make();
let (iterable, method) = if impls_core_iter(&ctx.sema, &iterable) {
(iterable, None)
@@ -85,12 +85,7 @@ pub(crate) fn convert_for_loop_to_while_let(
editor.insert(Position::before(for_loop.syntax()), make.whitespace(" "));
editor.insert(Position::before(for_loop.syntax()), label);
}
crate::utils::insert_attributes(
for_loop.syntax(),
&mut editor,
for_loop.attrs(),
&make,
);
crate::utils::insert_attributes(for_loop.syntax(), &editor, for_loop.attrs());
editor.insert(
Position::before(for_loop.syntax()),
@@ -110,7 +105,6 @@ pub(crate) fn convert_for_loop_to_while_let(
editor.replace(for_loop.syntax(), while_loop.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -74,8 +74,8 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
"Convert From to TryFrom",
impl_.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(impl_.syntax());
let editor = builder.make_editor(impl_.syntax());
let make = editor.make();
editor.replace(trait_ty.syntax(), make.ty(&format!("TryFrom<{from_type}>")).syntax());
editor.replace(
@@ -83,11 +83,11 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
make.ty("Result<Self, Self::Error>").syntax(),
);
editor.replace(from_fn_name.syntax(), make.name("try_from").syntax());
editor.replace(tail_expr.syntax(), wrap_ok(&make, tail_expr.clone()).syntax());
editor.replace(tail_expr.syntax(), wrap_ok(make, tail_expr.clone()).syntax());
for r in return_exprs {
let t = r.expr().unwrap_or_else(|| make.expr_unit());
editor.replace(t.syntax(), wrap_ok(&make, t.clone()).syntax());
editor.replace(t.syntax(), wrap_ok(make, t.clone()).syntax());
}
let error_type_alias =
@@ -111,7 +111,6 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
make.whitespace("\n").syntax_element(),
],
);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -3,7 +3,7 @@
use stdx::format_to;
use syntax::{
AstNode,
ast::{self, HasArgList, HasLoopBody, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
ast::{self, HasArgList, HasLoopBody, edit::AstNodeEdit},
};
use crate::{AssistContext, AssistId, Assists};
@@ -57,7 +57,9 @@ pub(crate) fn convert_iter_for_each_to_for(
"Replace this `Iterator::for_each` with a for loop",
range,
|builder| {
let make = SyntaxFactory::with_mappings();
let target_node = stmt.as_ref().map_or(method.syntax(), AstNode::syntax);
let editor = builder.make_editor(target_node);
let make = editor.make();
let indent =
stmt.as_ref().map_or_else(|| method.indent_level(), ast::ExprStmt::indent_level);
@@ -68,9 +70,6 @@ pub(crate) fn convert_iter_for_each_to_for(
.indent(indent);
let expr_for_loop = make.expr_for_loop(param, receiver, block);
let target_node = stmt.as_ref().map_or(method.syntax(), AstNode::syntax);
let mut editor = builder.make_editor(target_node);
editor.replace(target_node, expr_for_loop.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
@@ -1,7 +1,6 @@
use syntax::T;
use syntax::ast::RangeItem;
use syntax::ast::edit::AstNodeEdit;
use syntax::ast::syntax_factory::SyntaxFactory;
use syntax::ast::{self, AstNode, HasName, LetStmt, Pat};
use syntax::syntax_editor::SyntaxEditor;
@@ -26,15 +25,13 @@
// }
// ```
pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let root = ctx.source_file().syntax().clone();
let (mut editor, _) = SyntaxEditor::new(root);
let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone());
// Should focus on the `else` token to trigger
let let_stmt = ctx
.find_token_syntax_at_offset(T![else])
.and_then(|it| it.parent()?.parent())
.or_else(|| ctx.find_token_syntax_at_offset(T![let])?.parent())?;
let let_stmt = LetStmt::cast(let_stmt)?;
let make = SyntaxFactory::with_mappings();
let else_block = let_stmt.let_else()?.block_expr()?;
let else_expr = if else_block.statements().next().is_none()
&& let Some(tail_expr) = else_block.tail_expr()
@@ -50,7 +47,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'
}
let pat = let_stmt.pat()?;
let mut idents = Vec::default();
let pat_without_mut = remove_mut_and_collect_idents(&make, &mut editor, &pat, &mut idents)?;
let pat_without_mut = remove_mut_and_collect_idents(&editor, &pat, &mut idents)?;
let bindings = idents
.into_iter()
.filter_map(|ref pat| {
@@ -72,8 +69,7 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'
},
let_stmt.syntax().text_range(),
|builder| {
// let mut editor = builder.make_editor(let_stmt.syntax());
let make = editor.make();
let binding_paths = bindings
.iter()
.map(|(name, _)| make.expr_path(make.ident_path(&name.to_string())))
@@ -117,19 +113,17 @@ pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'
);
editor.replace(let_stmt.syntax(), new_let_stmt.syntax());
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
fn remove_mut_and_collect_idents(
make: &SyntaxFactory,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
pat: &ast::Pat,
acc: &mut Vec<ast::IdentPat>,
) -> Option<ast::Pat> {
let make = editor.make();
Some(match pat {
ast::Pat::IdentPat(p) => {
acc.push(p.clone());
@@ -139,97 +133,95 @@ fn remove_mut_and_collect_idents(
p.name()?,
);
let non_mut_pat = if let Some(inner) = p.pat() {
non_mut_pat.set_pat(
remove_mut_and_collect_idents(make, editor, &inner, acc),
editor,
make,
)
non_mut_pat.set_pat(remove_mut_and_collect_idents(editor, &inner, acc), editor)
} else {
non_mut_pat
};
non_mut_pat.into()
}
ast::Pat::BoxPat(p) => {
make.box_pat(remove_mut_and_collect_idents(make, editor, &p.pat()?, acc)?).into()
let pat = remove_mut_and_collect_idents(editor, &p.pat()?, acc)?;
make.box_pat(pat).into()
}
ast::Pat::OrPat(p) => {
let pats = p
.pats()
.map(|pat| remove_mut_and_collect_idents(editor, &pat, acc))
.collect::<Option<Vec<_>>>()?;
make.or_pat(pats, p.leading_pipe().is_some()).into()
}
ast::Pat::OrPat(p) => make
.or_pat(
p.pats()
.map(|pat| remove_mut_and_collect_idents(make, editor, &pat, acc))
.collect::<Option<Vec<_>>>()?,
p.leading_pipe().is_some(),
)
.into(),
ast::Pat::ParenPat(p) => {
make.paren_pat(remove_mut_and_collect_idents(make, editor, &p.pat()?, acc)?).into()
let pat = remove_mut_and_collect_idents(editor, &p.pat()?, acc)?;
make.paren_pat(pat).into()
}
ast::Pat::RangePat(p) => {
let start = if let Some(start) = p.start() {
Some(remove_mut_and_collect_idents(editor, &start, acc)?)
} else {
None
};
let end = if let Some(end) = p.end() {
Some(remove_mut_and_collect_idents(editor, &end, acc)?)
} else {
None
};
make.range_pat(start, end).into()
}
ast::Pat::RecordPat(p) => {
let fields = p
.record_pat_field_list()?
.fields()
.map(|field| {
remove_mut_and_collect_idents(editor, &field.pat()?, acc).map(|pat| {
if let Some(name_ref) = field.name_ref() {
make.record_pat_field(name_ref, pat)
} else {
make.record_pat_field_shorthand(pat)
}
})
})
.collect::<Option<Vec<_>>>()?;
editor
.make()
.record_pat_with_fields(
p.path()?,
editor
.make()
.record_pat_field_list(fields, p.record_pat_field_list()?.rest_pat()),
)
.into()
}
ast::Pat::RangePat(p) => make
.range_pat(
if let Some(start) = p.start() {
Some(remove_mut_and_collect_idents(make, editor, &start, acc)?)
} else {
None
},
if let Some(end) = p.end() {
Some(remove_mut_and_collect_idents(make, editor, &end, acc)?)
} else {
None
},
)
.into(),
ast::Pat::RecordPat(p) => make
.record_pat_with_fields(
p.path()?,
make.record_pat_field_list(
p.record_pat_field_list()?
.fields()
.map(|field| {
remove_mut_and_collect_idents(make, editor, &field.pat()?, acc).map(
|pat| {
if let Some(name_ref) = field.name_ref() {
make.record_pat_field(name_ref, pat)
} else {
make.record_pat_field_shorthand(pat)
}
},
)
})
.collect::<Option<Vec<_>>>()?,
p.record_pat_field_list()?.rest_pat(),
),
)
.into(),
ast::Pat::RefPat(p) => {
let inner = p.pat()?;
if let ast::Pat::IdentPat(ident) = inner {
acc.push(ident);
p.clone().into()
} else {
make.ref_pat(remove_mut_and_collect_idents(make, editor, &inner, acc)?).into()
let pat = remove_mut_and_collect_idents(editor, &inner, acc)?;
make.ref_pat(pat).into()
}
}
ast::Pat::SlicePat(p) => make
.slice_pat(
p.pats()
.map(|pat| remove_mut_and_collect_idents(make, editor, &pat, acc))
.collect::<Option<Vec<_>>>()?,
)
.into(),
ast::Pat::TuplePat(p) => make
.tuple_pat(
p.fields()
.map(|field| remove_mut_and_collect_idents(make, editor, &field, acc))
.collect::<Option<Vec<_>>>()?,
)
.into(),
ast::Pat::TupleStructPat(p) => make
.tuple_struct_pat(
p.path()?,
p.fields()
.map(|field| remove_mut_and_collect_idents(make, editor, &field, acc))
.collect::<Option<Vec<_>>>()?,
)
.into(),
ast::Pat::SlicePat(p) => {
let pats = p
.pats()
.map(|pat| remove_mut_and_collect_idents(editor, &pat, acc))
.collect::<Option<Vec<_>>>()?;
make.slice_pat(pats).into()
}
ast::Pat::TuplePat(p) => {
let pats = p
.fields()
.map(|field| remove_mut_and_collect_idents(editor, &field, acc))
.collect::<Option<Vec<_>>>()?;
make.tuple_pat(pats).into()
}
ast::Pat::TupleStructPat(p) => {
let fields = p
.fields()
.map(|field| remove_mut_and_collect_idents(editor, &field, acc))
.collect::<Option<Vec<_>>>()?;
make.tuple_struct_pat(p.path()?, fields).into()
}
ast::Pat::RestPat(_)
| ast::Pat::LiteralPat(_)
| ast::Pat::PathPat(_)
@@ -1,7 +1,7 @@
use ide_db::defs::{Definition, NameRefClass};
use syntax::{
AstNode, SyntaxNode,
ast::{self, HasName, Name, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
ast::{self, HasName, Name, edit::AstNodeEdit},
syntax_editor::SyntaxEditor,
};
@@ -121,8 +121,8 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
// Rename `extracted` with `binding` in `pat`.
fn rename_variable(pat: &ast::Pat, extracted: &[Name], binding: ast::Pat) -> SyntaxNode {
let (mut editor, syntax) = SyntaxEditor::new(pat.syntax().clone());
let make = SyntaxFactory::with_mappings();
let (editor, syntax) = SyntaxEditor::new(pat.syntax().clone());
let make = editor.make();
let extracted = extracted
.iter()
.map(|e| e.syntax().text_range() - pat.syntax().text_range().start())
@@ -137,7 +137,9 @@ fn rename_variable(pat: &ast::Pat, extracted: &[Name], binding: ast::Pat) -> Syn
if let Some(name_ref) = record_pat_field.field_name() {
editor.replace(
record_pat_field.syntax(),
make.record_pat_field(make.name_ref(&name_ref.text()), binding.clone())
editor
.make()
.record_pat_field(make.name_ref(&name_ref.text()), binding.clone())
.syntax(),
);
}
@@ -145,7 +147,6 @@ fn rename_variable(pat: &ast::Pat, extracted: &[Name], binding: ast::Pat) -> Syn
editor.replace(extracted_syntax, binding.syntax());
}
}
editor.add_mappings(make.finish_with_mappings());
let new_node = editor.finish().new_root().clone();
if let Some(pat) = ast::Pat::cast(new_node.clone()) {
pat.dedent(1.into()).syntax().clone()
@@ -3,9 +3,7 @@
use syntax::{
NodeOrToken, SyntaxKind, SyntaxNode, T,
algo::next_non_trivia_token,
ast::{
self, AstNode, HasAttrs, HasGenericParams, HasVisibility, syntax_factory::SyntaxFactory,
},
ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
match_ast,
syntax_editor::{Element, Position, SyntaxEditor},
};
@@ -102,7 +100,7 @@ fn edit_struct_def(
// Note that we don't need to consider macro files in this function because this is
// currently not triggered for struct definitions inside macro calls.
let tuple_fields = record_fields.fields().filter_map(|f| {
let (mut editor, field) =
let (editor, field) =
SyntaxEditor::with_ast_node(&ast::make::tuple_field(f.visibility(), f.ty()?));
editor.insert_all(
Position::first_child_of(field.syntax()),
@@ -113,15 +111,15 @@ fn edit_struct_def(
Some(field)
});
let make = SyntaxFactory::without_mappings();
let mut edit = builder.make_editor(strukt.syntax());
let editor = builder.make_editor(strukt.syntax());
let make = editor.make();
let tuple_fields = make.tuple_field_list(tuple_fields);
let mut elements = vec![tuple_fields.syntax().clone().into()];
if let Either::Left(strukt) = strukt {
if let Some(w) = strukt.where_clause() {
edit.delete(w.syntax());
editor.delete(w.syntax());
elements.extend([
make.whitespace("\n").into(),
@@ -136,23 +134,23 @@ fn edit_struct_def(
.and_then(|tok| tok.next_token())
.filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
{
edit.delete(tok);
editor.delete(tok);
}
} else {
elements.push(make.token(T![;]).into());
}
}
edit.replace_with_many(record_fields.syntax(), elements);
editor.replace_with_many(record_fields.syntax(), elements);
if let Some(tok) = record_fields
.l_curly_token()
.and_then(|tok| tok.prev_token())
.filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
{
edit.delete(tok)
editor.delete(tok)
}
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
}
fn edit_struct_references(
@@ -168,18 +166,18 @@ fn edit_struct_references(
for (file_id, refs) in usages {
let source = ctx.sema.parse(file_id);
let mut edit = builder.make_editor(source.syntax());
let editor = builder.make_editor(source.syntax());
for r in refs {
process_struct_name_reference(ctx, r, &mut edit, &source);
process_struct_name_reference(ctx, r, &editor, &source);
}
builder.add_file_edits(file_id.file_id(ctx.db()), edit);
builder.add_file_edits(file_id.file_id(ctx.db()), editor);
}
}
fn process_struct_name_reference(
ctx: &AssistContext<'_>,
r: FileReference,
edit: &mut SyntaxEditor,
edit: &SyntaxEditor,
source: &ast::SourceFile,
) -> Option<()> {
// First check if it's the last semgnet of a path that directly belongs to a record
@@ -232,7 +230,7 @@ fn process_struct_name_reference(
fn record_to_tuple_struct_like<T, I>(
ctx: &AssistContext<'_>,
source: &ast::SourceFile,
edit: &mut SyntaxEditor,
editor: &SyntaxEditor,
field_list: T,
fields: impl FnOnce(&T) -> I,
) -> Option<()>
@@ -240,7 +238,7 @@ fn record_to_tuple_struct_like<T, I>(
T: AstNode,
I: IntoIterator<Item = ast::NameRef>,
{
let make = SyntaxFactory::without_mappings();
let make = editor.make();
let orig = ctx.sema.original_range_opt(field_list.syntax())?;
let list_range = cover_edit_range(source.syntax(), orig.range);
@@ -254,13 +252,13 @@ fn record_to_tuple_struct_like<T, I>(
};
if l_curly.kind() == T!['{'] {
delete_whitespace(edit, l_curly.prev_token());
delete_whitespace(edit, l_curly.next_token());
edit.replace(l_curly, make.token(T!['(']));
delete_whitespace(editor, l_curly.prev_token());
delete_whitespace(editor, l_curly.next_token());
editor.replace(l_curly, make.token(T!['(']));
}
if r_curly.kind() == T!['}'] {
delete_whitespace(edit, r_curly.prev_token());
edit.replace(r_curly, make.token(T![')']));
delete_whitespace(editor, r_curly.prev_token());
editor.replace(r_curly, make.token(T![')']));
}
for name_ref in fields(&field_list) {
@@ -270,14 +268,14 @@ fn record_to_tuple_struct_like<T, I>(
if let Some(colon) = next_non_trivia_token(name_range.end().clone())
&& colon.kind() == T![:]
{
edit.delete(&colon);
edit.delete_all(name_range);
editor.delete(&colon);
editor.delete_all(name_range);
if let Some(next) = next_non_trivia_token(colon.clone())
&& next.kind() != T!['}']
{
// Avoid overlapping delete whitespace on `{ field: }`
delete_whitespace(edit, colon.next_token());
delete_whitespace(editor, colon.next_token());
}
}
}
@@ -289,7 +287,6 @@ fn edit_field_references(
builder: &mut SourceChangeBuilder,
fields: impl Iterator<Item = ast::RecordField>,
) {
let make = SyntaxFactory::without_mappings();
for (index, field) in fields.enumerate() {
let field = match ctx.sema.to_def(&field) {
Some(it) => it,
@@ -299,13 +296,14 @@ fn edit_field_references(
let usages = def.usages(&ctx.sema).all();
for (file_id, refs) in usages {
let source = ctx.sema.parse(file_id);
let mut edit = builder.make_editor(source.syntax());
let editor = builder.make_editor(source.syntax());
let make = editor.make();
for r in refs {
if let Some(name_ref) = r.name.as_name_ref() {
// Only edit the field reference if it's part of a `.field` access
if name_ref.syntax().parent().and_then(ast::FieldExpr::cast).is_some() {
edit.replace_all(
editor.replace_all(
cover_edit_range(source.syntax(), r.range),
vec![make.name_ref(&index.to_string()).syntax().clone().into()],
);
@@ -313,12 +311,12 @@ fn edit_field_references(
}
}
builder.add_file_edits(file_id.file_id(ctx.db()), edit);
builder.add_file_edits(file_id.file_id(ctx.db()), editor);
}
}
}
fn delete_whitespace(edit: &mut SyntaxEditor, whitespace: Option<impl Element>) {
fn delete_whitespace(edit: &SyntaxEditor, whitespace: Option<impl Element>) {
let Some(whitespace) = whitespace else { return };
let NodeOrToken::Token(token) = whitespace.syntax_element() else { return };
@@ -328,7 +326,7 @@ fn delete_whitespace(edit: &mut SyntaxEditor, whitespace: Option<impl Element>)
}
fn remove_trailing_comma(w: ast::WhereClause) -> SyntaxNode {
let (mut editor, w) = SyntaxEditor::new(w.syntax().clone());
let (editor, w) = SyntaxEditor::new(w.syntax().clone());
if let Some(last) = w.last_child_or_token()
&& last.kind() == T![,]
{
@@ -5,10 +5,7 @@
SyntaxKind::WHITESPACE,
T,
algo::previous_non_trivia_token,
ast::{
self, HasArgList, HasLoopBody, HasName, RangeItem, edit::AstNodeEdit, make,
syntax_factory::SyntaxFactory,
},
ast::{self, HasArgList, HasLoopBody, HasName, RangeItem, edit::AstNodeEdit, make},
syntax_editor::{Element, Position, SyntaxEditor},
};
@@ -55,13 +52,13 @@ pub(crate) fn convert_range_for_to_while(acc: &mut Assists, ctx: &AssistContext<
description,
for_.syntax().text_range(),
|builder| {
let mut edit = builder.make_editor(for_.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(for_.syntax());
let make = editor.make();
let indent = for_.indent_level();
let pat = make.ident_pat(pat.ref_token().is_some(), true, name.clone());
let let_stmt = make.let_stmt(pat.into(), None, Some(start));
edit.insert_all(
editor.insert_all(
Position::before(for_.syntax()),
vec![
let_stmt.syntax().syntax_element(),
@@ -86,25 +83,19 @@ pub(crate) fn convert_range_for_to_while(acc: &mut Assists, ctx: &AssistContext<
elements.push(make.token(T![loop]).syntax_element());
}
edit.replace_all(
editor.replace_all(
for_kw.syntax_element()..=iterable.syntax().syntax_element(),
elements,
);
let op = ast::BinaryOp::Assignment { op: Some(ast::ArithOp::Add) };
process_loop_body(
body,
label,
&mut edit,
vec![
make.whitespace(&format!("\n{}", indent + 1)).syntax_element(),
make.expr_bin(var_expr, op, step).syntax().syntax_element(),
make.token(T![;]).syntax_element(),
],
);
edit.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), edit);
let incrementer = vec![
make.whitespace(&format!("\n{}", indent + 1)).syntax_element(),
make.expr_bin(var_expr, op, step).syntax().syntax_element(),
make.token(T![;]).syntax_element(),
];
process_loop_body(body, label, &editor, incrementer);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -128,7 +119,7 @@ fn extract_range(iterable: &ast::Expr) -> Option<(ast::Expr, Option<ast::Expr>,
fn process_loop_body(
body: ast::StmtList,
label: Option<ast::Label>,
edit: &mut SyntaxEditor,
edit: &SyntaxEditor,
incrementer: Vec<SyntaxElement>,
) -> Option<()> {
let last = previous_non_trivia_token(body.r_curly_token()?)?.syntax_element();
@@ -156,7 +147,7 @@ fn process_loop_body(
let continue_label = make::lifetime("'cont");
let break_expr = make::expr_break(Some(continue_label.clone()), None);
let (mut new_edit, _) = SyntaxEditor::new(new_body.syntax().clone());
let (new_edit, _) = SyntaxEditor::new(new_body.syntax().clone());
for continue_expr in &continues {
new_edit.replace(continue_expr.syntax(), break_expr.syntax());
}
@@ -130,9 +130,10 @@ fn if_expr_to_guarded_return(
"Convert to guarded return",
target,
|edit| {
let make = SyntaxFactory::without_mappings();
let editor = edit.make_editor(if_expr.syntax());
let make = editor.make();
let if_indent_level = IndentLevel::from_node(if_expr.syntax());
let early_expression = else_block.make_early_block(&ctx.sema, &make);
let early_expression = else_block.make_early_block(&ctx.sema, make);
let replacement = let_chains.into_iter().map(|expr| {
if let ast::Expr::LetExpr(let_expr) = &expr
&& let (Some(pat), Some(expr)) = (let_expr.pat(), let_expr.expr())
@@ -145,8 +146,8 @@ fn if_expr_to_guarded_return(
} else {
// If.
let new_expr = {
let then_branch = clean_stmt_block(&early_expression, &make);
let cond = invert_boolean_expression(&make, expr);
let then_branch = clean_stmt_block(&early_expression, make);
let cond = invert_boolean_expression(make, expr);
make.expr_if(cond, then_branch, None).indent(if_indent_level)
};
new_expr.syntax().clone()
@@ -170,7 +171,6 @@ fn if_expr_to_guarded_return(
.take_while(|i| *i != end_of_then),
)
.collect();
let mut editor = edit.make_editor(if_expr.syntax());
editor.replace_with_many(if_expr.syntax(), then_statements);
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
@@ -209,22 +209,21 @@ fn let_stmt_to_guarded_return(
"Convert to guarded return",
target,
|edit| {
let editor = edit.make_editor(let_stmt.syntax());
let make = editor.make();
let let_indent_level = IndentLevel::from_node(let_stmt.syntax());
let make = SyntaxFactory::without_mappings();
let replacement = {
let let_else_stmt = make.let_else_stmt(
happy_pattern,
let_stmt.ty(),
expr.reset_indent(),
else_block.make_early_block(&ctx.sema, &make),
else_block.make_early_block(&ctx.sema, make),
);
let let_else_stmt = let_else_stmt.indent(let_indent_level);
let_else_stmt.syntax().clone()
};
let mut editor = edit.make_editor(let_stmt.syntax());
editor.replace(let_stmt.syntax(), replacement);
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -268,7 +267,8 @@ fn make_early_block(
return block_expr.reset_indent();
}
let (mut edit, block_expr) = SyntaxEditor::with_ast_node(&block_expr.reset_indent());
let (editor, block_expr) = SyntaxEditor::with_ast_node(&block_expr.reset_indent());
let make = editor.make();
let last_stmt = block_expr.statements().last().map(|it| it.syntax().clone());
let tail_expr = block_expr.tail_expr().map(|it| it.syntax().clone());
@@ -277,13 +277,11 @@ fn make_early_block(
};
let whitespace = last_element.prev_sibling_or_token().filter(|it| it.kind() == WHITESPACE);
let make = SyntaxFactory::without_mappings();
if let Some(tail_expr) = block_expr.tail_expr()
&& !self.kind.is_unit()
{
let early_expr = self.kind.make_early_expr(sema, &make, Some(tail_expr.clone()));
edit.replace(tail_expr.syntax(), early_expr.syntax());
let early_expr = self.kind.make_early_expr(sema, make, Some(tail_expr.clone()));
editor.replace(tail_expr.syntax(), early_expr.syntax());
} else {
let last_stmt = match block_expr.tail_expr() {
Some(expr) => make.expr_stmt(expr).syntax().clone(),
@@ -291,14 +289,14 @@ fn make_early_block(
};
let whitespace =
make.whitespace(&whitespace.map_or(String::new(), |it| it.to_string()));
let early_expr = self.kind.make_early_expr(sema, &make, None).syntax().clone().into();
edit.replace_with_many(
let early_expr = self.kind.make_early_expr(sema, make, None).syntax().clone().into();
editor.replace_with_many(
last_element,
vec![last_stmt.into(), whitespace.into(), early_expr],
);
}
ast::BlockExpr::cast(edit.finish().new_root().clone()).unwrap()
ast::BlockExpr::cast(editor.finish().new_root().clone()).unwrap()
}
}
@@ -72,15 +72,15 @@ pub(crate) fn convert_tuple_return_type_to_struct(
"Convert tuple return type to tuple struct",
target,
move |edit| {
let mut syntax_editor = edit.make_editor(ret_type.syntax());
let syntax_factory = SyntaxFactory::with_mappings();
let editor = edit.make_editor(ret_type.syntax());
let make = editor.make();
let usages = Definition::Function(fn_def).usages(&ctx.sema).all();
let struct_name = format!("{}Result", stdx::to_camel_case(&fn_name.to_string()));
let parent = fn_.syntax().ancestors().find_map(<Either<ast::Impl, ast::Trait>>::cast);
add_tuple_struct_def(
edit,
&syntax_factory,
make,
ctx,
&usages,
parent.as_ref().map(|it| it.syntax()).unwrap_or(fn_.syntax()),
@@ -89,22 +89,12 @@ pub(crate) fn convert_tuple_return_type_to_struct(
&target_module,
);
syntax_editor.replace(
ret_type.syntax(),
syntax_factory.ret_type(syntax_factory.ty(&struct_name)).syntax(),
);
editor.replace(ret_type.syntax(), make.ret_type(make.ty(&struct_name)).syntax());
if let Some(fn_body) = fn_.body() {
replace_body_return_values(
&mut syntax_editor,
&syntax_factory,
ast::Expr::BlockExpr(fn_body),
&struct_name,
);
replace_body_return_values(&editor, ast::Expr::BlockExpr(fn_body), &struct_name);
}
syntax_editor.add_mappings(syntax_factory.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), syntax_editor);
edit.add_file_edits(ctx.vfs_file_id(), editor);
replace_usages(edit, ctx, &usages, &struct_name, &target_module);
},
@@ -122,35 +112,22 @@ fn replace_usages(
for (file_id, references) in usages.iter() {
let Some(first_ref) = references.first() else { continue };
let mut editor = edit.make_editor(first_ref.name.syntax().as_node().unwrap());
let syntax_factory = SyntaxFactory::with_mappings();
let editor = edit.make_editor(first_ref.name.syntax().as_node().unwrap());
let make = editor.make();
let refs_with_imports = augment_references_with_imports(
&syntax_factory,
ctx,
references,
struct_name,
target_module,
);
let refs_with_imports =
augment_references_with_imports(make, ctx, references, struct_name, target_module);
refs_with_imports.into_iter().rev().for_each(|(name, import_data)| {
if let Some(fn_) = name.syntax().parent().and_then(ast::Fn::cast) {
cov_mark::hit!(replace_trait_impl_fns);
if let Some(ret_type) = fn_.ret_type() {
editor.replace(
ret_type.syntax(),
syntax_factory.ret_type(syntax_factory.ty(struct_name)).syntax(),
);
editor.replace(ret_type.syntax(), make.ret_type(make.ty(struct_name)).syntax());
}
if let Some(fn_body) = fn_.body() {
replace_body_return_values(
&mut editor,
&syntax_factory,
ast::Expr::BlockExpr(fn_body),
struct_name,
);
replace_body_return_values(&editor, ast::Expr::BlockExpr(fn_body), struct_name);
}
} else {
// replace tuple patterns
@@ -172,27 +149,17 @@ fn replace_usages(
for tuple_pat in tuple_pats {
editor.replace(
tuple_pat.syntax(),
syntax_factory
.tuple_struct_pat(
syntax_factory.path_from_text(struct_name),
tuple_pat.fields(),
)
editor
.make()
.tuple_struct_pat(make.path_from_text(struct_name), tuple_pat.fields())
.syntax(),
);
}
}
if let Some((import_scope, path)) = import_data {
insert_use_with_editor(
&import_scope,
path,
&ctx.config.insert_use,
&mut editor,
&syntax_factory,
);
insert_use_with_editor(&import_scope, path, &ctx.config.insert_use, &editor);
}
});
editor.add_mappings(syntax_factory.finish_with_mappings());
edit.add_file_edits(file_id.file_id(ctx.db()), editor);
}
}
@@ -296,12 +263,8 @@ fn add_tuple_struct_def(
}
/// Replaces each returned tuple in `body` with the constructor of the tuple struct named `struct_name`.
fn replace_body_return_values(
syntax_editor: &mut SyntaxEditor,
syntax_factory: &SyntaxFactory,
body: ast::Expr,
struct_name: &str,
) {
fn replace_body_return_values(editor: &SyntaxEditor, body: ast::Expr, struct_name: &str) {
let make = editor.make();
let mut exprs_to_wrap = Vec::new();
let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e);
@@ -316,11 +279,11 @@ fn replace_body_return_values(
for ret_expr in exprs_to_wrap {
if let ast::Expr::TupleExpr(tuple_expr) = &ret_expr {
let struct_constructor = syntax_factory.expr_call(
syntax_factory.expr_path(syntax_factory.ident_path(struct_name)),
syntax_factory.arg_list(tuple_expr.fields()),
let struct_constructor = make.expr_call(
make.expr_path(make.ident_path(struct_name)),
make.arg_list(tuple_expr.fields()),
);
syntax_editor.replace(ret_expr.syntax(), struct_constructor.syntax());
editor.replace(ret_expr.syntax(), struct_constructor.syntax());
}
}
}
@@ -86,24 +86,25 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
"Convert to named struct",
target,
|edit| {
let names = generate_names(tuple_fields.fields());
let editor = edit.make_editor(syntax);
let names = generate_names(tuple_fields.fields(), editor.make());
edit_field_references(ctx, edit, tuple_fields.fields(), &names);
let mut editor = edit.make_editor(syntax);
edit_struct_references(ctx, edit, strukt_def, &names);
edit_struct_def(&mut editor, &strukt_or_variant, tuple_fields, names);
edit_struct_def(&editor, &strukt_or_variant, tuple_fields, names);
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
fn edit_struct_def(
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
strukt: &Either<ast::Struct, ast::Variant>,
tuple_fields: ast::TupleFieldList,
names: Vec<ast::Name>,
) {
let make = editor.make();
let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| {
let (mut field_editor, field) =
let (field_editor, field) =
SyntaxEditor::with_ast_node(&ast::make::record_field(f.visibility(), name, f.ty()?));
field_editor.insert_all(
Position::first_child_of(field.syntax()),
@@ -111,7 +112,6 @@ fn edit_struct_def(
);
ast::RecordField::cast(field_editor.finish().new_root().clone())
});
let make = SyntaxFactory::without_mappings();
let record_fields = make.record_field_list(record_fields);
let tuple_fields_before = Position::before(tuple_fields.syntax());
@@ -153,10 +153,10 @@ fn edit_struct_references(
for (file_id, refs) in usages {
let source = ctx.sema.parse(file_id);
let mut editor = edit.make_editor(source.syntax());
let editor = edit.make_editor(source.syntax());
for r in refs {
process_struct_name_reference(ctx, r, &mut editor, &source, &strukt_def, names);
process_struct_name_reference(ctx, r, &editor, &source, &strukt_def, names);
}
edit.add_file_edits(file_id.file_id(ctx.db()), editor);
@@ -166,12 +166,12 @@ fn edit_struct_references(
fn process_struct_name_reference(
ctx: &AssistContext<'_>,
r: FileReference,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
source: &ast::SourceFile,
strukt_def: &Definition,
names: &[ast::Name],
) -> Option<()> {
let make = SyntaxFactory::without_mappings();
let make = editor.make();
let name_ref = r.name.as_name_ref()?;
let path_segment = name_ref.syntax().parent().and_then(ast::PathSegment::cast)?;
let full_path = path_segment.syntax().parent().and_then(ast::Path::cast)?.top_path();
@@ -231,10 +231,11 @@ fn process_struct_name_reference(
fn process_delimiter(
ctx: &AssistContext<'_>,
source: &ast::SourceFile,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
list: &impl AstNode,
first_insert: Vec<syntax::SyntaxElement>,
) {
let make = editor.make();
let Some(range) = ctx.sema.original_range_opt(list.syntax()) else { return };
let place = cover_edit_range(source.syntax(), range.range);
@@ -247,7 +248,6 @@ fn process_delimiter(
syntax::NodeOrToken::Token(t) => Some(t.clone()),
};
let make = SyntaxFactory::without_mappings();
if let Some(l_paren) = l_paren
&& l_paren.kind() == T!['(']
{
@@ -284,7 +284,7 @@ fn edit_field_references(
let usages = def.usages(&ctx.sema).all();
for (file_id, refs) in usages {
let source = ctx.sema.parse(file_id);
let mut editor = edit.make_editor(source.syntax());
let editor = edit.make_editor(source.syntax());
for r in refs {
if let Some(name_ref) = r.name.as_name_ref()
&& let Some(original) = ctx.sema.original_range_opt(name_ref.syntax())
@@ -300,8 +300,10 @@ fn edit_field_references(
}
}
fn generate_names(fields: impl Iterator<Item = ast::TupleField>) -> Vec<ast::Name> {
let make = SyntaxFactory::without_mappings();
fn generate_names(
fields: impl Iterator<Item = ast::TupleField>,
make: &SyntaxFactory,
) -> Vec<ast::Name> {
fields
.enumerate()
.map(|(i, _)| {
@@ -6,7 +6,6 @@
ast::{
self, HasLoopBody,
edit::{AstNodeEdit, IndentLevel},
syntax_factory::SyntaxFactory,
},
syntax_editor::{Element, Position},
};
@@ -52,18 +51,19 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
"Convert while to loop",
target,
|builder| {
let make = SyntaxFactory::without_mappings();
let mut edit = builder.make_editor(while_expr.syntax());
let editor = builder.make_editor(while_expr.syntax());
let make = editor.make();
let while_indent_level = IndentLevel::from_node(while_expr.syntax());
let break_block = make
let break_block = editor
.make()
.block_expr(
iter::once(make.expr_stmt(make.expr_break(None, None).into()).into()),
None,
)
.indent(IndentLevel(1));
edit.replace_all(
editor.replace_all(
while_kw.syntax_element()..=while_cond.syntax().syntax_element(),
vec![make.token(T![loop]).syntax_element()],
);
@@ -73,17 +73,17 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
let if_expr = make.expr_if(while_cond, then_branch, Some(break_block.into()));
let stmts = iter::once(make.expr_stmt(if_expr.into()).into());
let block_expr = make.block_expr(stmts, None);
edit.replace(while_body.syntax(), block_expr.indent(while_indent_level).syntax());
editor.replace(while_body.syntax(), block_expr.indent(while_indent_level).syntax());
} else {
let if_cond = invert_boolean_expression(&make, while_cond);
let if_cond = invert_boolean_expression(make, while_cond);
let if_expr = make.expr_if(if_cond, break_block, None).indent(while_indent_level);
if !while_body.syntax().text().contains_char('\n') {
edit.insert(
editor.insert(
Position::after(&l_curly),
make.whitespace(&format!("\n{while_indent_level}")),
);
}
edit.insert_all(
editor.insert_all(
Position::after(&l_curly),
vec![
make.whitespace(&format!("\n{}", while_indent_level + 1)).into(),
@@ -91,9 +91,7 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
],
);
};
edit.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -124,9 +124,9 @@ fn destructure_struct_binding_impl(
data: &StructEditData,
) {
let field_names = generate_field_names(ctx, data);
let mut editor = builder.make_editor(data.target.syntax());
destructure_pat(ctx, &mut editor, data, &field_names);
update_usages(ctx, &mut editor, data, &field_names.into_iter().collect());
let editor = builder.make_editor(data.target.syntax());
destructure_pat(ctx, &editor, data, &field_names);
update_usages(ctx, &editor, data, &field_names.into_iter().collect());
builder.add_file_edits(ctx.vfs_file_id(), editor);
}
@@ -145,19 +145,16 @@ struct StructEditData {
}
impl StructEditData {
fn apply_to_destruct(
&self,
new_pat: ast::Pat,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
) {
fn apply_to_destruct(&self, new_pat: ast::Pat, editor: &SyntaxEditor) {
let make = editor.make();
match &self.target {
Target::IdentPat(pat) => {
// If the binding is nested inside a record, we need to wrap the new
// destructured pattern in a non-shorthand record field
if self.need_record_field_name {
let new_pat =
make.record_pat_field(make.name_ref(&self.name.to_string()), new_pat);
let new_pat = editor
.make()
.record_pat_field(make.name_ref(&self.name.to_string()), new_pat);
editor.replace(pat.syntax(), new_pat.syntax())
} else {
editor.replace(pat.syntax(), new_pat.syntax())
@@ -275,15 +272,15 @@ fn last_usage(usages: &[FileReference]) -> Option<SyntaxNode> {
fn destructure_pat(
_ctx: &AssistContext<'_>,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
data: &StructEditData,
field_names: &[(SmolStr, SmolStr)],
) {
let make = editor.make();
let struct_path = mod_path_to_ast(&data.struct_def_path, data.edition);
let is_ref = data.target.is_ref();
let is_mut = data.target.is_mut();
let make = SyntaxFactory::with_mappings();
let new_pat = match data.kind {
hir::StructKind::Tuple => {
let ident_pats = field_names.iter().map(|(_, new_name)| {
@@ -297,7 +294,7 @@ fn destructure_pat(
// Use shorthand syntax if possible
if old_name == new_name {
make.record_pat_field_shorthand(
make.ident_pat(is_ref, is_mut, make.name(old_name)).into(),
editor.make().ident_pat(is_ref, is_mut, make.name(old_name)).into(),
)
} else {
make.record_pat_field(
@@ -314,8 +311,7 @@ fn destructure_pat(
hir::StructKind::Unit => make.path_pat(struct_path),
};
data.apply_to_destruct(new_pat, editor, &make);
editor.add_mappings(make.finish_with_mappings());
data.apply_to_destruct(new_pat, editor);
}
fn generate_field_names(ctx: &AssistContext<'_>, data: &StructEditData) -> Vec<(SmolStr, SmolStr)> {
@@ -354,18 +350,16 @@ fn new_field_name(base_name: SmolStr, names_in_scope: &FxHashSet<SmolStr>) -> Sm
fn update_usages(
ctx: &AssistContext<'_>,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
data: &StructEditData,
field_names: &FxHashMap<SmolStr, SmolStr>,
) {
let source = ctx.source_file().syntax();
let make = SyntaxFactory::with_mappings();
let edits = data
.usages
.iter()
.filter_map(|r| build_usage_edit(ctx, &make, data, r, field_names))
.filter_map(|r| build_usage_edit(ctx, editor.make(), data, r, field_names))
.collect_vec();
editor.add_mappings(make.finish_with_mappings());
for (old, new) in edits {
if let Some(range) = ctx.sema.original_range_opt(&old) {
editor.replace_all(cover_edit_range(source, range.range), vec![new.into()]);
@@ -89,22 +89,17 @@ fn destructure_tuple_edit_impl(
data: &TupleData,
in_sub_pattern: bool,
) {
let mut syntax_editor = edit.make_editor(data.ident_pat.syntax());
let syntax_factory = SyntaxFactory::with_mappings();
let editor = edit.make_editor(data.ident_pat.syntax());
let make = editor.make();
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);
let assignment_edit = edit_tuple_assignment(ctx, edit, &editor, data, in_sub_pattern);
let current_file_usages_edit = edit_tuple_usages(data, ctx, make, in_sub_pattern);
assignment_edit.apply(&mut syntax_editor, &syntax_factory);
assignment_edit.apply(&editor);
if let Some(usages_edit) = current_file_usages_edit {
usages_edit
.into_iter()
.for_each(|usage_edit| usage_edit.apply(ctx, edit, &mut syntax_editor))
usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(ctx, edit, &editor))
}
syntax_editor.add_mappings(syntax_factory.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), syntax_editor);
edit.add_file_edits(ctx.vfs_file_id(), editor);
}
fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleData> {
@@ -175,11 +170,11 @@ struct TupleData {
fn edit_tuple_assignment(
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
data: &TupleData,
in_sub_pattern: bool,
) -> AssignmentEdit {
let make = editor.make();
let tuple_pat = {
let original = &data.ident_pat;
let is_ref = original.ref_token().is_some();
@@ -223,18 +218,17 @@ struct AssignmentEdit {
}
impl AssignmentEdit {
fn apply(self, syntax_editor: &mut SyntaxEditor, syntax_mapping: &SyntaxFactory) {
fn apply(self, editor: &SyntaxEditor) {
let make = editor.make();
// 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()), syntax_editor, syntax_mapping);
self.ident_pat.set_pat(Some(self.tuple_pat.into()), editor);
} else if self.is_shorthand_field {
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![:]));
editor.insert(Position::after(self.ident_pat.syntax()), self.tuple_pat.syntax());
editor.insert(Position::after(self.ident_pat.syntax()), make.whitespace(" "));
editor.insert(Position::after(self.ident_pat.syntax()), make.token(T![:]));
} else {
syntax_editor.replace(self.ident_pat.syntax(), self.tuple_pat.syntax())
editor.replace(self.ident_pat.syntax(), self.tuple_pat.syntax())
}
}
}
@@ -313,7 +307,7 @@ fn apply(
self,
ctx: &AssistContext<'_>,
edit: &mut SourceChangeBuilder,
syntax_editor: &mut SyntaxEditor,
syntax_editor: &SyntaxEditor,
) {
match self {
EditTupleUsage::NoIndex(range) => {
@@ -65,19 +65,19 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
"Replace try expression with match",
target,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(try_expr.syntax());
let editor = builder.make_editor(try_expr.syntax());
let make = editor.make();
let sad_pat = match try_enum {
TryEnum::Option => make.path_pat(make.ident_path("None")),
TryEnum::Result => make
TryEnum::Result => editor
.make()
.tuple_struct_pat(
make.ident_path("Err"),
iter::once(make.path_pat(make.ident_path("err"))),
)
.into(),
};
let sad_expr = make.expr_return(Some(sad_expr(try_enum, &make, || {
let sad_expr = make.expr_return(Some(sad_expr(try_enum, make, || {
make.expr_path(make.ident_path("err"))
})));
@@ -90,12 +90,12 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
let match_arm_list = make.match_arm_list([happy_arm, sad_arm]);
let expr_match = make
let expr_match = editor
.make()
.expr_match(expr.clone(), match_arm_list)
.indent(IndentLevel::from_node(try_expr.syntax()));
editor.replace(try_expr.syntax(), expr_match.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -109,8 +109,8 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
"Replace try expression with let else",
target,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(let_stmt.syntax());
let editor = builder.make_editor(let_stmt.syntax());
let make = editor.make();
let indent_level = IndentLevel::from_node(let_stmt.syntax());
let fill_expr = || crate::utils::expr_fill_default(ctx.config);
@@ -121,19 +121,25 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
TryEnum::Result => make.ty_result(ty, make.ty_infer().into()).into(),
}),
expr,
make.block_expr(
iter::once(
make.expr_stmt(
make.expr_return(Some(sad_expr(try_enum, &make, fill_expr))).into(),
)
.into(),
),
None,
)
.indent(indent_level),
editor
.make()
.block_expr(
iter::once(
editor
.make()
.expr_stmt(
editor
.make()
.expr_return(Some(sad_expr(try_enum, make, fill_expr)))
.into(),
)
.into(),
),
None,
)
.indent(indent_level),
);
editor.replace(let_stmt.syntax(), new_let_stmt.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -8,7 +8,7 @@
use stdx::never;
use syntax::{
AstNode, Direction, SyntaxNode, SyntaxToken, T,
ast::{self, Use, UseTree, VisibilityKind, syntax_factory::SyntaxFactory},
ast::{self, Use, UseTree, VisibilityKind},
};
use crate::{
@@ -148,8 +148,8 @@ fn build_expanded_import(
current_module: Module,
reexport_public_items: bool,
) {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(use_tree.syntax());
let editor = builder.make_editor(use_tree.syntax());
let make = editor.make();
let (must_be_pub, visible_from) = if !reexport_public_items {
(false, current_module)
} else {
@@ -192,7 +192,6 @@ fn build_expanded_import(
}
None => never!(),
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
}
@@ -51,23 +51,25 @@ fn expand_record_rest_pattern(
"Fill struct fields",
rest_pat.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(rest_pat.syntax());
let editor = builder.make_editor(rest_pat.syntax());
let make = editor.make();
let new_fields = old_field_list.fields().chain(matched_fields.iter().map(|(f, _)| {
make.record_pat_field_shorthand(
make.ident_pat(
false,
false,
make.name(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()),
)
.into(),
editor
.make()
.ident_pat(
false,
false,
editor
.make()
.name(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()),
)
.into(),
)
}));
let new_field_list = make.record_pat_field_list(new_fields, None);
editor.replace(old_field_list.syntax(), new_field_list.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -130,8 +132,8 @@ fn expand_tuple_struct_rest_pattern(
"Fill tuple struct fields",
rest_pat.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(rest_pat.syntax());
let editor = builder.make_editor(rest_pat.syntax());
let make = editor.make();
let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax()));
let new_pat = make.tuple_struct_pat(
@@ -141,7 +143,7 @@ fn expand_tuple_struct_rest_pattern(
.chain(fields[prefix_count..fields.len() - suffix_count].iter().map(|f| {
gen_unnamed_pat(
ctx,
&make,
make,
&mut name_gen,
&f.ty(ctx.db()).to_type(ctx.sema.db),
f.index(),
@@ -151,8 +153,6 @@ fn expand_tuple_struct_rest_pattern(
);
editor.replace(pat.syntax(), new_pat.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -200,24 +200,21 @@ fn expand_tuple_rest_pattern(
"Fill tuple fields",
rest_pat.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(rest_pat.syntax());
let editor = builder.make_editor(rest_pat.syntax());
let make = editor.make();
let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax()));
let new_pat = make.tuple_pat(
pat.fields()
.take(prefix_count)
.chain(fields[prefix_count..len - suffix_count].iter().enumerate().map(
|(index, ty)| {
gen_unnamed_pat(ctx, &make, &mut name_gen, ty, prefix_count + index)
gen_unnamed_pat(ctx, make, &mut name_gen, ty, prefix_count + index)
},
))
.chain(pat.fields().skip(prefix_count + 1)),
);
editor.replace(pat.syntax(), new_pat.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -264,8 +261,8 @@ fn expand_slice_rest_pattern(
"Fill slice fields",
rest_pat.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(rest_pat.syntax());
let editor = builder.make_editor(rest_pat.syntax());
let make = editor.make();
let mut name_gen = NameGenerator::new_from_scope_locals(ctx.sema.scope(pat.syntax()));
let new_pat = make.slice_pat(
@@ -273,14 +270,12 @@ fn expand_slice_rest_pattern(
.take(prefix_count)
.chain(
(prefix_count..len - suffix_count)
.map(|index| gen_unnamed_pat(ctx, &make, &mut name_gen, &ty, index)),
.map(|index| gen_unnamed_pat(ctx, make, &mut name_gen, &ty, index)),
)
.chain(pat.pats().skip(prefix_count + 1)),
);
editor.replace(pat.syntax(), new_pat.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -8,7 +8,7 @@
AstNode, AstToken, NodeOrToken,
SyntaxKind::WHITESPACE,
SyntaxToken, T,
ast::{self, TokenTree, syntax_factory::SyntaxFactory},
ast::{self, TokenTree},
};
// Assist: extract_expressions_from_format_string
@@ -57,7 +57,8 @@ pub(crate) fn extract_expressions_from_format_string(
"Extract format expressions",
tt.syntax().text_range(),
|edit| {
let make = SyntaxFactory::without_mappings();
let editor = edit.make_editor(tt.syntax());
let make = editor.make();
// Extract existing arguments in macro
let mut raw_tokens = tt.token_trees_and_tokens().skip(1).collect_vec();
let format_string_index = format_str_index(&raw_tokens, &fmt_string);
@@ -110,7 +111,7 @@ pub(crate) fn extract_expressions_from_format_string(
Arg::Expr(s) => {
// insert arg
let expr = ast::Expr::parse(&s, ctx.edition()).syntax_node();
let mut expr_tt = utils::tt_from_syntax(expr, &make);
let mut expr_tt = utils::tt_from_syntax(expr, make);
new_tt_bits.append(&mut expr_tt);
}
Arg::Placeholder => {
@@ -131,7 +132,6 @@ pub(crate) fn extract_expressions_from_format_string(
// Insert new args
let new_tt = make.token_tree(tt_delimiter, new_tt_bits);
let mut editor = edit.make_editor(tt.syntax());
editor.replace(tt.syntax(), new_tt.syntax());
if let Some(cap) = ctx.config.snippet_cap {
@@ -158,7 +158,6 @@ pub(crate) fn extract_expressions_from_format_string(
editor.add_annotation(literal, annotation);
}
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -60,8 +60,8 @@ pub(crate) fn extract_struct_from_enum_variant(
"Extract struct from enum variant",
target,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(variant.syntax());
let editor = builder.make_editor(variant.syntax());
let make = editor.make();
let edition = enum_hir.krate(ctx.db()).edition(ctx.db());
let variant_hir_name = variant_hir.name(ctx.db());
let enum_module_def = ModuleDef::from(enum_hir);
@@ -87,7 +87,7 @@ pub(crate) fn extract_struct_from_enum_variant(
if processed.is_empty() {
continue;
}
let mut file_editor = builder.make_editor(processed[0].0.syntax());
let file_editor = builder.make_editor(processed[0].0.syntax());
processed.into_iter().for_each(|(path, node, import)| {
apply_references(
ctx.config.insert_use,
@@ -95,11 +95,9 @@ pub(crate) fn extract_struct_from_enum_variant(
node,
import,
edition,
&mut file_editor,
&make,
&file_editor,
)
});
file_editor.add_mappings(make.take());
builder.add_file_edits(file_id.file_id(ctx.db()), file_editor);
}
@@ -112,20 +110,12 @@ pub(crate) fn extract_struct_from_enum_variant(
references,
);
processed.into_iter().for_each(|(path, node, import)| {
apply_references(
ctx.config.insert_use,
path,
node,
import,
edition,
&mut editor,
&make,
)
apply_references(ctx.config.insert_use, path, node, import, edition, &editor)
});
}
let generic_params = enum_ast.generic_param_list().and_then(|known_generics| {
extract_generic_params(&make, &known_generics, &field_list)
extract_generic_params(make, &known_generics, &field_list)
});
// resolve GenericArg in field_list to actual type
@@ -148,13 +138,13 @@ pub(crate) fn extract_struct_from_enum_variant(
};
let (comments_for_struct, comments_to_delete) =
collect_variant_comments(&make, variant.syntax());
collect_variant_comments(make, variant.syntax());
for element in &comments_to_delete {
editor.delete(element.clone());
}
let def = create_struct_def(
&make,
make,
variant_name.clone(),
&field_list,
generic_params.clone(),
@@ -173,15 +163,10 @@ pub(crate) fn extract_struct_from_enum_variant(
insert_items.extend(comments_for_struct);
insert_items.push(def.syntax().clone().into());
insert_items.push(make.whitespace(&format!("\n\n{indent}")).into());
editor.insert_all_with_whitespace(
Position::before(enum_ast.syntax()),
insert_items,
&make,
);
editor.insert_all_with_whitespace(Position::before(enum_ast.syntax()), insert_items);
update_variant(&make, &mut editor, &variant, generic_params);
update_variant(&editor, &variant, generic_params);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -340,11 +325,11 @@ fn create_struct_def(
}
fn update_variant(
make: &SyntaxFactory,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
variant: &ast::Variant,
generics: Option<ast::GenericParamList>,
) -> Option<()> {
let make = editor.make();
let name = variant.name()?;
let generic_args = generics
.filter(|generics| generics.generic_params().count() > 0)
@@ -407,17 +392,11 @@ fn apply_references(
node: SyntaxNode,
import: Option<(ImportScope, hir::ModPath)>,
edition: Edition,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
) {
let make = editor.make();
if let Some((scope, path)) = import {
insert_use_with_editor(
&scope,
mod_path_to_ast(&path, edition),
&insert_use_cfg,
editor,
make,
);
insert_use_with_editor(&scope, mod_path_to_ast(&path, edition), &insert_use_cfg, editor);
}
// deep clone to prevent cycle
let path = make.path_from_segments(iter::once(segment.clone()), false);
@@ -2,10 +2,7 @@
use hir::HirDisplay;
use ide_db::syntax_helpers::node_ext::walk_ty;
use syntax::{
ast::{
self, AstNode, HasGenericArgs, HasGenericParams, HasName, edit::IndentLevel,
syntax_factory::SyntaxFactory,
},
ast::{self, AstNode, HasGenericArgs, HasGenericParams, HasName, edit::IndentLevel},
syntax_editor,
};
@@ -56,8 +53,8 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Extract type as type alias",
target,
|builder| {
let mut edit = builder.make_editor(node);
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(node);
let make = editor.make();
let resolved_ty = make.ty(&resolved_ty);
@@ -82,7 +79,7 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
} else {
make.path_segment(make.name_ref("Type"))
};
edit.replace(ty.syntax(), new_ty.syntax());
editor.replace(ty.syntax(), new_ty.syntax());
// Insert new alias
let ty_alias =
@@ -91,11 +88,11 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
if let Some(cap) = ctx.config.snippet_cap
&& let Some(name) = ty_alias.name()
{
edit.add_annotation(name.syntax(), builder.make_tabstop_before(cap));
editor.add_annotation(name.syntax(), builder.make_tabstop_before(cap));
}
let indent = IndentLevel::from_node(node);
edit.insert_all(
editor.insert_all(
syntax_editor::Position::before(node),
vec![
ty_alias.syntax().clone().into(),
@@ -103,7 +100,7 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
],
);
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -9,7 +9,6 @@
ast::{
self, AstNode,
edit::{AstNodeEdit, IndentLevel},
syntax_factory::SyntaxFactory,
},
syntax_editor::{Element, Position},
};
@@ -206,8 +205,8 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
to_replace.clone()
};
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(&place);
let editor = edit.make_editor(&place);
let make = editor.make();
let pat_name = make.name(&var_name);
let name_expr = make.expr_path(make.ident_path(&var_name));
@@ -292,13 +291,11 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
make.block_expr([new_stmt], Some(to_wrap.clone()))
}
// fixup indentation of block
.indent_with_mapping(indent_to, &make);
.indent_with_mapping(indent_to, make);
editor.replace(to_wrap.syntax(), block.syntax());
}
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
edit.rename();
},
@@ -78,7 +78,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
};
acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |builder| {
let mut editor = builder.make_editor(vis_owner.syntax());
let editor = builder.make_editor(vis_owner.syntax());
if let Some(current_visibility) = vis_owner.visibility() {
editor.replace(current_visibility.syntax(), missing_visibility.syntax());
@@ -1,6 +1,6 @@
use syntax::{
SyntaxKind, T,
ast::{self, AstNode, BinExpr, RangeItem, syntax_factory::SyntaxFactory},
ast::{self, AstNode, BinExpr, RangeItem},
syntax_editor::Position,
};
@@ -48,14 +48,13 @@ pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
"Flip binary expression",
op_token.text_range(),
|builder| {
let mut editor = builder.make_editor(&expr.syntax().parent().unwrap());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(&expr.syntax().parent().unwrap());
let make = editor.make();
if let FlipAction::FlipAndReplaceOp(binary_op) = action {
editor.replace(op_token, make.token(binary_op))
};
editor.replace(lhs.syntax(), rhs.syntax());
editor.replace(rhs.syntax(), lhs.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -133,25 +132,25 @@ pub(crate) fn flip_range_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
"Flip range expression",
op.text_range(),
|builder| {
let mut edit = builder.make_editor(range_expr.syntax());
let editor = builder.make_editor(range_expr.syntax());
match (start, end) {
(Some(start), Some(end)) => {
edit.replace(start.syntax(), end.syntax());
edit.replace(end.syntax(), start.syntax());
editor.replace(start.syntax(), end.syntax());
editor.replace(end.syntax(), start.syntax());
}
(Some(start), None) => {
edit.delete(start.syntax());
edit.insert(Position::after(&op), start.syntax());
editor.delete(start.syntax());
editor.insert(Position::after(&op), start.syntax());
}
(None, Some(end)) => {
edit.delete(end.syntax());
edit.insert(Position::before(&op), end.syntax());
editor.delete(end.syntax());
editor.insert(Position::before(&op), end.syntax());
}
(None, None) => (),
}
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -2,7 +2,6 @@
AstNode, Direction, NodeOrToken, SyntaxKind, SyntaxToken, T,
algo::non_trivia_sibling,
ast::{self, syntax_factory::SyntaxFactory},
syntax_editor::SyntaxMapping,
};
use crate::{AssistContext, AssistId, Assists};
@@ -42,14 +41,13 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
let target = comma.text_range();
acc.add(AssistId::refactor_rewrite("flip_comma"), "Flip comma", target, |builder| {
let parent = comma.parent().unwrap();
let mut editor = builder.make_editor(&parent);
let editor = builder.make_editor(&parent);
if let Some(parent) = ast::TokenTree::cast(parent) {
// An attribute. It often contains a path followed by a
// token tree (e.g. `align(2)`), so we have to be smarter.
let (new_tree, mapping) = flip_tree(parent.clone(), comma);
let new_tree = flip_tree(parent.clone(), comma, editor.make());
editor.replace(parent.syntax(), new_tree.syntax());
editor.add_mappings(mapping);
} else {
editor.replace(prev.clone(), next.clone());
editor.replace(next.clone(), prev.clone());
@@ -59,7 +57,7 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
})
}
fn flip_tree(tree: ast::TokenTree, comma: SyntaxToken) -> (ast::TokenTree, SyntaxMapping) {
fn flip_tree(tree: ast::TokenTree, comma: SyntaxToken, make: &SyntaxFactory) -> ast::TokenTree {
let mut tree_iter = tree.token_trees_and_tokens();
let before: Vec<_> =
tree_iter.by_ref().take_while(|it| it.as_token() != Some(&comma)).collect();
@@ -100,10 +98,7 @@ fn flip_tree(tree: ast::TokenTree, comma: SyntaxToken) -> (ast::TokenTree, Synta
&after[next_end..after.len() - 1],
]
.concat();
let make = SyntaxFactory::with_mappings();
let new_token_tree = make.token_tree(tree.left_delimiter_token().unwrap().kind(), result);
(new_token_tree, make.finish_with_mappings())
make.token_tree(tree.left_delimiter_token().unwrap().kind(), result)
}
#[cfg(test)]
@@ -32,7 +32,7 @@ pub(crate) fn flip_or_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
let target = pipe.text_range();
acc.add(AssistId::refactor_rewrite("flip_or_pattern"), "Flip patterns", target, |builder| {
let mut editor = builder.make_editor(parent.syntax());
let editor = builder.make_editor(parent.syntax());
editor.replace(before.clone(), after.clone());
editor.replace(after, before);
builder.add_file_edits(ctx.vfs_file_id(), editor);
@@ -33,7 +33,7 @@ pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
"Flip trait bounds",
target,
|builder| {
let mut editor = builder.make_editor(parent.syntax());
let editor = builder.make_editor(parent.syntax());
editor.replace(before.clone(), after.clone());
editor.replace(after, before);
builder.add_file_edits(ctx.vfs_file_id(), editor);
@@ -73,19 +73,19 @@ pub(crate) fn generate_blanket_trait_impl(
"Generate blanket trait implementation",
name.syntax().text_range(),
|builder| {
let mut editor = builder.make_editor(traitd.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(traitd.syntax());
let make = editor.make();
let namety = make.ty_path(make.path_from_text(&name.text()));
let trait_where_clause = traitd.where_clause().map(|it| it.reset_indent());
let bounds = traitd.type_bound_list().and_then(|list| exclude_sized(&make, list));
let bounds = traitd.type_bound_list().and_then(|list| exclude_sized(make, list));
let is_unsafe = traitd.unsafe_token().is_some();
let thisname = this_name(&make, &traitd);
let thisname = this_name(make, &traitd);
let thisty = make.ty_path(make.path_from_text(&thisname.text()));
let indent = traitd.indent_level();
let gendecl = make.generic_param_list([GenericParam::TypeParam(make.type_param(
thisname.clone(),
apply_sized(&make, has_sized(&traitd, &ctx.sema), bounds),
apply_sized(make, has_sized(&traitd, &ctx.sema), bounds),
))]);
let trait_gen_args =
@@ -107,12 +107,11 @@ pub(crate) fn generate_blanket_trait_impl(
);
if let Some(trait_assoc_list) = traitd.assoc_item_list() {
let assoc_item_list =
impl_.get_or_create_assoc_item_list_with_editor(&mut editor, &make);
let assoc_item_list = impl_.get_or_create_assoc_item_list_with_editor(&editor);
for item in trait_assoc_list.assoc_items() {
let item = match item {
ast::AssocItem::Fn(method) if method.body().is_none() => {
todo_fn(&make, &method, ctx.config).into()
todo_fn(make, &method, ctx.config).into()
}
ast::AssocItem::Const(_) | ast::AssocItem::TypeAlias(_) => item,
_ => continue,
@@ -136,8 +135,6 @@ pub(crate) fn generate_blanket_trait_impl(
{
builder.add_tabstop_before(cap, self_ty);
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -73,12 +73,12 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
"Generate a Default impl from a new fn",
target,
move |builder| {
let make = SyntaxFactory::without_mappings();
let default_impl = generate_default_impl(&make, &impl_, self_ty);
let editor = builder.make_editor(impl_.syntax());
let make = editor.make();
let default_impl = generate_default_impl(make, &impl_, self_ty);
let indent = IndentLevel::from_node(impl_.syntax());
let default_impl = default_impl.indent(indent);
let mut editor = builder.make_editor(impl_.syntax());
editor.insert_all(
Position::after(impl_.syntax()),
vec![
@@ -4,7 +4,6 @@
ast::{
self, AstNode, HasGenericParams, HasName, HasVisibility as _,
edit::{AstNodeEdit, IndentLevel},
syntax_factory::SyntaxFactory,
},
syntax_editor::Position,
};
@@ -107,8 +106,10 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
format!("Generate delegate for `{field_name}.{name}()`",),
target,
|edit| {
let make = SyntaxFactory::without_mappings();
let field = make
let editor = edit.make_editor(strukt.syntax());
let make = editor.make();
let field = editor
.make()
.field_from_idents(["self", &field_name])
.expect("always be a valid expression");
// Create the function
@@ -145,17 +146,19 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
// compute the `body`
let arg_list = method_source
.param_list()
.map(|v| convert_param_list_to_arg_list(v, &make))
.map(|v| convert_param_list_to_arg_list(v, make))
.unwrap_or_else(|| make.arg_list([]));
let tail_expr = make.expr_method_call(field, make.name_ref(&name), arg_list).into();
let tail_expr =
editor.make().expr_method_call(field, make.name_ref(&name), arg_list).into();
let tail_expr_finished =
if is_async { make.expr_await(tail_expr).into() } else { tail_expr };
let body = make.block_expr([], Some(tail_expr_finished));
let ret_type = method_source.ret_type();
let f = make
let f = editor
.make()
.fn_(
None,
vis,
@@ -173,12 +176,11 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
.indent(IndentLevel(1));
let item = ast::AssocItem::Fn(f.clone());
let mut editor = edit.make_editor(strukt.syntax());
let fn_: Option<ast::AssocItem> = match impl_def {
Some(impl_def) => match impl_def.assoc_item_list() {
Some(assoc_item_list) => {
let item = item.indent(IndentLevel::from_node(impl_def.syntax()));
assoc_item_list.add_items(&mut editor, vec![item.clone()]);
assoc_item_list.add_items(&editor, vec![item.clone()]);
Some(item)
}
None => {
@@ -229,7 +231,6 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
let tabstop = edit.make_tabstop_before(cap);
editor.add_annotation(fn_.syntax(), tabstop);
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)?;
@@ -494,7 +494,7 @@ fn remove_instantiated_params(
}
}
fn remove_useless_where_clauses(editor: &mut SyntaxEditor, delegate: &ast::Impl) {
fn remove_useless_where_clauses(editor: &SyntaxEditor, delegate: &ast::Impl) {
let Some(wc) = delegate.where_clause() else {
return;
};
@@ -563,7 +563,7 @@ fn finalize_delegate(
return Some(delegate.clone());
}
let (mut editor, delegate) = SyntaxEditor::with_ast_node(delegate);
let (editor, delegate) = SyntaxEditor::with_ast_node(delegate);
// 1. Replace assoc_item_list if we have new items
if let Some(items) = assoc_items
@@ -577,7 +577,7 @@ fn finalize_delegate(
// 2. Remove useless where clauses
if remove_where_clauses {
remove_useless_where_clauses(&mut editor, &delegate);
remove_useless_where_clauses(&editor, &delegate);
}
ast::Impl::cast(editor.finish().new_root().clone())
@@ -2,7 +2,7 @@
use ide_db::{FileId, RootDatabase, famous_defs::FamousDefs};
use syntax::{
Edition,
ast::{self, AstNode, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory},
ast::{self, AstNode, HasName, edit::AstNodeEdit},
syntax_editor::Position,
};
@@ -138,7 +138,8 @@ fn generate_edit(
trait_path: ModPath,
edition: Edition,
) {
let make = SyntaxFactory::with_mappings();
let editor = edit.make_editor(strukt.syntax());
let make = editor.make();
let strukt_adt = ast::Adt::Struct(strukt.clone());
let trait_ty = make.ty(&trait_path.display(db, edition).to_string());
@@ -150,7 +151,8 @@ fn generate_edit(
make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), false);
let field_expr = make.expr_field(make.expr_path(make.ident_path("self")), field_name);
let body = make.block_expr([], Some(make.expr_ref(field_expr.into(), false)));
let fn_ = make
let fn_ = editor
.make()
.fn_(
[],
None,
@@ -173,7 +175,8 @@ fn generate_edit(
make.ty_ref(make.ty_path(make.path_from_text("Self::Target")).into(), true);
let field_expr = make.expr_field(make.expr_path(make.ident_path("self")), field_name);
let body = make.block_expr([], Some(make.expr_ref(field_expr.into(), true)));
let fn_ = make
let fn_ = editor
.make()
.fn_(
[],
None,
@@ -195,15 +198,12 @@ fn generate_edit(
let body = make.assoc_item_list(assoc_items);
let indent = strukt.indent_level();
let impl_ = generate_trait_impl_intransitive_with_item(&make, &strukt_adt, trait_ty, body)
let impl_ = generate_trait_impl_intransitive_with_item(make, &strukt_adt, trait_ty, body)
.indent(indent);
let mut editor = edit.make_editor(strukt.syntax());
editor.insert_all(
Position::after(strukt.syntax()),
vec![make.whitespace(&format!("\n\n{indent}")).into(), impl_.syntax().clone().into()],
);
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(file_id, editor);
}
@@ -1,7 +1,7 @@
use syntax::{
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
T,
ast::{self, AstNode, HasAttrs, edit::IndentLevel, syntax_factory::SyntaxFactory},
ast::{self, AstNode, HasAttrs, edit::IndentLevel},
syntax_editor::{Element, Position},
};
@@ -42,17 +42,15 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
};
acc.add(AssistId::generate("generate_derive"), "Add `#[derive]`", target, |edit| {
let make = SyntaxFactory::without_mappings();
match derive_attr {
None => {
let editor = edit.make_editor(nominal.syntax());
let make = editor.make();
let derive =
make.attr_outer(make.meta_token_tree(
make.ident_path("derive"),
make.token_tree(T!['('], vec![]),
));
let mut editor = edit.make_editor(nominal.syntax());
let indent = IndentLevel::from_node(nominal.syntax());
let after_attrs_and_comments = nominal
.syntax()
@@ -59,12 +59,12 @@ pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext<'_>)
let InRealFile { file_id, value: enum_node } = e.source(db)?.original_ast_node_rooted(db)?;
acc.add(AssistId::generate("generate_enum_variant"), "Generate variant", target, |builder| {
let mut editor = builder.make_editor(enum_node.syntax());
let make = SyntaxFactory::with_mappings();
let field_list = parent.make_field_list(ctx, &make);
let editor = builder.make_editor(enum_node.syntax());
let make = editor.make();
let field_list = parent.make_field_list(ctx, make);
let variant = make.variant(None, make.name(&name_ref.text()), field_list, None);
if let Some(it) = enum_node.variant_list() {
it.add_variant(&mut editor, &variant);
it.add_variant(&editor, &variant);
}
builder.add_file_edits(file_id.file_id(ctx.db()), editor);
})
@@ -2,7 +2,7 @@
use ide_db::assists::{AssistId, GroupLabel};
use syntax::{
AstNode,
ast::{self, HasGenericParams, HasName, edit::IndentLevel, syntax_factory::SyntaxFactory},
ast::{self, HasGenericParams, HasName, edit::IndentLevel},
syntax_editor,
};
@@ -55,9 +55,8 @@ pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>)
style.label(),
func_node.syntax().text_range(),
|builder| {
let mut edit = builder.make_editor(func);
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(func);
let make = editor.make();
let alias_name = format!("{}Fn", stdx::to_camel_case(&name.to_string()));
let mut fn_params_vec = Vec::new();
@@ -104,7 +103,7 @@ pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>)
);
let indent = IndentLevel::from_node(insertion_node);
edit.insert_all(
editor.insert_all(
syntax_editor::Position::before(insertion_node),
vec![
ty_alias.syntax().clone().into(),
@@ -115,10 +114,10 @@ pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>)
if let Some(cap) = ctx.config.snippet_cap
&& let Some(name) = ty_alias.name()
{
edit.add_annotation(name.syntax(), builder.make_placeholder_snippet(cap));
editor.add_annotation(name.syntax(), builder.make_placeholder_snippet(cap));
}
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
}
@@ -40,19 +40,18 @@ pub(crate) fn generate_from_impl_for_enum(
"Generate `From` impl for this enum variant(s)",
target,
|edit| {
let make = SyntaxFactory::with_mappings();
let editor = edit.make_editor(adt.syntax());
let make = editor.make();
let indent = adt.indent_level();
let mut elements = Vec::new();
for variant_info in variants {
let impl_ = build_from_impl(&make, &adt, variant_info).indent(indent);
let impl_ = build_from_impl(make, &adt, variant_info).indent(indent);
elements.push(make.whitespace(&format!("\n\n{indent}")).into());
elements.push(impl_.syntax().clone().into());
}
let mut editor = edit.make_editor(adt.syntax());
editor.insert_all(Position::after(adt.syntax()), elements);
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(file_id, editor);
},
)
@@ -410,35 +410,37 @@ fn parse_record_field(
Some(RecordFieldInfo { field_name, field_ty, fn_name, target })
}
fn items(
ctx: &AssistContext<'_>,
info_of_record_fields: Vec<RecordFieldInfo>,
assist_info: &AssistInfo,
make: &SyntaxFactory,
) -> Vec<ast::AssocItem> {
info_of_record_fields
.iter()
.map(|record_field_info| {
let method = match assist_info.assist_type {
AssistType::Set => generate_setter_from_info(assist_info, record_field_info, make),
_ => generate_getter_from_info(ctx, assist_info, record_field_info, make),
};
let new_fn = method;
let new_fn = new_fn.indent(1.into());
new_fn.into()
})
.collect()
}
fn build_source_change(
builder: &mut SourceChangeBuilder,
ctx: &AssistContext<'_>,
info_of_record_fields: Vec<RecordFieldInfo>,
assist_info: AssistInfo,
) {
let syntax_factory = SyntaxFactory::without_mappings();
let items: Vec<ast::AssocItem> = info_of_record_fields
.iter()
.map(|record_field_info| {
let method = match assist_info.assist_type {
AssistType::Set => {
generate_setter_from_info(&assist_info, record_field_info, &syntax_factory)
}
_ => {
generate_getter_from_info(ctx, &assist_info, record_field_info, &syntax_factory)
}
};
let new_fn = method;
let new_fn = new_fn.indent(1.into());
new_fn.into()
})
.collect();
if let Some(impl_def) = &assist_info.impl_def {
// We have an existing impl to add to
let mut editor = builder.make_editor(impl_def.syntax());
impl_def.assoc_item_list().unwrap().add_items(&mut editor, items.clone());
let editor = builder.make_editor(impl_def.syntax());
let items = items(ctx, info_of_record_fields, &assist_info, editor.make());
impl_def.assoc_item_list().unwrap().add_items(&editor, items.clone());
if let Some(cap) = ctx.config.snippet_cap
&& let Some(ast::AssocItem::Fn(fn_)) = items.last()
@@ -451,22 +453,26 @@ fn build_source_change(
builder.add_file_edits(ctx.vfs_file_id(), editor);
return;
}
let editor = builder.make_editor(assist_info.strukt.syntax());
let make = editor.make();
let items = items(ctx, info_of_record_fields, &assist_info, make);
let ty_params = assist_info.strukt.generic_param_list();
let ty_args = ty_params.as_ref().map(|it| it.to_generic_args());
let impl_def = syntax_factory.impl_(
let impl_def = make.impl_(
None,
ty_params,
ty_args,
syntax_factory
.ty_path(syntax_factory.ident_path(&assist_info.strukt.name().unwrap().to_string()))
editor
.make()
.ty_path(make.ident_path(&assist_info.strukt.name().unwrap().to_string()))
.into(),
None,
Some(syntax_factory.assoc_item_list(items)),
Some(make.assoc_item_list(items)),
);
let mut editor = builder.make_editor(assist_info.strukt.syntax());
editor.insert_all(
Position::after(assist_info.strukt.syntax()),
vec![syntax_factory.whitespace("\n\n").into(), impl_def.syntax().clone().into()],
vec![make.whitespace("\n\n").into(), impl_def.syntax().clone().into()],
);
if let Some(cap) = ctx.config.snippet_cap
@@ -1,7 +1,5 @@
use syntax::{
ast::{
self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit, syntax_factory::SyntaxFactory,
},
ast::{self, AstNode, HasGenericParams, HasName, edit::AstNodeEdit},
syntax_editor::{Position, SyntaxEditor},
};
@@ -13,12 +11,8 @@
},
};
fn insert_impl(
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
impl_: &ast::Impl,
nominal: &impl AstNodeEdit,
) -> ast::Impl {
fn insert_impl(editor: &SyntaxEditor, impl_: &ast::Impl, nominal: &impl AstNodeEdit) -> ast::Impl {
let make = editor.make();
let indent = nominal.indent_level();
let impl_ = impl_.indent(indent);
@@ -65,13 +59,11 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
format!("Generate impl for `{name}`"),
target,
|edit| {
let make = SyntaxFactory::with_mappings();
// Generate the impl
let impl_ = generate_impl_with_factory(&make, &nominal);
let editor = edit.make_editor(nominal.syntax());
let make = editor.make();
let impl_ = generate_impl_with_factory(make, &nominal);
let mut editor = edit.make_editor(nominal.syntax());
let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
let impl_ = insert_impl(&editor, &impl_, &nominal);
// Add a tabstop after the left curly brace
if let Some(cap) = ctx.config.snippet_cap
&& let Some(l_curly) = impl_.assoc_item_list().and_then(|it| it.l_curly_token())
@@ -79,8 +71,6 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
let tabstop = edit.make_tabstop_after(cap);
editor.add_annotation(l_curly, tabstop);
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -117,13 +107,10 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate trait impl for `{name}`"),
target,
|edit| {
let make = SyntaxFactory::with_mappings();
// Generate the impl
let impl_ = generate_trait_impl_intransitive(&make, &nominal, make.ty_placeholder());
let mut editor = edit.make_editor(nominal.syntax());
let impl_ = insert_impl(&mut editor, &make, &impl_, &nominal);
let editor = edit.make_editor(nominal.syntax());
let make = editor.make();
let impl_ = generate_trait_impl_intransitive(make, &nominal, make.ty_placeholder());
let impl_ = insert_impl(&editor, &impl_, &nominal);
// Make the trait type a placeholder snippet
if let Some(cap) = ctx.config.snippet_cap {
if let Some(trait_) = impl_.trait_() {
@@ -136,8 +123,6 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
editor.add_annotation(l_curly, tabstop);
}
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -176,8 +161,8 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Generate `{name}` impl for type"),
target,
|edit| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(trait_.syntax());
let editor = edit.make_editor(trait_.syntax());
let make = editor.make();
let holder_arg = ast::GenericArg::TypeArg(make.type_arg(make.ty_placeholder()));
let missing_items = utils::filter_assoc_items(
@@ -188,7 +173,9 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
);
let trait_gen_args = trait_.generic_param_list().map(|list| {
make.generic_arg_list(list.generic_params().map(|_| holder_arg.clone()), false)
editor
.make()
.generic_arg_list(list.generic_params().map(|_| holder_arg.clone()), false)
});
let make_impl_ = |body| {
@@ -213,7 +200,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
} else {
let impl_ = make_impl_(None);
let assoc_items = add_trait_assoc_items_to_impl(
&make,
make,
&ctx.sema,
ctx.config,
&missing_items,
@@ -225,8 +212,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_>) ->
make_impl_(Some(assoc_item_list))
};
let impl_ = insert_impl(&mut editor, &make, &impl_, &trait_);
editor.add_mappings(make.finish_with_mappings());
let impl_ = insert_impl(&editor, &impl_, &trait_);
if let Some(cap) = ctx.config.snippet_cap {
if let Some(generics) = impl_.trait_().and_then(|it| it.generic_arg_list()) {
@@ -67,10 +67,9 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>
format!("Generate `{trait_new}` impl from this `{trait_name}` trait"),
target,
|edit| {
let (mut editor, impl_clone) = SyntaxEditor::with_ast_node(&impl_def.reset_indent());
let factory = SyntaxFactory::without_mappings();
let (editor, impl_clone) = SyntaxEditor::with_ast_node(&impl_def.reset_indent());
apply_generate_mut_impl(&mut editor, &factory, &impl_clone, trait_new);
apply_generate_mut_impl(&editor, &impl_clone, trait_new);
let new_root = editor.finish();
let new_root = new_root.new_root();
@@ -79,12 +78,13 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>
let new_impl = new_impl.indent(indent);
let mut editor = edit.make_editor(impl_def.syntax());
let editor = edit.make_editor(impl_def.syntax());
let make = editor.make();
editor.insert_all(
Position::before(impl_def.syntax()),
vec![
new_impl.syntax().syntax_element(),
factory.whitespace(&format!("\n\n{indent}")).syntax_element(),
make.whitespace(&format!("\n\n{indent}")).syntax_element(),
],
);
@@ -98,7 +98,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>
)
}
fn delete_with_trivia(editor: &mut SyntaxEditor, node: &SyntaxNode) {
fn delete_with_trivia(editor: &SyntaxEditor, node: &SyntaxNode) {
let mut end: SyntaxElement = node.clone().into();
if let Some(next) = node.next_sibling_or_token()
@@ -112,23 +112,23 @@ fn delete_with_trivia(editor: &mut SyntaxEditor, node: &SyntaxNode) {
}
fn apply_generate_mut_impl(
editor: &mut SyntaxEditor,
factory: &SyntaxFactory,
editor: &SyntaxEditor,
impl_def: &ast::Impl,
trait_new: &str,
) -> Option<()> {
let make = editor.make();
let path =
impl_def.trait_().and_then(|t| t.syntax().descendants().find_map(ast::Path::cast))?;
let seg = path.segment()?;
let name_ref = seg.name_ref()?;
let new_name_ref = factory.name_ref(trait_new);
let new_name_ref = make.name_ref(trait_new);
editor.replace(name_ref.syntax(), new_name_ref.syntax());
if let Some((name, new_name)) =
impl_def.syntax().descendants().filter_map(ast::Name::cast).find_map(process_method_name)
{
let new_name_node = factory.name(new_name);
let new_name_node = make.name(new_name);
editor.replace(name.syntax(), new_name_node.syntax());
}
@@ -137,14 +137,14 @@ fn apply_generate_mut_impl(
}
if let Some(self_param) = impl_def.syntax().descendants().find_map(ast::SelfParam::cast) {
let mut_self = factory.mut_self_param();
let mut_self = make.mut_self_param();
editor.replace(self_param.syntax(), mut_self.syntax());
}
if let Some(ret_type) = impl_def.syntax().descendants().find_map(ast::RetType::cast)
&& let Some(new_ty) = process_ret_type(factory, &ret_type)
&& let Some(new_ty) = process_ret_type(make, &ret_type)
{
let new_ret = factory.ret_type(new_ty);
let new_ret = make.ret_type(new_ty);
editor.replace(ret_type.syntax(), new_ret.syntax())
}
@@ -154,13 +154,14 @@ fn apply_generate_mut_impl(
_ => None,
})
}) {
process_ref_mut(editor, factory, &fn_);
process_ref_mut(editor, &fn_);
}
Some(())
}
fn process_ref_mut(editor: &mut SyntaxEditor, factory: &SyntaxFactory, fn_: &ast::Fn) {
fn process_ref_mut(editor: &SyntaxEditor, fn_: &ast::Fn) {
let make = editor.make();
let Some(expr) = fn_.body().and_then(|b| b.tail_expr()) else { return };
let ast::Expr::RefExpr(ref_expr) = expr else { return };
@@ -171,8 +172,8 @@ fn process_ref_mut(editor: &mut SyntaxEditor, factory: &SyntaxFactory, fn_: &ast
let Some(amp) = ref_expr.amp_token() else { return };
let mut_kw = factory.token(T![mut]);
let space = factory.whitespace(" ");
let mut_kw = make.token(T![mut]);
let space = make.whitespace(" ");
editor.insert(Position::after(amp.clone()), space.syntax_element());
editor.insert(Position::after(amp), mut_kw.syntax_element());
@@ -3,10 +3,7 @@
use_trivial_constructor::use_trivial_constructor,
};
use syntax::{
ast::{
self, AstNode, HasName, HasVisibility, StructKind, edit::AstNodeEdit,
syntax_factory::SyntaxFactory,
},
ast::{self, AstNode, HasName, HasVisibility, StructKind, edit::AstNodeEdit},
syntax_editor::Position,
};
@@ -38,11 +35,9 @@
// ```
pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
let make = SyntaxFactory::without_mappings();
let field_list = match strukt.kind() {
let field_list: Vec<(String, ast::Type)> = match strukt.kind() {
StructKind::Record(named) => {
named.fields().filter_map(|f| Some((f.name()?, f.ty()?))).collect::<Vec<_>>()
named.fields().filter_map(|f| Some((f.name()?.to_string(), f.ty()?))).collect()
}
StructKind::Tuple(tuple) => {
let mut name_generator = NameGenerator::default();
@@ -56,12 +51,12 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
ctx.db(),
ctx.edition(),
) {
Some(name) => name,
None => name_generator.suggest_name(&format!("_{i}")),
Some(name) => name.to_string(),
None => name_generator.suggest_name(&format!("_{i}")).to_string(),
};
Some((make.name(name.as_str()), f.ty()?))
Some((name, ty))
})
.collect::<Vec<_>>()
.collect()
}
StructKind::Unit => return None,
};
@@ -74,7 +69,9 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
let target = strukt.syntax().text_range();
acc.add(AssistId::generate("generate_new"), "Generate `new`", target, |builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(strukt.syntax());
let make = editor.make();
let trivial_constructors = field_list
.iter()
.map(|(name, ty)| {
@@ -100,13 +97,13 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
edition,
)?;
Some((make.name_ref(&name.text()), Some(expr)))
Some((make.name_ref(name), Some(expr)))
})
.collect::<Vec<_>>();
let params = field_list.iter().enumerate().filter_map(|(i, (name, ty))| {
if trivial_constructors[i].is_none() {
Some(make.param(make.ident_pat(false, false, name.clone()).into(), ty.clone()))
Some(make.param(make.ident_pat(false, false, make.name(name)).into(), ty.clone()))
} else {
None
}
@@ -117,7 +114,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
if let Some(constructor) = trivial_constructors[i].clone() {
constructor
} else {
(make.name_ref(&name.text()), None)
(make.name_ref(name), None)
}
});
@@ -141,7 +138,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
let ret_type = make.ret_type(make.ty_path(make.ident_path("Self")).into());
let fn_ = make
let fn_ = editor
.make()
.fn_(
[],
strukt.visibility(),
@@ -158,8 +156,6 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
)
.indent(1.into());
let mut editor = builder.make_editor(strukt.syntax());
// Get the node for set annotation
let contain_fn = if let Some(impl_def) = impl_def {
let fn_ = fn_.indent(impl_def.indent_level());
@@ -169,7 +165,10 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
editor.insert_all(
Position::after(l_curly),
vec![
make.whitespace(&format!("\n{}", impl_def.indent_level() + 1)).into(),
editor
.make()
.whitespace(&format!("\n{}", impl_def.indent_level() + 1))
.into(),
fn_.syntax().clone().into(),
make.whitespace("\n").into(),
],
@@ -185,7 +184,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
let indent_level = strukt.indent_level();
let list = make.assoc_item_list([ast::AssocItem::Fn(fn_)]);
let impl_def =
generate_impl_with_item(&make, &ast::Adt::Struct(strukt.clone()), Some(list))
generate_impl_with_item(make, &ast::Adt::Struct(strukt.clone()), Some(list))
.indent(strukt.indent_level());
// Insert it after the adt
@@ -235,8 +234,6 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
editor.add_annotation(name.syntax(), tabstop_before);
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
@@ -80,8 +80,8 @@ pub(crate) fn generate_single_field_struct_from(
"Generate single field `From`",
strukt.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(strukt.syntax());
let editor = builder.make_editor(strukt.syntax());
let make = editor.make();
let indent = strukt.indent_level();
let ty_where_clause = strukt.where_clause();
@@ -95,10 +95,11 @@ pub(crate) fn generate_single_field_struct_from(
let ty = make.ty(&strukt_name.text());
let constructor =
make_adt_constructor(names.as_deref(), constructors, &main_field_name, &make);
make_adt_constructor(names.as_deref(), constructors, &main_field_name, make);
let body = make.block_expr([], Some(constructor));
let fn_ = make
let fn_ = editor
.make()
.fn_(
[],
None,
@@ -119,7 +120,7 @@ pub(crate) fn generate_single_field_struct_from(
false,
false,
)
.indent_with_mapping(1.into(), &make);
.indent_with_mapping(1.into(), make);
let cfg_attrs =
strukt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_))));
@@ -139,13 +140,12 @@ pub(crate) fn generate_single_field_struct_from(
None,
);
let (mut impl_editor, impl_root) = SyntaxEditor::with_ast_node(&impl_);
let assoc_list =
impl_root.get_or_create_assoc_item_list_with_editor(&mut impl_editor, &make);
assoc_list.add_items(&mut impl_editor, vec![fn_.into()]);
let (impl_editor, impl_root) = SyntaxEditor::with_ast_node(&impl_);
let assoc_list = impl_root.get_or_create_assoc_item_list_with_editor(&impl_editor);
assoc_list.add_items(&impl_editor, vec![fn_.into()]);
let impl_ = ast::Impl::cast(impl_editor.finish().new_root().clone())
.unwrap()
.indent_with_mapping(indent, &make);
.indent_with_mapping(indent, make);
editor.insert_all(
Position::after(strukt.syntax()),
@@ -154,8 +154,6 @@ pub(crate) fn generate_single_field_struct_from(
impl_.syntax().clone().into(),
],
);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -4,7 +4,6 @@
AstNode, AstToken, SyntaxKind, T,
ast::{
self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make,
syntax_factory::SyntaxFactory,
},
syntax_editor::{Position, SyntaxEditor},
};
@@ -99,18 +98,19 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
impl_ast.syntax().text_range(),
|builder| {
let trait_items: ast::AssocItemList = {
let (mut trait_items_editor, trait_items) =
let (trait_items_editor, trait_items) =
SyntaxEditor::with_ast_node(&impl_assoc_items);
trait_items.assoc_items().for_each(|item| {
strip_body(&mut trait_items_editor, &item);
remove_items_visibility(&mut trait_items_editor, &item);
strip_body(&trait_items_editor, &item);
remove_items_visibility(&trait_items_editor, &item);
});
ast::AssocItemList::cast(trait_items_editor.finish().new_root().clone()).unwrap()
};
let factory = SyntaxFactory::with_mappings();
let trait_ast = factory.trait_(
let editor = builder.make_editor(impl_ast.syntax());
let make = editor.make();
let trait_ast = make.trait_(
false,
&trait_name(&impl_assoc_items).text(),
impl_ast.generic_param_list(),
@@ -119,7 +119,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
);
let trait_name = trait_ast.name().expect("new trait should have a name");
let trait_name_ref = factory.name_ref(&trait_name.to_string());
let trait_name_ref = make.name_ref(&trait_name.to_string());
// Change `impl Foo` to `impl NewTrait for Foo`
let mut elements = vec![
@@ -134,10 +134,9 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
elements.insert(1, gen_args.syntax().clone().into());
}
let mut editor = builder.make_editor(impl_ast.syntax());
impl_assoc_items.assoc_items().for_each(|item| {
remove_items_visibility(&mut editor, &item);
remove_doc_comments(&mut editor, &item);
remove_items_visibility(&editor, &item);
remove_doc_comments(&editor, &item);
});
editor.insert_all(Position::before(impl_name.syntax()), elements);
@@ -157,8 +156,6 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
editor.add_annotation(trait_name.syntax(), placeholder);
editor.add_annotation(trait_name_ref.syntax(), placeholder);
}
editor.add_mappings(factory.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -179,7 +176,7 @@ fn trait_name(items: &ast::AssocItemList) -> ast::Name {
}
/// `E0449` Trait items always share the visibility of their trait
fn remove_items_visibility(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
fn remove_items_visibility(editor: &SyntaxEditor, item: &ast::AssocItem) {
if let Some(has_vis) = ast::AnyHasVisibility::cast(item.syntax().clone()) {
if let Some(vis) = has_vis.visibility()
&& let Some(token) = vis.syntax().next_sibling_or_token()
@@ -193,7 +190,7 @@ fn remove_items_visibility(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
}
}
fn remove_doc_comments(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
fn remove_doc_comments(editor: &SyntaxEditor, item: &ast::AssocItem) {
for doc in item.doc_comments() {
if let Some(next) = doc.syntax().next_token()
&& next.kind() == SyntaxKind::WHITESPACE
@@ -204,7 +201,7 @@ fn remove_doc_comments(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
}
}
fn strip_body(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
fn strip_body(editor: &SyntaxEditor, item: &ast::AssocItem) {
if let ast::AssocItem::Fn(f) = item
&& let Some(body) = f.body()
{
@@ -7,7 +7,7 @@
};
use syntax::{
Direction, TextRange,
ast::{self, AstNode, AstToken, HasName, syntax_factory::SyntaxFactory},
ast::{self, AstNode, AstToken, HasName},
syntax_editor::{Element, SyntaxEditor},
};
@@ -83,7 +83,8 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
"Inline variable",
target.text_range(),
move |builder| {
let mut editor = builder.make_editor(&target);
let editor = builder.make_editor(&target);
let make = editor.make();
if delete_let {
editor.delete(let_stmt.syntax());
@@ -91,15 +92,13 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
&& let Some(op_token) = bin_expr.op_token()
{
editor.delete(&op_token);
remove_whitespace(op_token, Direction::Prev, &mut editor);
remove_whitespace(let_stmt.syntax(), Direction::Prev, &mut editor);
remove_whitespace(op_token, Direction::Prev, &editor);
remove_whitespace(let_stmt.syntax(), Direction::Prev, &editor);
} else {
remove_whitespace(let_stmt.syntax(), Direction::Next, &mut editor);
remove_whitespace(let_stmt.syntax(), Direction::Next, &editor);
}
}
let make = SyntaxFactory::with_mappings();
for (name, should_wrap) in wrap_in_parens {
let replacement = if should_wrap {
make.expr_paren(initializer_expr.clone()).into()
@@ -115,8 +114,6 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
editor.replace(name.syntax(), replacement.syntax());
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -204,7 +201,7 @@ fn inline_usage(
Some(InlineData { let_stmt, delete_let, target: ast::NameOrNameRef::NameRef(name), references })
}
fn remove_whitespace(elem: impl Element, dir: Direction, editor: &mut SyntaxEditor) {
fn remove_whitespace(elem: impl Element, dir: Direction, editor: &SyntaxEditor) {
let token = match elem.syntax_element() {
syntax::NodeOrToken::Node(node) => match dir {
Direction::Next => node.last_token(),
@@ -70,7 +70,7 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| {
let source = ctx.sema.parse(file_id);
let mut editor = builder.make_editor(source.syntax());
let editor = builder.make_editor(source.syntax());
let (path_types, path_type_uses) =
split_refs_and_uses(builder, refs, |path_type| {
@@ -101,7 +101,7 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
inline_refs_for_file(file_id, refs);
}
if !definition_deleted {
let mut editor = builder.make_editor(ast_alias.syntax());
let editor = builder.make_editor(ast_alias.syntax());
editor.delete(ast_alias.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor)
}
@@ -156,7 +156,7 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
"Inline type alias",
alias_instance.syntax().text_range(),
|builder| {
let mut editor = builder.make_editor(alias_instance.syntax());
let editor = builder.make_editor(alias_instance.syntax());
let replace = replacement.replace_generic(&concrete_type);
editor.replace(alias_instance.syntax(), replace);
builder.add_file_edits(ctx.vfs_file_id(), editor);
@@ -312,8 +312,8 @@ fn create_replacement(
const_and_type_map: &ConstAndTypeMap,
concrete_type: &ast::Type,
) -> SyntaxNode {
let (mut editor, updated_concrete_type) = SyntaxEditor::new(concrete_type.syntax().clone());
let (editor, updated_concrete_type) = SyntaxEditor::new(concrete_type.syntax().clone());
let make = editor.make();
let mut replacements: Vec<(SyntaxNode, SyntaxNode)> = Vec::new();
let mut removals: Vec<NodeOrToken<SyntaxNode, _>> = Vec::new();
@@ -368,7 +368,6 @@ fn create_replacement(
};
let new_string = replacement_syntax.to_string();
let new = if new_string == "_" {
let make = SyntaxFactory::without_mappings();
make.wildcard_pat().syntax().clone()
} else {
replacement_syntax.clone()
@@ -1,7 +1,7 @@
use ide_db::{FileId, FxHashSet};
use syntax::{
AstNode, SmolStr, T, TextRange, ToSmolStr,
ast::{self, HasGenericParams, HasName, syntax_factory::SyntaxFactory},
ast::{self, HasGenericParams, HasName},
format_smolstr,
syntax_editor::{Element, Position, SyntaxEditor},
};
@@ -97,23 +97,23 @@ fn generate_fn_def_assist(
};
acc.add(AssistId::refactor(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |edit| {
let mut editor = edit.make_editor(fn_def.syntax());
let factory = SyntaxFactory::with_mappings();
let editor = edit.make_editor(fn_def.syntax());
let make = editor.make();
if let Some(generic_list) = fn_def.generic_param_list() {
insert_lifetime_param(&mut editor, &factory, &generic_list, &new_lifetime_name);
insert_lifetime_param(&editor, &generic_list, &new_lifetime_name);
} else {
insert_new_generic_param_list_fn(&mut editor, &factory, &fn_def, &new_lifetime_name);
insert_new_generic_param_list_fn(&editor, &fn_def, &new_lifetime_name);
}
editor.replace(lifetime.syntax(), factory.lifetime(&new_lifetime_name).syntax());
editor.replace(lifetime.syntax(), make.lifetime(&new_lifetime_name).syntax());
if let Some(pos) = loc_needing_lifetime.and_then(|l| l.to_position()) {
editor.insert_all(
pos,
vec![
factory.lifetime(&new_lifetime_name).syntax().clone().into(),
factory.whitespace(" ").into(),
make.lifetime(&new_lifetime_name).syntax().clone().into(),
make.whitespace(" ").into(),
],
);
}
@@ -123,19 +123,19 @@ fn generate_fn_def_assist(
}
fn insert_new_generic_param_list_fn(
editor: &mut SyntaxEditor,
factory: &SyntaxFactory,
editor: &SyntaxEditor,
fn_def: &ast::Fn,
lifetime_name: &str,
) -> Option<()> {
let make = editor.make();
let name = fn_def.name()?;
editor.insert_all(
Position::after(name.syntax()),
vec![
factory.token(T![<]).syntax_element(),
factory.lifetime(lifetime_name).syntax().syntax_element(),
factory.token(T![>]).syntax_element(),
make.token(T![<]).syntax_element(),
make.lifetime(lifetime_name).syntax().syntax_element(),
make.token(T![>]).syntax_element(),
],
);
@@ -166,35 +166,35 @@ fn generate_impl_def_assist(
let new_lifetime_name = generate_unique_lifetime_param_name(impl_def.generic_param_list())?;
acc.add(AssistId::refactor(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |edit| {
let mut editor = edit.make_editor(impl_def.syntax());
let factory = SyntaxFactory::without_mappings();
let editor = edit.make_editor(impl_def.syntax());
let make = editor.make();
if let Some(generic_list) = impl_def.generic_param_list() {
insert_lifetime_param(&mut editor, &factory, &generic_list, &new_lifetime_name);
insert_lifetime_param(&editor, &generic_list, &new_lifetime_name);
} else {
insert_new_generic_param_list_imp(&mut editor, &factory, &impl_def, &new_lifetime_name);
insert_new_generic_param_list_imp(&editor, &impl_def, &new_lifetime_name);
}
editor.replace(lifetime.syntax(), factory.lifetime(&new_lifetime_name).syntax());
editor.replace(lifetime.syntax(), make.lifetime(&new_lifetime_name).syntax());
edit.add_file_edits(file_id, editor);
})
}
fn insert_new_generic_param_list_imp(
editor: &mut SyntaxEditor,
factory: &SyntaxFactory,
editor: &SyntaxEditor,
impl_: &ast::Impl,
lifetime_name: &str,
) -> Option<()> {
let make = editor.make();
let impl_kw = impl_.impl_token()?;
editor.insert_all(
Position::after(impl_kw),
vec![
factory.token(T![<]).syntax_element(),
factory.lifetime(lifetime_name).syntax().syntax_element(),
factory.token(T![>]).syntax_element(),
make.token(T![<]).syntax_element(),
make.lifetime(lifetime_name).syntax().syntax_element(),
make.token(T![>]).syntax_element(),
],
);
@@ -202,22 +202,22 @@ fn insert_new_generic_param_list_imp(
}
fn insert_lifetime_param(
editor: &mut SyntaxEditor,
factory: &SyntaxFactory,
editor: &SyntaxEditor,
generic_list: &ast::GenericParamList,
lifetime_name: &str,
) -> Option<()> {
let make = editor.make();
let r_angle = generic_list.r_angle_token()?;
let needs_comma = generic_list.generic_params().next().is_some();
let mut elements = Vec::new();
if needs_comma {
elements.push(factory.token(T![,]).syntax_element());
elements.push(factory.whitespace(" ").syntax_element());
elements.push(make.token(T![,]).syntax_element());
elements.push(make.whitespace(" ").syntax_element());
}
let lifetime = factory.lifetime(lifetime_name);
let lifetime = make.lifetime(lifetime_name);
elements.push(lifetime.syntax().clone().into());
editor.insert_all(Position::before(r_angle), elements);
@@ -1,6 +1,6 @@
use ide_db::syntax_helpers::suggest_name;
use itertools::Itertools;
use syntax::ast::{self, AstNode, HasGenericParams, HasName, syntax_factory::SyntaxFactory};
use syntax::ast::{self, AstNode, HasGenericParams, HasName};
use crate::{AssistContext, AssistId, Assists};
@@ -24,14 +24,14 @@ pub(crate) fn introduce_named_type_parameter(
let fn_ = param.syntax().ancestors().nth(2).and_then(ast::Fn::cast)?;
let type_bound_list = impl_trait_type.type_bound_list()?;
let make = SyntaxFactory::with_mappings();
let target = fn_.syntax().text_range();
acc.add(
AssistId::refactor_rewrite("introduce_named_type_parameter"),
"Replace impl trait with type parameter",
target,
|builder| {
let mut editor = builder.make_editor(fn_.syntax());
let editor = builder.make_editor(fn_.syntax());
let make = editor.make();
let existing_names = match fn_.generic_param_list() {
Some(generic_param_list) => generic_param_list
@@ -58,7 +58,6 @@ pub(crate) fn introduce_named_type_parameter(
editor.add_annotation(type_param.syntax(), builder.make_tabstop_before(cap));
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -4,11 +4,7 @@
merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees},
};
use syntax::{
AstNode, SyntaxElement, SyntaxNode,
algo::neighbor,
ast::{self, syntax_factory::SyntaxFactory},
match_ast,
syntax_editor::Removable,
AstNode, SyntaxElement, SyntaxNode, algo::neighbor, ast, match_ast, syntax_editor::Removable,
};
use crate::{
@@ -76,17 +72,16 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
};
acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(&parent_node);
let editor = builder.make_editor(&parent_node);
for edit in edits {
match edit {
Remove(it) => {
let node = it.as_ref();
if let Some(left) = node.left() {
left.remove(&mut editor);
left.remove(&editor);
} else if let Some(right) = node.right() {
right.remove(&mut editor);
right.remove(&editor);
}
}
Replace(old, new) => {
@@ -94,7 +89,6 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
}
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
@@ -45,22 +45,21 @@ pub(crate) fn move_bounds_to_where_clause(
"Move to where clause",
target,
|builder| {
let mut edit = builder.make_editor(&parent);
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(&parent);
let new_preds: Vec<ast::WherePred> = type_param_list
.generic_params()
.filter_map(|param| build_predicate(param, &make))
.filter_map(|param| build_predicate(param, editor.make()))
.collect();
match_ast! {
match (&parent) {
ast::Fn(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::Trait(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::Impl(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::Enum(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::Struct(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::TypeAlias(it) => it.get_or_create_where_clause(&mut edit, &make, new_preds.into_iter()),
ast::Fn(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
ast::Trait(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
ast::Impl(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
ast::Enum(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
ast::Struct(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
ast::TypeAlias(it) => it.get_or_create_where_clause(&editor, new_preds.into_iter()),
_ => return,
}
};
@@ -72,11 +71,11 @@ pub(crate) fn move_bounds_to_where_clause(
ast::GenericParam::ConstParam(_) => continue,
};
if let Some(tbl) = param.type_bound_list() {
tbl.remove(&mut edit);
tbl.remove(&editor);
}
}
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -73,24 +73,24 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
"Move guard to arm body",
target,
|builder| {
let mut edit = builder.make_editor(match_arm.syntax());
let editor = builder.make_editor(match_arm.syntax());
for element in space_before_delete {
if element.kind() == WHITESPACE {
edit.delete(element);
editor.delete(element);
}
}
for rest_arm in &rest_arms {
edit.delete(rest_arm.syntax());
editor.delete(rest_arm.syntax());
}
if let Some(element) = space_after_arrow
&& element.kind() == WHITESPACE
{
edit.replace(element, make.whitespace(" "));
editor.replace(element, make.whitespace(" "));
}
edit.delete(guard.syntax());
edit.replace(arm_expr.syntax(), if_expr.syntax());
builder.add_file_edits(ctx.vfs_file_id(), edit);
editor.delete(guard.syntax());
editor.replace(arm_expr.syntax(), if_expr.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -156,7 +156,8 @@ pub(crate) fn move_arm_cond_to_match_guard(
"Move condition to match guard",
replace_node.text_range(),
|builder| {
let make = SyntaxFactory::without_mappings();
let editor = builder.make_editor(match_arm.syntax());
let make = editor.make();
let mut replace_arms = vec![];
// Dedent if if_expr is in a BlockExpr
@@ -227,14 +228,12 @@ pub(crate) fn move_arm_cond_to_match_guard(
}
}
let mut edit = builder.make_editor(match_arm.syntax());
let newline = make.whitespace(&format!("\n{indent_level}"));
let replace_arms = replace_arms.iter().map(|it| it.syntax().syntax_element());
let replace_arms = Itertools::intersperse(replace_arms, newline.syntax_element());
edit.replace_with_many(match_arm.syntax(), replace_arms.collect());
editor.replace_with_many(match_arm.syntax(), replace_arms.collect());
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -3,7 +3,7 @@
use stdx::to_upper_snake_case;
use syntax::{
AstNode,
ast::{self, HasName, syntax_factory::SyntaxFactory},
ast::{self, HasName},
};
use crate::{
@@ -68,8 +68,8 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
"Promote local to constant",
let_stmt.syntax().text_range(),
|edit| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(let_stmt.syntax());
let editor = edit.make_editor(let_stmt.syntax());
let make = editor.make();
let name = to_upper_snake_case(&name.to_string());
let usages = Definition::Local(local).usages(&ctx.sema).all();
if let Some(usages) = usages.references.get(&ctx.file_id()) {
@@ -97,7 +97,6 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
editor.replace(let_stmt.syntax(), item.syntax());
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -1,10 +1,5 @@
use either::Either;
use syntax::{
AstNode,
algo::find_node_at_range,
ast::{self, syntax_factory::SyntaxFactory},
syntax_editor::SyntaxEditor,
};
use syntax::{AstNode, algo::find_node_at_range, ast, syntax_editor::SyntaxEditor};
use crate::{
AssistId,
@@ -75,8 +70,7 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext<'_>) ->
}
let target = tgt.syntax().text_range();
let (mut editor, edit_tgt) = SyntaxEditor::new(tgt.syntax().clone());
let (editor, edit_tgt) = SyntaxEditor::new(tgt.syntax().clone());
let assignments: Vec<_> = collector
.assignments
.into_iter()
@@ -110,13 +104,12 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Pull assignment up",
target,
move |edit| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(tgt.syntax());
let editor = edit.make_editor(tgt.syntax());
let make = editor.make();
let assign_expr = make.expr_assignment(collector.common_lhs, new_tgt.clone());
let assign_stmt = make.expr_stmt(assign_expr.into());
editor.replace(tgt.syntax(), assign_stmt.syntax());
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -1,6 +1,6 @@
use hir::{AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef, db::HirDatabase};
use ide_db::assists::AssistId;
use syntax::{AstNode, ast, ast::syntax_factory::SyntaxFactory};
use syntax::{AstNode, ast};
use crate::{
assist_context::{AssistContext, Assists},
@@ -59,17 +59,8 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
format!("Qualify `{ident}` method call"),
range,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(call.syntax());
qualify_candidate.qualify(
|_| {},
&mut editor,
&make,
&receiver_path,
item_in_ns,
current_edition,
);
editor.add_mappings(make.finish_with_mappings());
let editor = builder.make_editor(call.syntax());
qualify_candidate.qualify(|_| {}, &editor, &receiver_path, item_in_ns, current_edition);
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -9,11 +9,7 @@
};
use syntax::Edition;
use syntax::ast::HasGenericArgs;
use syntax::{
AstNode, ast,
ast::{HasArgList, syntax_factory::SyntaxFactory},
syntax_editor::SyntaxEditor,
};
use syntax::{AstNode, ast, ast::HasArgList, syntax_editor::SyntaxEditor};
use crate::{
AssistId, GroupLabel,
@@ -102,17 +98,14 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
label(ctx.db(), candidate, &import, current_edition),
range,
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(&syntax_under_caret);
let editor = builder.make_editor(&syntax_under_caret);
qualify_candidate.qualify(
|replace_with: String| builder.replace(range, replace_with),
&mut editor,
&make,
&editor,
&import.import_path,
import.item_to_import,
current_edition,
);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -131,8 +124,7 @@ impl QualifyCandidate<'_> {
pub(crate) fn qualify(
&self,
mut replacer: impl FnMut(String),
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
import: &hir::ModPath,
item: hir::ItemInNs,
edition: Edition,
@@ -151,10 +143,10 @@ pub(crate) fn qualify(
replacer(format!("<{qualifier} as {import}>::{segment}"));
}
QualifyCandidate::TraitMethod(db, mcall_expr) => {
Self::qualify_trait_method(db, mcall_expr, editor, make, import, item);
Self::qualify_trait_method(db, mcall_expr, editor, import, item);
}
QualifyCandidate::ImplMethod(db, mcall_expr, hir_fn) => {
Self::qualify_fn_call(db, mcall_expr, editor, make, import, hir_fn);
Self::qualify_fn_call(db, mcall_expr, editor, import, hir_fn);
}
}
}
@@ -162,11 +154,11 @@ pub(crate) fn qualify(
fn qualify_fn_call(
db: &RootDatabase,
mcall_expr: &ast::MethodCallExpr,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
import: ast::Path,
hir_fn: &hir::Function,
) -> Option<()> {
let make = editor.make();
let receiver = mcall_expr.receiver()?;
let method_name = mcall_expr.name_ref()?;
let generics =
@@ -193,15 +185,14 @@ fn qualify_fn_call(
fn qualify_trait_method(
db: &RootDatabase,
mcall_expr: &ast::MethodCallExpr,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
import: ast::Path,
item: hir::ItemInNs,
) -> Option<()> {
let trait_method_name = mcall_expr.name_ref()?;
let trait_ = item_as_trait(db, item)?;
let method = find_trait_method(db, trait_, &trait_method_name)?;
Self::qualify_fn_call(db, mcall_expr, editor, make, import, &method)
Self::qualify_fn_call(db, mcall_expr, editor, import, &method)
}
}
@@ -164,7 +164,7 @@ fn replace_literal(
) {
let token = token.syntax();
let node = token.parent().expect("no parent token");
let mut edit = builder.make_editor(&node);
let edit = builder.make_editor(&node);
let new_literal = literal(new);
edit.replace(token, mut_token(new_literal));
@@ -47,7 +47,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
.map(|t| t.text_range())
.reduce(|acc, range| acc.cover(range))?;
acc.add(AssistId::quick_fix("remove_dbg"), "Remove dbg!()", target, |builder| {
let mut editor = builder.make_editor(ctx.source_file().syntax());
let editor = builder.make_editor(ctx.source_file().syntax());
for (range, expr) in replacements {
if let Some(expr) = expr {
editor.insert(Position::before(range[0].clone()), expr.syntax());
@@ -209,7 +209,7 @@ fn replace_nested_dbgs(expanded: ast::Expr) -> ast::Expr {
return replaced;
}
let (mut editor, expanded) = SyntaxEditor::with_ast_node(&expanded);
let (editor, expanded) = SyntaxEditor::with_ast_node(&expanded);
// We need to collect to avoid mutation during traversal.
let macro_exprs: Vec<_> =
expanded.syntax().descendants().filter_map(ast::MacroExpr::cast).collect();
@@ -55,7 +55,7 @@ pub(crate) fn remove_else_branches(acc: &mut Assists, ctx: &AssistContext<'_>) -
"Remove `else` branches",
target,
|builder| {
let mut editor = builder.make_editor(&else_token.parent().unwrap());
let editor = builder.make_editor(&else_token.parent().unwrap());
match else_token.prev_token() {
Some(it) if it.kind() == SyntaxKind::WHITESPACE => editor.delete(it),
_ => (),
@@ -22,7 +22,7 @@ pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
let target = mut_token.text_range();
acc.add(AssistId::refactor("remove_mut"), "Remove `mut` keyword", target, |builder| {
let mut editor = builder.make_editor(&mut_token.parent().unwrap());
let editor = builder.make_editor(&mut_token.parent().unwrap());
match mut_token.next_token() {
Some(it) if it.kind() == SyntaxKind::WHITESPACE => editor.delete(it),
_ => (),
@@ -1,8 +1,4 @@
use syntax::{
AstNode, SyntaxKind, T,
ast::{self, syntax_factory::SyntaxFactory},
syntax_editor::Position,
};
use syntax::{AstNode, SyntaxKind, T, ast, syntax_editor::Position};
use crate::{AssistContext, AssistId, Assists};
@@ -44,7 +40,8 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Remove redundant parentheses",
target,
|builder| {
let mut editor = builder.make_editor(parens.syntax());
let editor = builder.make_editor(parens.syntax());
let make = editor.make();
let prev_token = parens.syntax().first_token().and_then(|it| it.prev_token());
let need_to_add_ws = match prev_token {
Some(it) => {
@@ -54,9 +51,7 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
None => false,
};
if need_to_add_ws {
let make = SyntaxFactory::with_mappings();
editor.insert(Position::before(parens.syntax()), make.whitespace(" "));
editor.add_mappings(make.finish_with_mappings());
}
editor.replace(parens.syntax(), expr.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor);
@@ -80,7 +80,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Remove unused parameter",
param.syntax().text_range(),
|builder| {
let mut editor = builder.make_editor(&parent);
let editor = builder.make_editor(&parent);
let elements = elements_to_remove(param.syntax());
for element in elements {
editor.delete(element);
@@ -116,7 +116,7 @@ fn process_usages(
else {
continue;
};
let mut editor = builder.make_editor(&parent);
let editor = builder.make_editor(&parent);
for element in element_range {
editor.delete(element);
}
@@ -71,14 +71,12 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
"Reorder record fields",
target,
|builder| {
let mut editor = builder.make_editor(&parent_node);
let editor = builder.make_editor(&parent_node);
match fields {
Either::Left((sorted, field_list)) => {
replace(&mut editor, field_list.fields(), sorted)
}
Either::Left((sorted, field_list)) => replace(&editor, field_list.fields(), sorted),
Either::Right((sorted, field_list)) => {
replace(&mut editor, field_list.fields(), sorted)
replace(&editor, field_list.fields(), sorted)
}
}
@@ -88,7 +86,7 @@ pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
}
fn replace<T: AstNode + PartialEq>(
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
fields: impl Iterator<Item = T>,
sorted_fields: impl IntoIterator<Item = T>,
) {
@@ -99,7 +99,7 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
"Sort items by trait definition",
target,
|builder| {
let mut editor = builder.make_editor(&parent_node);
let editor = builder.make_editor(&parent_node);
assoc_items
.into_iter()
@@ -1,7 +1,7 @@
use ide_db::assists::{AssistId, GroupLabel};
use syntax::{
AstNode,
ast::{self, ArithOp, BinaryOp, syntax_factory::SyntaxFactory},
ast::{self, ArithOp, BinaryOp},
};
use crate::assist_context::{AssistContext, Assists};
@@ -83,8 +83,8 @@ fn replace_arith(acc: &mut Assists, ctx: &AssistContext<'_>, kind: ArithKind) ->
kind.label(),
op_expr.text_range(),
|builder| {
let mut edit = builder.make_editor(rhs.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(rhs.syntax());
let make = editor.make();
let method_name = kind.method_name(op);
let needs_parentheses =
@@ -92,10 +92,8 @@ fn replace_arith(acc: &mut Assists, ctx: &AssistContext<'_>, kind: ArithKind) ->
let receiver = if needs_parentheses { make.expr_paren(lhs).into() } else { lhs };
let arith_expr =
make.expr_method_call(receiver, make.name_ref(&method_name), make.arg_list([rhs]));
edit.replace(op_expr, arith_expr.syntax());
edit.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), edit);
editor.replace(op_expr, arith_expr.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
@@ -4,7 +4,7 @@
use syntax::{
SyntaxKind::WHITESPACE,
T,
ast::{self, AstNode, HasName, syntax_factory::SyntaxFactory},
ast::{self, AstNode, HasName},
syntax_editor::{Position, SyntaxEditor},
};
@@ -128,10 +128,12 @@ fn add_assist(
let label = format!("Convert to manual `impl {replace_trait_path} for {annotated_name}`");
acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(attr.syntax());
let make = editor.make();
let insert_after = Position::after(adt.syntax());
let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
let impl_def = impl_def_from_trait(
&editor,
&ctx.sema,
ctx.config,
adt,
@@ -140,9 +142,7 @@ fn add_assist(
replace_trait_path,
impl_is_unsafe,
);
let mut editor = builder.make_editor(attr.syntax());
update_attribute(&make, &mut editor, old_derives, old_tree, old_trait_path, attr);
update_attribute(&editor, old_derives, old_tree, old_trait_path, attr);
let trait_path = make.ty_path(replace_trait_path.clone()).into();
@@ -152,7 +152,7 @@ fn add_assist(
impl_def.assoc_item_list().and_then(|list| list.assoc_items().next()),
)
} else {
(generate_trait_impl(&make, impl_is_unsafe, adt, trait_path), None)
(generate_trait_impl(make, impl_is_unsafe, adt, trait_path), None)
};
if let Some(cap) = ctx.config.snippet_cap {
@@ -178,12 +178,12 @@ fn add_assist(
insert_after,
vec![make.whitespace("\n\n").into(), impl_def.syntax().clone().into()],
);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
fn impl_def_from_trait(
editor: &SyntaxEditor,
sema: &hir::Semantics<'_, ide_db::RootDatabase>,
config: &AssistConfig,
adt: &ast::Adt,
@@ -192,6 +192,7 @@ fn impl_def_from_trait(
trait_path: &ast::Path,
impl_is_unsafe: bool,
) -> Option<ast::Impl> {
let make = editor.make();
let trait_ = trait_?;
let target_scope = sema.scope(annotated_name.syntax())?;
@@ -208,12 +209,11 @@ fn impl_def_from_trait(
if trait_items.is_empty() {
return None;
}
let make = SyntaxFactory::without_mappings();
let trait_ty: ast::Type = make.ty_path(trait_path.clone()).into();
let impl_def = generate_trait_impl(&make, impl_is_unsafe, adt, trait_ty.clone());
let impl_def = generate_trait_impl(make, impl_is_unsafe, adt, trait_ty.clone());
let assoc_items = add_trait_assoc_items_to_impl(
&make,
make,
sema,
config,
&trait_items,
@@ -223,10 +223,10 @@ fn impl_def_from_trait(
);
let assoc_item_list = if let Some((first, other)) = assoc_items.split_first() {
let first_item = if let ast::AssocItem::Fn(func) = first
&& let Some(body) = gen_trait_fn_body(&make, func, trait_path, adt, None)
&& let Some(body) = gen_trait_fn_body(make, func, trait_path, adt, None)
&& let Some(func_body) = func.body()
{
let (mut editor, _) = SyntaxEditor::new(first.syntax().clone());
let (editor, _) = SyntaxEditor::new(first.syntax().clone());
editor.replace(func_body.syntax(), body.syntax());
ast::AssocItem::cast(editor.finish().new_root().clone())
} else {
@@ -239,17 +239,17 @@ fn impl_def_from_trait(
make.assoc_item_list_empty()
};
Some(generate_trait_impl_with_item(&make, impl_is_unsafe, adt, trait_ty, assoc_item_list))
Some(generate_trait_impl_with_item(make, impl_is_unsafe, adt, trait_ty, assoc_item_list))
}
fn update_attribute(
make: &SyntaxFactory,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
old_derives: &[ast::Path],
old_tree: &ast::TokenTree,
old_trait_path: &ast::Path,
attr: &ast::Attr,
) {
let make = editor.make();
let new_derives = old_derives
.iter()
.filter(|t| t.to_string() != old_trait_path.to_string())
@@ -111,9 +111,10 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
format!("Replace if{let_} with match"),
available_range,
move |builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(if_expr.syntax());
let make = editor.make();
let match_expr: ast::Expr = {
let else_arm = make_else_arm(ctx, &make, else_block, &cond_bodies);
let else_arm = make_else_arm(ctx, make, else_block, &cond_bodies);
let make_match_arm =
|(pat, guard, body): (_, Option<ast::Expr>, ast::BlockExpr)| {
// Dedent from original position, then indent for match arm
@@ -139,17 +140,15 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
if_expr.syntax().parent().is_some_and(|it| ast::IfExpr::can_cast(it.kind()));
let expr = if has_preceding_if_expr {
// make sure we replace the `else if let ...` with a block so we don't end up with `else expr`
let block_expr = make
let block_expr = editor
.make()
.block_expr([], Some(match_expr.dedent(indent).indent(IndentLevel(1))))
.indent(indent);
block_expr.into()
} else {
match_expr
};
let mut editor = builder.make_editor(if_expr.syntax());
editor.replace(if_expr.syntax(), expr.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -267,7 +266,8 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
format!("Replace match with if{let_}"),
match_expr.syntax().text_range(),
move |builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(match_expr.syntax());
let make = editor.make();
let make_block_expr = |expr: ast::Expr| {
// Blocks with modifiers (unsafe, async, etc.) are parsed as BlockExpr, but are
// formatted without enclosing braces. If we encounter such block exprs,
@@ -292,7 +292,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
_ => make.expr_let(if_let_pat, scrutinee).into(),
};
let condition = if let Some(guard) = guard {
let guard = wrap_paren(guard, &make, ast::prec::ExprPrecedence::LAnd);
let guard = wrap_paren(guard, make, ast::prec::ExprPrecedence::LAnd);
make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard).into()
} else {
condition
@@ -301,7 +301,8 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
let else_expr = else_expr.reset_indent();
let then_block = make_block_expr(then_expr);
let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
let if_let_expr = make
let if_let_expr = editor
.make()
.expr_if(
condition,
then_block,
@@ -309,9 +310,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
)
.indent(IndentLevel::from_node(match_expr.syntax()));
let mut editor = builder.make_editor(match_expr.syntax());
editor.replace(match_expr.syntax(), if_let_expr.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -402,21 +401,20 @@ fn let_and_guard(cond: &ast::Expr) -> (Option<ast::LetExpr>, Option<ast::Expr>)
} else if let ast::Expr::BinExpr(bin_expr) = cond
&& let Some(ast::Expr::LetExpr(let_expr)) = and_bin_expr_left(bin_expr).lhs()
{
let (mut edit, new_expr) = SyntaxEditor::with_ast_node(bin_expr);
let (editor, new_expr) = SyntaxEditor::with_ast_node(bin_expr);
let left_bin = and_bin_expr_left(&new_expr);
if let Some(rhs) = left_bin.rhs() {
edit.replace(left_bin.syntax(), rhs.syntax());
editor.replace(left_bin.syntax(), rhs.syntax());
} else {
if let Some(next) = left_bin.syntax().next_sibling_or_token()
&& next.kind() == SyntaxKind::WHITESPACE
{
edit.delete(next);
editor.delete(next);
}
edit.delete(left_bin.syntax());
editor.delete(left_bin.syntax());
}
let new_expr = edit.finish().new_root().clone();
let new_expr = editor.finish().new_root().clone();
(Some(let_expr), ast::Expr::cast(new_expr))
} else {
(None, Some(cond.clone()))
@@ -1,6 +1,9 @@
use either::Either;
use ide_db::syntax_helpers::suggest_name;
use syntax::ast::{self, AstNode, HasArgList, prec::ExprPrecedence, syntax_factory::SyntaxFactory};
use syntax::{
ast::{self, AstNode, HasArgList, prec::ExprPrecedence, syntax_factory::SyntaxFactory},
syntax_editor::SyntaxEditor,
};
use crate::{
AssistContext, AssistId, Assists,
@@ -41,9 +44,9 @@ pub(crate) fn replace_is_method_with_if_let_method(
let method_kind = token.text().strip_suffix("_and").unwrap_or(token.text());
match method_kind {
"is_some" | "is_ok" => {
let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone());
let make = editor.make();
let receiver = call_expr.receiver()?;
let make = SyntaxFactory::with_mappings();
let mut name_generator = suggest_name::NameGenerator::new_from_scope_locals(
ctx.sema.scope(has_cond.syntax()),
);
@@ -52,7 +55,7 @@ pub(crate) fn replace_is_method_with_if_let_method(
} else {
name_generator.for_variable(&receiver, &ctx.sema)
};
let (pat, predicate) = method_predicate(&call_expr, &var_name, &make);
let (pat, predicate) = method_predicate(&call_expr, &var_name, make);
let (assist_id, message, text) = if method_kind == "is_some" {
("replace_is_some_with_if_let_some", "Replace `is_some` with `let Some`", "Some")
@@ -65,8 +68,7 @@ pub(crate) fn replace_is_method_with_if_let_method(
message,
call_expr.syntax().text_range(),
|edit| {
let mut editor = edit.make_editor(call_expr.syntax());
let make = editor.make();
let pat = make.tuple_struct_pat(make.ident_path(text), [pat]).into();
let let_expr = make.expr_let(pat, receiver);
@@ -81,14 +83,12 @@ pub(crate) fn replace_is_method_with_if_let_method(
let new_expr = if let Some(predicate) = predicate {
let op = ast::BinaryOp::LogicOp(ast::LogicOp::And);
let predicate = wrap_paren(predicate, &make, ExprPrecedence::LAnd);
let predicate = wrap_paren(predicate, make, ExprPrecedence::LAnd);
make.expr_bin(let_expr.into(), op, predicate).into()
} else {
ast::Expr::from(let_expr)
};
editor.replace(call_expr.syntax(), new_expr.syntax());
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -46,8 +46,8 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_>
"Replace let with if let",
target,
|builder| {
let mut editor = builder.make_editor(let_stmt.syntax());
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(let_stmt.syntax());
let make = editor.make();
let ty = ctx.sema.type_of_expr(&init);
let pat = if let_stmt.let_else().is_some() {
// Do not add the wrapper type that implements `Try`,
@@ -59,9 +59,10 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_>
.map(|it| it.happy_case());
match happy_variant {
None => original_pat,
Some(var_name) => {
make.tuple_struct_pat(make.ident_path(var_name), [original_pat]).into()
}
Some(var_name) => editor
.make()
.tuple_struct_pat(make.ident_path(var_name), [original_pat])
.into(),
}
};
let init_expr =
@@ -79,7 +80,6 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_>
let if_stmt = make.expr_stmt(if_expr.into());
editor.replace(let_stmt.syntax(), if_stmt.syntax());
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -5,7 +5,6 @@
defs::Definition,
search::{SearchScope, UsageSearchResult},
};
use syntax::ast::syntax_factory::SyntaxFactory;
use syntax::{
AstNode,
ast::{self, HasGenericParams, HasName, HasTypeBounds, Name, NameLike, PathType},
@@ -72,8 +71,8 @@ pub(crate) fn replace_named_generic_with_impl(
"Replace named generic with impl trait",
target,
|edit| {
let mut editor = edit.make_editor(type_param.syntax());
let make = SyntaxFactory::without_mappings();
let editor = edit.make_editor(type_param.syntax());
let make = editor.make();
// remove trait from generic param list
if let Some(generic_params) = fn_.generic_param_list() {
@@ -73,8 +73,8 @@ pub(crate) fn replace_qualified_name_with_use(
// Now that we've brought the name into scope, re-qualify all paths that could be
// affected (that is, all paths inside the node we added the `use` to).
let scope_node = scope.as_syntax_node();
let mut editor = builder.make_editor(scope_node);
shorten_paths(&mut editor, scope_node, &original_path);
let editor = builder.make_editor(scope_node);
shorten_paths(&editor, scope_node, &original_path);
builder.add_file_edits(ctx.vfs_file_id(), editor);
let path = drop_generic_args(&original_path);
let edition = ctx
@@ -111,7 +111,7 @@ fn target_path(ctx: &AssistContext<'_>, mut original_path: ast::Path) -> Option<
}
fn drop_generic_args(path: &ast::Path) -> ast::Path {
let (mut editor, path) = SyntaxEditor::with_ast_node(path);
let (editor, path) = SyntaxEditor::with_ast_node(path);
if let Some(segment) = path.segment()
&& let Some(generic_args) = segment.generic_arg_list()
{
@@ -122,7 +122,7 @@ fn drop_generic_args(path: &ast::Path) -> ast::Path {
}
/// Mutates `node` to shorten `path` in all descendants of `node`.
fn shorten_paths(editor: &mut SyntaxEditor, node: &SyntaxNode, path: &ast::Path) {
fn shorten_paths(editor: &SyntaxEditor, node: &SyntaxNode, path: &ast::Path) {
for child in node.children() {
match_ast! {
match child {
@@ -141,7 +141,7 @@ fn shorten_paths(editor: &mut SyntaxEditor, node: &SyntaxNode, path: &ast::Path)
}
}
fn maybe_replace_path(editor: &mut SyntaxEditor, path: ast::Path, target: ast::Path) -> Option<()> {
fn maybe_replace_path(editor: &SyntaxEditor, path: ast::Path, target: ast::Path) -> Option<()> {
if !path_eq_no_generics(path.clone(), target) {
return None;
}
@@ -127,7 +127,7 @@ fn add_rewrite<T: AstNode>(
target: &SyntaxNode,
) -> Option<()> {
self.add(AssistId::refactor_rewrite("sort_items"), label, target.text_range(), |builder| {
let mut editor = builder.make_editor(target);
let editor = builder.make_editor(target);
old.into_iter()
.zip(new)
@@ -2,7 +2,7 @@
use syntax::{
AstNode, SyntaxKind, SyntaxToken, T,
algo::{previous_non_trivia_token, skip_trivia_token},
ast::{self, syntax_factory::SyntaxFactory},
ast,
};
use crate::{AssistContext, Assists};
@@ -73,8 +73,8 @@ enum MacroDelims {
},
token_tree.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(token_tree.syntax());
let editor = builder.make_editor(token_tree.syntax());
let make = editor.make();
match token {
MacroDelims::LPar | MacroDelims::RPar => {
@@ -100,7 +100,6 @@ enum MacroDelims {
}
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -1,6 +1,6 @@
use syntax::{
AstNode, SyntaxKind,
ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, make, syntax_factory::SyntaxFactory},
ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, make},
syntax_editor::{Element, Position, Removable},
};
@@ -41,26 +41,27 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
let target = tree.syntax().text_range();
acc.add(AssistId::refactor_rewrite("unmerge_imports"), label, target, |builder| {
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(use_.syntax());
let make = editor.make();
let new_use = make.use_(
use_.attrs(),
use_.visibility(),
make.use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()),
);
let mut editor = builder.make_editor(use_.syntax());
// Remove the use tree from the current use item
tree.remove(&mut editor);
tree.remove(&editor);
// Insert a newline and indentation, followed by the new use item
editor.insert_all(
Position::after(use_.syntax()),
vec![
make.whitespace(&format!("\n{}", IndentLevel::from_node(use_.syntax())))
editor
.make()
.whitespace(&format!("\n{}", IndentLevel::from_node(use_.syntax())))
.syntax_element(),
new_use.syntax().syntax_element(),
],
);
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
@@ -1,6 +1,6 @@
use syntax::{
Direction, SyntaxKind, T,
ast::{self, AstNode, edit::IndentLevel, syntax_factory::SyntaxFactory},
ast::{self, AstNode, edit::IndentLevel},
syntax_editor::{Element, Position},
};
@@ -56,8 +56,8 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
"Unmerge match arm",
pipe_token.text_range(),
|edit| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(&new_parent);
let editor = edit.make_editor(&new_parent);
let make = editor.make();
// It is guaranteed that `pats_after` has at least one element
let new_pat = if pats_after.len() == 1 {
pats_after[0].clone()
@@ -101,7 +101,6 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
insert_after_old_arm.push(new_match_arm.syntax().clone().into());
editor.insert_all(Position::after(match_arm.syntax()), insert_after_old_arm);
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -1,5 +1,5 @@
use hir::AsAssocItem;
use syntax::ast::{self, AstNode, HasArgList, prec::ExprPrecedence, syntax_factory::SyntaxFactory};
use syntax::ast::{self, AstNode, HasArgList, prec::ExprPrecedence};
use crate::{AssistContext, AssistId, Assists};
@@ -50,8 +50,8 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
"Unqualify method call",
call.syntax().text_range(),
|builder| {
let make = SyntaxFactory::with_mappings();
let mut editor = builder.make_editor(call.syntax());
let editor = builder.make_editor(call.syntax());
let make = editor.make();
let new_arg_list = make.arg_list(args.args().skip(1));
let receiver = if first_arg.precedence().needs_parentheses_in(ExprPrecedence::Postfix) {
@@ -67,10 +67,9 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
&& let Some(trait_) = fun.container_or_implemented_trait(ctx.db())
&& !scope.can_use_trait_methods(trait_)
{
add_import(qualifier, ctx, &make, &mut editor);
add_import(qualifier, ctx, &editor);
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
@@ -79,8 +78,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
fn add_import(
qualifier: ast::Path,
ctx: &AssistContext<'_>,
make: &SyntaxFactory,
editor: &mut syntax::syntax_editor::SyntaxEditor,
editor: &syntax::syntax_editor::SyntaxEditor,
) {
if let Some(path_segment) = qualifier.segment() {
// for `<i32 as std::ops::Add>`
@@ -112,7 +110,6 @@ fn add_import(
import,
&ctx.config.insert_use,
editor,
make,
);
}
}
@@ -72,18 +72,18 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
let replacement = replacement.stmt_list()?;
acc.add(AssistId::refactor_rewrite("unwrap_block"), "Unwrap block", target, |builder| {
let mut edit = builder.make_editor(block.syntax());
let editor = builder.make_editor(block.syntax());
let replacement = replacement.dedent(from_indent).indent(into_indent);
let container = prefer_container.unwrap_or(container);
edit.replace_with_many(&container, extract_statements(replacement));
delete_else_before(container, &mut edit);
editor.replace_with_many(&container, extract_statements(replacement));
delete_else_before(container, &editor);
builder.add_file_edits(ctx.vfs_file_id(), edit);
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
fn delete_else_before(container: SyntaxNode, edit: &mut SyntaxEditor) {
fn delete_else_before(container: SyntaxNode, edit: &SyntaxEditor) {
let Some(else_token) = container
.siblings_with_tokens(syntax::Direction::Prev)
.skip(1)
@@ -103,7 +103,7 @@ fn delete_else_before(container: SyntaxNode, edit: &mut SyntaxEditor) {
fn wrap_let(assign: &ast::LetStmt, replacement: ast::BlockExpr) -> ast::BlockExpr {
let try_wrap_assign = || {
let initializer = assign.initializer()?.syntax().syntax_element();
let (mut edit, replacement) = SyntaxEditor::with_ast_node(&replacement);
let (editor, replacement) = SyntaxEditor::with_ast_node(&replacement);
let tail_expr = replacement.tail_expr()?;
let before =
assign.syntax().children_with_tokens().take_while(|it| *it != initializer).collect();
@@ -114,9 +114,9 @@ fn wrap_let(assign: &ast::LetStmt, replacement: ast::BlockExpr) -> ast::BlockExp
.skip(1)
.collect();
edit.insert_all(Position::before(tail_expr.syntax()), before);
edit.insert_all(Position::after(tail_expr.syntax()), after);
ast::BlockExpr::cast(edit.finish().new_root().clone())
editor.insert_all(Position::before(tail_expr.syntax()), before);
editor.insert_all(Position::after(tail_expr.syntax()), after);
ast::BlockExpr::cast(editor.finish().new_root().clone())
};
try_wrap_assign().unwrap_or(replacement)
}
@@ -5,7 +5,7 @@
};
use syntax::{
AstNode, NodeOrToken, SyntaxKind,
ast::{self, HasArgList, HasGenericArgs, syntax_factory::SyntaxFactory},
ast::{self, HasArgList, HasGenericArgs},
match_ast,
};
@@ -66,8 +66,8 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let happy_type = extract_wrapped_type(type_ref)?;
acc.add(kind.assist_id(), kind.label(), type_ref.syntax().text_range(), |builder| {
let mut editor = builder.make_editor(&parent);
let make = SyntaxFactory::with_mappings();
let editor = builder.make_editor(&parent);
let make = editor.make();
let mut exprs_to_unwrap = Vec::new();
let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e);
@@ -168,7 +168,6 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) ->
editor.add_annotation(final_placeholder.syntax(), builder.make_tabstop_after(cap));
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
})
}
@@ -46,7 +46,7 @@ pub(crate) fn unwrap_type_to_generic_arg(acc: &mut Assists, ctx: &AssistContext<
format!("Unwrap type to type argument {generic_arg}"),
path_type.syntax().text_range(),
|builder| {
let mut editor = builder.make_editor(path_type.syntax());
let editor = builder.make_editor(path_type.syntax());
editor.replace(path_type.syntax(), generic_arg.syntax());
builder.add_file_edits(ctx.vfs_file_id(), editor);
@@ -77,9 +77,9 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
kind.label(),
type_ref.syntax().text_range(),
|builder| {
let mut editor = builder.make_editor(&parent);
let make = SyntaxFactory::with_mappings();
let alias = wrapper_alias(ctx, &make, core_wrapper, type_ref, &ty, kind.symbol());
let editor = builder.make_editor(&parent);
let make = editor.make();
let alias = wrapper_alias(ctx, make, core_wrapper, type_ref, &ty, kind.symbol());
let (ast_new_return_ty, semantic_new_return_ty) = alias.unwrap_or_else(|| {
let (ast_ty, ty_constructor) = match kind {
WrapperKind::Option => {
@@ -156,8 +156,6 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
);
}
}
editor.add_mappings(make.finish_with_mappings());
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
);
@@ -2,7 +2,7 @@
use itertools::Itertools;
use syntax::{
NodeOrToken, SyntaxToken, T, TextRange, algo,
ast::{self, AstNode, edit::AstNodeEdit, make, syntax_factory::SyntaxFactory},
ast::{self, AstNode, edit::AstNodeEdit, make},
};
use crate::{AssistContext, AssistId, Assists};
@@ -192,8 +192,8 @@ fn wrap_derive(
}
}
let handle_source_change = |edit: &mut SourceChangeBuilder| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(attr.syntax());
let editor = edit.make_editor(attr.syntax());
let make = editor.make();
let new_derive = make.attr_outer(
make.meta_token_tree(make.ident_path("derive"), make.token_tree(T!['('], new_derive)),
);
@@ -221,8 +221,6 @@ fn wrap_derive(
let tabstop = edit.make_placeholder_snippet(snippet_cap);
editor.add_annotation(cfg_predicate.syntax(), tabstop);
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
};
@@ -239,8 +237,8 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::At
let (first_attr, last_attr) = (attrs.first()?, attrs.last()?);
let range = first_attr.syntax().text_range().cover(last_attr.syntax().text_range());
let handle_source_change = |edit: &mut SourceChangeBuilder| {
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(first_attr.syntax());
let editor = edit.make_editor(first_attr.syntax());
let make = editor.make();
let meta =
make.cfg_attr_meta(make.cfg_flag("cfg"), attrs.iter().filter_map(|attr| attr.meta()));
let cfg_attr = if first_attr.excl_token().is_some() {
@@ -258,8 +256,6 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::At
let tabstop = edit.make_placeholder_snippet(snippet_cap);
editor.add_annotation(cfg_flag.syntax(), tabstop);
}
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
};
acc.add(
@@ -248,20 +248,20 @@ pub fn add_trait_assoc_items_to_impl(
})
.filter_map(|item| match item {
ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
let (mut fn_editor, fn_) = SyntaxEditor::with_ast_node(&fn_);
let (fn_editor, fn_) = SyntaxEditor::with_ast_node(&fn_);
let fill_expr: ast::Expr = match config.expr_fill_default {
ExprFillDefaultMode::Todo | ExprFillDefaultMode::Default => make.expr_todo(),
ExprFillDefaultMode::Underscore => make.expr_underscore().into(),
};
let new_body = make.block_expr(None::<ast::Stmt>, Some(fill_expr));
fn_.replace_or_insert_body(&mut fn_editor, new_body);
fn_.replace_or_insert_body(&fn_editor, new_body);
let new_fn_ = fn_editor.finish().new_root().clone();
ast::AssocItem::cast(new_fn_)
}
ast::AssocItem::TypeAlias(type_alias) => {
let (mut type_alias_editor, type_alias) = SyntaxEditor::with_ast_node(&type_alias);
let (type_alias_editor, type_alias) = SyntaxEditor::with_ast_node(&type_alias);
if let Some(type_bound_list) = type_alias.type_bound_list() {
type_bound_list.remove(&mut type_alias_editor);
type_bound_list.remove(&type_alias_editor);
};
let type_alias = type_alias_editor.finish().new_root().clone();
ast::AssocItem::cast(type_alias)
@@ -346,10 +346,10 @@ fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Ex
pub(crate) fn insert_attributes(
before: impl Element,
edit: &mut SyntaxEditor,
editor: &SyntaxEditor,
attrs: impl IntoIterator<Item = ast::Attr>,
make: &SyntaxFactory,
) {
let make = editor.make();
let mut attrs = attrs.into_iter().peekable();
if attrs.peek().is_none() {
return;
@@ -357,12 +357,10 @@ pub(crate) fn insert_attributes(
let elem = before.syntax_element();
let indent = IndentLevel::from_element(&elem);
let whitespace = format!("\n{indent}");
edit.insert_all(
syntax::syntax_editor::Position::before(elem),
attrs
.flat_map(|attr| [attr.syntax().clone().into(), make.whitespace(&whitespace).into()])
.collect(),
);
let elements: Vec<syntax::SyntaxElement> = attrs
.flat_map(|attr| [attr.syntax().clone().into(), make.whitespace(&whitespace).into()])
.collect();
editor.insert_all(syntax::syntax_editor::Position::before(elem), elements);
}
pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {
@@ -9,7 +9,7 @@
Direction, NodeOrToken, SyntaxKind, SyntaxNode, algo,
ast::{
self, AstNode, HasAttrs, HasModuleItem, HasVisibility, PathSegmentKind,
edit_in_place::Removable, make, syntax_factory::SyntaxFactory,
edit_in_place::Removable, make,
},
syntax_editor::{Position, SyntaxEditor},
ted,
@@ -175,10 +175,9 @@ pub fn insert_use_with_editor(
scope: &ImportScope,
path: ast::Path,
cfg: &InsertUseConfig,
syntax_editor: &mut SyntaxEditor,
syntax_factory: &SyntaxFactory,
syntax_editor: &SyntaxEditor,
) {
insert_use_with_alias_option_with_editor(scope, path, cfg, None, syntax_editor, syntax_factory);
insert_use_with_alias_option_with_editor(scope, path, cfg, None, syntax_editor);
}
pub fn insert_use_as_alias(
@@ -269,9 +268,9 @@ fn insert_use_with_alias_option_with_editor(
path: ast::Path,
cfg: &InsertUseConfig,
alias: Option<ast::Rename>,
syntax_editor: &mut SyntaxEditor,
syntax_factory: &SyntaxFactory,
syntax_editor: &SyntaxEditor,
) {
let make = syntax_editor.make();
let _p = tracing::info_span!("insert_use_with_alias_option").entered();
let mut mb = match cfg.granularity {
ImportGranularity::Crate => Some(MergeBehavior::Crate),
@@ -301,7 +300,7 @@ fn insert_use_with_alias_option_with_editor(
};
}
let use_tree = syntax_factory.use_tree(path, None, alias, false);
let use_tree = make.use_tree(path, None, alias, false);
if mb == Some(MergeBehavior::One) && use_tree.path().is_some() {
use_tree.wrap_in_tree_list();
}
@@ -324,7 +323,7 @@ fn insert_use_with_alias_option_with_editor(
}
// either we weren't allowed to merge or there is no import that fits the merge conditions
// so look for the place we have to insert to
insert_use_with_editor_(scope, use_item, cfg.group, syntax_editor, syntax_factory);
insert_use_with_editor_(scope, use_item, cfg.group, syntax_editor);
}
pub fn ast_to_remove_for_path_in_use_stmt(path: &ast::Path) -> Option<Box<dyn Removable>> {
@@ -604,9 +603,9 @@ fn insert_use_with_editor_(
scope: &ImportScope,
use_item: ast::Use,
group_imports: bool,
syntax_editor: &mut SyntaxEditor,
syntax_factory: &SyntaxFactory,
syntax_editor: &SyntaxEditor,
) {
let make = syntax_editor.make();
let scope_syntax = scope.as_syntax_node();
let insert_use_tree =
use_item.use_tree().expect("`use_item` should have a use tree for `insert_path`");
@@ -656,7 +655,7 @@ fn insert_use_with_editor_(
cov_mark::hit!(insert_group_new_group);
syntax_editor.insert(Position::before(&node), use_item.syntax());
if let Some(node) = algo::non_trivia_sibling(node.into(), Direction::Prev) {
syntax_editor.insert(Position::after(node), syntax_factory.whitespace("\n"));
syntax_editor.insert(Position::after(node), make.whitespace("\n"));
}
return;
}
@@ -664,7 +663,7 @@ fn insert_use_with_editor_(
if let Some(node) = last {
cov_mark::hit!(insert_group_no_group);
syntax_editor.insert(Position::after(&node), use_item.syntax());
syntax_editor.insert(Position::after(node), syntax_factory.whitespace("\n"));
syntax_editor.insert(Position::after(node), make.whitespace("\n"));
return;
}
} else {
@@ -703,24 +702,18 @@ fn insert_use_with_editor_(
{
cov_mark::hit!(insert_empty_inner_attr);
syntax_editor.insert(Position::after(&last_inner_element), use_item.syntax());
syntax_editor.insert(Position::after(last_inner_element), syntax_factory.whitespace("\n"));
syntax_editor.insert(Position::after(last_inner_element), make.whitespace("\n"));
} else {
match l_curly {
Some(b) => {
cov_mark::hit!(insert_empty_module);
syntax_editor.insert(Position::after(&b), syntax_factory.whitespace("\n"));
syntax_editor.insert_with_whitespace(
Position::after(&b),
use_item.syntax(),
syntax_factory,
);
syntax_editor.insert(Position::after(&b), make.whitespace("\n"));
syntax_editor.insert_with_whitespace(Position::after(&b), use_item.syntax());
}
None => {
cov_mark::hit!(insert_empty_file);
syntax_editor.insert(
Position::first_child_of(scope_syntax),
syntax_factory.whitespace("\n\n"),
);
syntax_editor
.insert(Position::first_child_of(scope_syntax), make.whitespace("\n\n"));
syntax_editor.insert(Position::first_child_of(scope_syntax), use_item.syntax());
}
}
@@ -278,7 +278,7 @@ fn apply(&self, item: &SyntaxNode) -> SyntaxNode {
// `transform_path` may update a node's parent and that would break the
// tree traversal. Thus all paths in the tree are collected into a vec
// so that such operation is safe.
let (mut editor, item) = SyntaxEditor::new(self.transform_path(item));
let (editor, item) = SyntaxEditor::new(self.transform_path(item));
preorder_rev(&item).filter_map(ast::Lifetime::cast).for_each(|lifetime| {
if let Some(subst) = self.lifetime_substs.get(&lifetime.syntax().text().to_string()) {
editor.replace(lifetime.syntax(), subst.clone().syntax());
@@ -329,22 +329,22 @@ fn find_child_paths_and_ident_pats(
result
}
let (mut editor, root_path) = SyntaxEditor::new(path.clone());
let (editor, root_path) = SyntaxEditor::new(path.clone());
let result = find_child_paths_and_ident_pats(&root_path);
for sub_path in result {
let new = self.transform_path(sub_path.syntax());
editor.replace(sub_path.syntax(), new);
}
let (mut editor, update_sub_item) = SyntaxEditor::new(editor.finish().new_root().clone());
let (editor, update_sub_item) = SyntaxEditor::new(editor.finish().new_root().clone());
let item = find_child_paths_and_ident_pats(&update_sub_item);
for sub_path in item {
self.transform_path_or_ident_pat(&mut editor, &sub_path);
self.transform_path_or_ident_pat(&editor, &sub_path);
}
editor.finish().new_root().clone()
}
fn transform_path_or_ident_pat(
&self,
editor: &mut SyntaxEditor,
editor: &SyntaxEditor,
item: &Either<ast::Path, ast::IdentPat>,
) -> Option<()> {
match item {
@@ -353,7 +353,7 @@ fn transform_path_or_ident_pat(
}
}
fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option<()> {
fn transform_path_(&self, editor: &SyntaxEditor, path: &ast::Path) -> Option<()> {
if path.qualifier().is_some() {
return None;
}
@@ -448,7 +448,7 @@ fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option
};
let found_path = self.target_module.find_path(self.source_scope.db, def, cfg)?;
let res = mod_path_to_ast(&found_path, self.target_edition);
let (mut res_editor, res) = SyntaxEditor::with_ast_node(&res);
let (res_editor, res) = SyntaxEditor::with_ast_node(&res);
if let Some(args) = path.segment().and_then(|it| it.generic_arg_list())
&& let Some(segment) = res.segment()
{
@@ -522,11 +522,7 @@ fn transform_path_(&self, editor: &mut SyntaxEditor, path: &ast::Path) -> Option
Some(())
}
fn transform_ident_pat(
&self,
editor: &mut SyntaxEditor,
ident_pat: &ast::IdentPat,
) -> Option<()> {
fn transform_ident_pat(&self, editor: &SyntaxEditor, ident_pat: &ast::IdentPat) -> Option<()> {
let name = ident_pat.name()?;
let temp_path = make::path_from_text(&name.text());
@@ -10,7 +10,6 @@
ast::{
self, BlockExpr, Expr, ExprStmt, HasArgList,
edit::{AstNodeEdit, IndentLevel},
syntax_factory::SyntaxFactory,
},
};
@@ -235,7 +234,7 @@ fn remove_unnecessary_wrapper(
let file_id = expr_ptr.file_id.original_file(db);
let mut builder = SourceChangeBuilder::new(file_id.file_id(ctx.sema.db));
let mut editor;
let editor;
match inner_arg {
// We're returning `()`
Expr::TupleExpr(tup) if tup.fields().next().is_none() => {
@@ -245,7 +244,7 @@ fn remove_unnecessary_wrapper(
.and_then(Either::<ast::ReturnExpr, ast::StmtList>::cast)?;
editor = builder.make_editor(parent.syntax());
let make = SyntaxFactory::with_mappings();
let make = editor.make();
match parent {
Either::Left(ret_expr) => {
@@ -261,8 +260,6 @@ fn remove_unnecessary_wrapper(
editor.replace(stmt_list.syntax().parent()?, new_block.syntax());
}
}
editor.add_mappings(make.finish_with_mappings());
}
_ => {
editor = builder.make_editor(call_expr.syntax());
@@ -108,7 +108,7 @@ pub(super) fn increase_indent(self, node: &SyntaxNode) {
}
pub(super) fn clone_increase_indent(self, node: &SyntaxNode) -> SyntaxNode {
let (mut editor, node) = SyntaxEditor::new(node.clone());
let (editor, node) = SyntaxEditor::new(node.clone());
let tokens = node
.preorder_with_tokens()
.filter_map(|event| match event {
@@ -142,7 +142,7 @@ pub(super) fn decrease_indent(self, node: &SyntaxNode) {
}
pub(super) fn clone_decrease_indent(self, node: &SyntaxNode) -> SyntaxNode {
let (mut editor, node) = SyntaxEditor::new(node.clone());
let (editor, node) = SyntaxEditor::new(node.clone());
let tokens = node
.preorder_with_tokens()
.filter_map(|event| match event {
@@ -198,12 +198,8 @@ fn reset_indent(&self) -> Self {
impl<N: AstNode + Clone> AstNodeEdit for N {}
impl ast::IdentPat {
pub fn set_pat(
&self,
pat: Option<ast::Pat>,
syntax_editor: &mut SyntaxEditor,
syntax_factory: &SyntaxFactory,
) -> ast::IdentPat {
pub fn set_pat(&self, pat: Option<ast::Pat>, editor: &SyntaxEditor) -> ast::IdentPat {
let make = editor.make();
match pat {
None => {
if let Some(at_token) = self.at_token() {
@@ -213,7 +209,7 @@ pub fn set_pat(
.pat()
.map(|it| it.syntax().clone().into())
.unwrap_or_else(|| at_token.into());
syntax_editor.delete_all(start..=end);
editor.delete_all(start..=end);
// Remove any trailing ws
if let Some(last) =
@@ -226,28 +222,28 @@ pub fn set_pat(
Some(pat) => {
if let Some(old_pat) = self.pat() {
// Replace existing pattern
syntax_editor.replace(old_pat.syntax(), pat.syntax())
editor.replace(old_pat.syntax(), pat.syntax())
} else if let Some(at_token) = self.at_token() {
// Have an `@` token but not a pattern yet
syntax_editor.insert(Position::after(at_token), pat.syntax());
editor.insert(Position::after(at_token), pat.syntax());
} else {
// Don't have an `@`, should have a name
let name = self.name().unwrap();
let elements = vec![
syntax_factory.whitespace(" ").into(),
syntax_factory.token(T![@]).into(),
syntax_factory.whitespace(" ").into(),
make.whitespace(" ").into(),
make.token(T![@]).into(),
make.whitespace(" ").into(),
pat.syntax().clone().into(),
];
if self.syntax().parent().is_none() {
let (mut local, local_self) = SyntaxEditor::with_ast_node(self);
let (local, local_self) = SyntaxEditor::with_ast_node(self);
let local_name = local_self.name().unwrap();
local.insert_all(Position::after(local_name.syntax()), elements);
let edit = local.finish();
return ast::IdentPat::cast(edit.new_root().clone()).unwrap();
} else {
syntax_editor.insert_all(Position::after(name.syntax()), elements);
editor.insert_all(Position::after(name.syntax()), elements);
}
}
}
@@ -12,6 +12,7 @@
use crate::syntax_editor::SyntaxMapping;
#[derive(Debug)]
pub struct SyntaxFactory {
// Stored in a refcell so that the factory methods can be &self
mappings: Option<RefCell<SyntaxMapping>>,
@@ -19,7 +20,7 @@ pub struct SyntaxFactory {
impl SyntaxFactory {
/// Creates a new [`SyntaxFactory`], generating mappings between input nodes and generated nodes.
pub fn with_mappings() -> Self {
pub(crate) fn with_mappings() -> Self {
Self { mappings: Some(RefCell::new(SyntaxMapping::default())) }
}
@@ -28,13 +29,8 @@ pub fn without_mappings() -> Self {
Self { mappings: None }
}
/// Gets all of the tracked syntax mappings, if any.
pub fn finish_with_mappings(self) -> SyntaxMapping {
self.mappings.unwrap_or_default().into_inner()
}
/// Take all of the tracked syntax mappings, leaving `SyntaxMapping::default()` in its place, if any.
pub fn take(&self) -> SyntaxMapping {
pub(crate) fn take(&self) -> SyntaxMapping {
self.mappings.as_ref().map(|mappings| mappings.take()).unwrap_or_default()
}
@@ -96,7 +96,9 @@ pub fn type_bound_list(
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
builder.map_children(input, ast.bounds().map(|b| b.syntax().clone()));
for (input_node, output_bound) in input.into_iter().zip(ast.bounds()) {
builder.map_node(input_node, output_bound.syntax().clone());
}
builder.finish(&mut mapping);
}
@@ -209,7 +211,7 @@ pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
}
builder.map_children(
params_input,
ast.param_list().unwrap().params().map(|p| p.syntax().clone()),
ast.syntax().children().filter(|c| ast::Param::can_cast(c.kind())),
);
if let Some(ret_type) = ret_type {
builder
@@ -242,13 +244,17 @@ pub fn where_pred(
builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
}
}
builder.finish(&mut mapping);
if let Some(type_bound_list) = ast.type_bound_list() {
builder.map_children(
let mut bounds_builder =
SyntaxMappingBuilder::new(type_bound_list.syntax().clone());
bounds_builder.map_children(
bounds_input,
type_bound_list.bounds().map(|b| b.syntax().clone()),
);
bounds_builder.finish(&mut mapping);
}
builder.finish(&mut mapping);
}
ast
@@ -484,11 +490,13 @@ pub fn generic_ty_path_segment(
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
builder.map_children(
input,
ast.generic_arg_list().unwrap().generic_args().map(|a| a.syntax().clone()),
);
builder.finish(&mut mapping);
let generic_arg_list = ast.generic_arg_list().unwrap();
let mut arg_builder = SyntaxMappingBuilder::new(generic_arg_list.syntax().clone());
arg_builder
.map_children(input, generic_arg_list.generic_args().map(|a| a.syntax().clone()));
arg_builder.finish(&mut mapping);
}
ast
@@ -629,9 +637,16 @@ pub fn path_from_segments(
let ast = make::path_from_segments(segments, is_abs).clone_for_update();
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
builder.map_children(input, ast.segments().map(|it| it.syntax().clone()));
builder.finish(&mut mapping);
let mut current_path = Some(ast.clone());
for input_segment in input.iter().rev() {
let Some(path) = current_path else { break };
if let Some(segment) = path.segment() {
let mut builder = SyntaxMappingBuilder::new(path.syntax().clone());
builder.map_node(input_segment.clone(), segment.syntax().clone());
builder.finish(&mut mapping);
}
current_path = path.qualifier();
}
}
ast
@@ -5,6 +5,7 @@
//! [`SyntaxEditor`]: https://github.com/dotnet/roslyn/blob/43b0b05cc4f492fd5de00f6f6717409091df8daa/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs
use std::{
cell::RefCell,
fmt, iter,
num::NonZeroU32,
ops::RangeInclusive,
@@ -29,9 +30,9 @@
#[derive(Debug)]
pub struct SyntaxEditor {
root: SyntaxNode,
changes: Vec<Change>,
mappings: SyntaxMapping,
annotations: Vec<(SyntaxElement, SyntaxAnnotation)>,
changes: RefCell<Vec<Change>>,
annotations: RefCell<Vec<(SyntaxElement, SyntaxAnnotation)>>,
make: SyntaxFactory,
}
impl SyntaxEditor {
@@ -50,9 +51,9 @@ pub fn new(root: SyntaxNode) -> (Self, SyntaxNode) {
let editor = Self {
root: root.clone(),
changes: Vec::new(),
mappings: SyntaxMapping::default(),
annotations: Vec::new(),
changes: RefCell::new(Vec::new()),
annotations: RefCell::new(Vec::new()),
make: SyntaxFactory::with_mappings(),
};
(editor, root)
@@ -68,20 +69,21 @@ pub fn with_ast_node<T>(root: &T) -> (Self, T)
(editor, T::cast(root).unwrap())
}
pub fn add_annotation(&mut self, element: impl Element, annotation: SyntaxAnnotation) {
self.annotations.push((element.syntax_element(), annotation))
pub fn make(&self) -> &SyntaxFactory {
&self.make
}
pub fn add_annotation_all(
&mut self,
elements: Vec<impl Element>,
annotation: SyntaxAnnotation,
) {
pub fn add_annotation(&self, element: impl Element, annotation: SyntaxAnnotation) {
self.annotations.borrow_mut().push((element.syntax_element(), annotation))
}
pub fn add_annotation_all(&self, elements: Vec<impl Element>, annotation: SyntaxAnnotation) {
self.annotations
.borrow_mut()
.extend(elements.into_iter().map(|e| e.syntax_element()).zip(iter::repeat(annotation)));
}
pub fn merge(&mut self, mut other: SyntaxEditor) {
pub fn merge(&self, other: SyntaxEditor) {
debug_assert!(
self.root == other.root || other.root.ancestors().any(|node| node == self.root),
"{:?} is not in the same tree as {:?}",
@@ -89,102 +91,92 @@ pub fn merge(&mut self, mut other: SyntaxEditor) {
self.root
);
self.changes.append(&mut other.changes);
self.mappings.merge(other.mappings);
self.annotations.append(&mut other.annotations);
self.changes.borrow_mut().append(&mut other.changes.into_inner());
if let Some(mut m) = self.make.mappings() {
m.merge(other.make.take());
}
self.annotations.borrow_mut().append(&mut other.annotations.into_inner());
}
pub fn insert(&mut self, position: Position, element: impl Element) {
pub fn insert(&self, position: Position, element: impl Element) {
debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
self.changes.push(Change::Insert(position, element.syntax_element()))
self.changes.borrow_mut().push(Change::Insert(position, element.syntax_element()))
}
pub fn insert_all(&mut self, position: Position, elements: Vec<SyntaxElement>) {
pub fn insert_all(&self, position: Position, elements: Vec<SyntaxElement>) {
debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
self.changes.push(Change::InsertAll(position, elements))
self.changes.borrow_mut().push(Change::InsertAll(position, elements))
}
pub fn insert_with_whitespace(
&mut self,
position: Position,
element: impl Element,
factory: &SyntaxFactory,
) {
self.insert_all_with_whitespace(position, vec![element.syntax_element()], factory)
pub fn insert_with_whitespace(&self, position: Position, element: impl Element) {
self.insert_all_with_whitespace(position, vec![element.syntax_element()])
}
pub fn insert_all_with_whitespace(
&mut self,
position: Position,
mut elements: Vec<SyntaxElement>,
factory: &SyntaxFactory,
) {
pub fn insert_all_with_whitespace(&self, position: Position, mut elements: Vec<SyntaxElement>) {
if let Some(first) = elements.first()
&& let Some(ws) = ws_before(&position, first, factory)
&& let Some(ws) = ws_before(&position, first, &self.make)
{
elements.insert(0, ws.into());
}
if let Some(last) = elements.last()
&& let Some(ws) = ws_after(&position, last, factory)
&& let Some(ws) = ws_after(&position, last, &self.make)
{
elements.push(ws.into());
}
self.insert_all(position, elements)
}
pub fn delete(&mut self, element: impl Element) {
pub fn delete(&self, element: impl Element) {
let element = element.syntax_element();
debug_assert!(is_ancestor_or_self_of_element(&element, &self.root));
debug_assert!(
!matches!(&element, SyntaxElement::Node(node) if node == &self.root),
"should not delete root node"
);
self.changes.push(Change::Replace(element.syntax_element(), None));
self.changes.borrow_mut().push(Change::Replace(element.syntax_element(), None));
}
pub fn delete_all(&mut self, range: RangeInclusive<SyntaxElement>) {
pub fn delete_all(&self, range: RangeInclusive<SyntaxElement>) {
if range.start() == range.end() {
self.delete(range.start());
return;
}
debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
self.changes.push(Change::ReplaceAll(range, Vec::new()))
self.changes.borrow_mut().push(Change::ReplaceAll(range, Vec::new()))
}
pub fn replace(&mut self, old: impl Element, new: impl Element) {
pub fn replace(&self, old: impl Element, new: impl Element) {
let old = old.syntax_element();
debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element())));
self.changes
.borrow_mut()
.push(Change::Replace(old.syntax_element(), Some(new.syntax_element())));
}
pub fn replace_with_many(&mut self, old: impl Element, new: Vec<SyntaxElement>) {
pub fn replace_with_many(&self, old: impl Element, new: Vec<SyntaxElement>) {
let old = old.syntax_element();
debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
debug_assert!(
!(matches!(&old, SyntaxElement::Node(node) if node == &self.root) && new.len() > 1),
"cannot replace root node with many elements"
);
self.changes.push(Change::ReplaceWithMany(old.syntax_element(), new));
self.changes.borrow_mut().push(Change::ReplaceWithMany(old.syntax_element(), new));
}
pub fn replace_all(&mut self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
pub fn replace_all(&self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
if range.start() == range.end() {
self.replace_with_many(range.start(), new);
return;
}
debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
self.changes.push(Change::ReplaceAll(range, new))
self.changes.borrow_mut().push(Change::ReplaceAll(range, new))
}
pub fn finish(self) -> SyntaxEdit {
edit_algo::apply_edits(self)
}
pub fn add_mappings(&mut self, other: SyntaxMapping) {
self.mappings.merge(other);
}
}
/// Represents a completed [`SyntaxEditor`] operation.
@@ -538,7 +530,7 @@ mod tests {
use crate::{
AstNode,
ast::{self, make, syntax_factory::SyntaxFactory},
ast::{self, make},
};
use super::*;
@@ -559,13 +551,12 @@ fn basic_usage() {
.into(),
);
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
let (editor, root) = SyntaxEditor::with_ast_node(&root);
let make = editor.make();
let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap();
let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap();
let make = SyntaxFactory::with_mappings();
let name = make::name("var_name");
let name_ref = make::name_ref("var_name").clone_for_update();
@@ -574,7 +565,8 @@ fn basic_usage() {
editor.add_annotation(name_ref.syntax(), placeholder_snippet);
let new_block = make.block_expr(
[make
[editor
.make()
.let_stmt(
make.ident_pat(false, false, name.clone()).into(),
None,
@@ -586,7 +578,6 @@ fn basic_usage() {
editor.replace(to_replace.syntax(), name_ref.syntax());
editor.replace(to_wrap.syntax(), new_block.syntax());
editor.add_mappings(make.finish_with_mappings());
let edit = editor.finish();
@@ -618,9 +609,9 @@ fn test_insert_independent() {
None,
);
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
let (editor, root) = SyntaxEditor::with_ast_node(&root);
let make = editor.make();
let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
let make = SyntaxFactory::without_mappings();
editor.insert(
Position::first_child_of(root.stmt_list().unwrap().syntax()),
@@ -669,14 +660,13 @@ fn test_insert_dependent() {
),
);
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
let (editor, root) = SyntaxEditor::with_ast_node(&root);
let make = editor.make();
let inner_block =
root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap();
let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
let make = SyntaxFactory::with_mappings();
let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
let first_let = make.let_stmt(
@@ -697,7 +687,6 @@ fn test_insert_dependent() {
);
editor.insert(Position::after(second_let.syntax()), third_let.syntax());
editor.replace(inner_block.syntax(), new_block_expr.syntax());
editor.add_mappings(make.finish_with_mappings());
let edit = editor.finish();
@@ -724,10 +713,10 @@ fn test_replace_root_with_dependent() {
None,
);
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
let (editor, root) = SyntaxEditor::with_ast_node(&root);
let make = editor.make();
let inner_block = root;
let make = SyntaxFactory::with_mappings();
let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
@@ -742,7 +731,6 @@ fn test_replace_root_with_dependent() {
first_let.syntax(),
);
editor.replace(inner_block.syntax(), new_block_expr.syntax());
editor.add_mappings(make.finish_with_mappings());
let edit = editor.finish();
@@ -772,7 +760,7 @@ fn test_replace_token_in_parent() {
false,
);
let (mut editor, parent_fn) = SyntaxEditor::with_ast_node(&parent_fn);
let (editor, parent_fn) = SyntaxEditor::with_ast_node(&parent_fn);
if let Some(ret_ty) = parent_fn.ret_type() {
editor.delete(ret_ty.syntax().clone());
@@ -799,7 +787,7 @@ fn test_more_times_replace_node_to_mutable_token() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let target_expr = make::token(parser::SyntaxKind::UNDERSCORE);
@@ -818,7 +806,7 @@ fn test_more_times_replace_node_to_mutable() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let target_expr = make::expr_literal("3").clone_for_update();
@@ -837,7 +825,7 @@ fn test_more_times_insert_node_to_mutable() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
let target_expr = make::ext::expr_unit().clone_for_update();
@@ -35,7 +35,10 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
// - changed nodes become part of the changed node set (useful for the formatter to only change those parts)
// - Propagate annotations
let SyntaxEditor { root, mut changes, mappings, annotations } = editor;
let SyntaxEditor { root, changes, annotations, make } = editor;
let mut changes = changes.into_inner();
let annotations = annotations.into_inner();
let mappings = make.take();
let mut node_depths = FxHashMap::<SyntaxNode, usize>::default();
let mut get_node_depth = |node: SyntaxNode| {
@@ -3,10 +3,7 @@
use crate::{
AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
algo::neighbor,
ast::{
self, AstNode, Fn, GenericParam, HasGenericParams, HasName, edit::IndentLevel, make,
syntax_factory::SyntaxFactory,
},
ast::{self, AstNode, Fn, GenericParam, HasGenericParams, HasName, edit::IndentLevel, make},
syntax_editor::{Position, SyntaxEditor},
};
@@ -15,10 +12,10 @@ pub trait GetOrCreateWhereClause: ast::HasGenericParams {
fn get_or_create_where_clause(
&self,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
new_preds: impl Iterator<Item = ast::WherePred>,
) {
let make = editor.make();
let existing = self.where_clause();
let all_preds: Vec<_> =
existing.iter().flat_map(|wc| wc.predicates()).chain(new_preds).collect();
@@ -113,7 +110,7 @@ fn where_clause_position(&self) -> Option<Position> {
impl SyntaxEditor {
/// Adds a new generic param to the function using `SyntaxEditor`
pub fn add_generic_param(&mut self, function: &Fn, new_param: GenericParam) {
pub fn add_generic_param(&self, function: &Fn, new_param: GenericParam) {
match function.generic_param_list() {
Some(generic_param_list) => match generic_param_list.generic_params().last() {
Some(last_param) => {
@@ -177,8 +174,8 @@ pub fn add_generic_param(&mut self, function: &Fn, new_param: GenericParam) {
}
}
fn get_or_insert_comma_after(editor: &mut SyntaxEditor, syntax: &SyntaxNode) -> SyntaxToken {
let make = SyntaxFactory::without_mappings();
fn get_or_insert_comma_after(editor: &SyntaxEditor, syntax: &SyntaxNode) -> SyntaxToken {
let make = editor.make();
match syntax
.siblings_with_tokens(Direction::Next)
.filter_map(|it| it.into_token())
@@ -198,7 +195,7 @@ impl ast::AssocItemList {
///
/// Attention! This function does align the first line of `item` with respect to `self`,
/// but it does _not_ change indentation of other lines (if any).
pub fn add_items(&self, editor: &mut SyntaxEditor, items: Vec<ast::AssocItem>) {
pub fn add_items(&self, editor: &SyntaxEditor, items: Vec<ast::AssocItem>) {
let (indent, position, whitespace) = match self.assoc_items().last() {
Some(last_item) => (
IndentLevel::from_node(last_item.syntax()),
@@ -232,9 +229,9 @@ pub fn add_items(&self, editor: &mut SyntaxEditor, items: Vec<ast::AssocItem>) {
impl ast::Impl {
pub fn get_or_create_assoc_item_list_with_editor(
&self,
editor: &mut SyntaxEditor,
make: &SyntaxFactory,
editor: &SyntaxEditor,
) -> ast::AssocItemList {
let make = editor.make();
if let Some(list) = self.assoc_item_list() {
list
} else {
@@ -249,8 +246,8 @@ pub fn get_or_create_assoc_item_list_with_editor(
}
impl ast::VariantList {
pub fn add_variant(&self, editor: &mut SyntaxEditor, variant: &ast::Variant) {
let make = SyntaxFactory::without_mappings();
pub fn add_variant(&self, editor: &SyntaxEditor, variant: &ast::Variant) {
let make = editor.make();
let (indent, position) = match self.variants().last() {
Some(last_item) => (
IndentLevel::from_node(last_item.syntax()),
@@ -274,7 +271,7 @@ pub fn add_variant(&self, editor: &mut SyntaxEditor, variant: &ast::Variant) {
}
impl ast::Fn {
pub fn replace_or_insert_body(&self, editor: &mut SyntaxEditor, body: ast::BlockExpr) {
pub fn replace_or_insert_body(&self, editor: &SyntaxEditor, body: ast::BlockExpr) {
if let Some(old_body) = self.body() {
editor.replace(old_body.syntax(), body.syntax());
} else {
@@ -290,8 +287,8 @@ pub fn replace_or_insert_body(&self, editor: &mut SyntaxEditor, body: ast::Block
}
}
fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) -> Option<()> {
let make = SyntaxFactory::without_mappings();
fn normalize_ws_between_braces(editor: &SyntaxEditor, node: &SyntaxNode) -> Option<()> {
let make = editor.make();
let l = node
.children_with_tokens()
.filter_map(|it| it.into_token())
@@ -318,11 +315,11 @@ fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) ->
}
pub trait Removable: AstNode {
fn remove(&self, editor: &mut SyntaxEditor);
fn remove(&self, editor: &SyntaxEditor);
}
impl Removable for ast::TypeBoundList {
fn remove(&self, editor: &mut SyntaxEditor) {
fn remove(&self, editor: &SyntaxEditor) {
match self.syntax().siblings_with_tokens(Direction::Prev).find(|it| it.kind() == T![:]) {
Some(colon) => editor.delete_all(colon..=self.syntax().clone().into()),
None => editor.delete(self.syntax()),
@@ -331,9 +328,8 @@ fn remove(&self, editor: &mut SyntaxEditor) {
}
impl Removable for ast::Use {
fn remove(&self, editor: &mut SyntaxEditor) {
let make = SyntaxFactory::without_mappings();
fn remove(&self, editor: &SyntaxEditor) {
let make = editor.make();
let next_ws = self
.syntax()
.next_sibling_or_token()
@@ -355,7 +351,7 @@ fn remove(&self, editor: &mut SyntaxEditor) {
}
impl Removable for ast::UseTree {
fn remove(&self, editor: &mut SyntaxEditor) {
fn remove(&self, editor: &SyntaxEditor) {
for dir in [Direction::Next, Direction::Prev] {
if let Some(next_use_tree) = neighbor(self, dir) {
let separators = self
@@ -379,7 +375,7 @@ mod tests {
use stdx::trim_indent;
use test_utils::assert_eq_text;
use crate::SourceFile;
use crate::{SourceFile, ast::syntax_factory::SyntaxFactory};
use super::*;
@@ -492,9 +488,9 @@ enum Foo {
}
fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) {
let (mut editor, enum_) = SyntaxEditor::with_ast_node(&ast_from_text::<ast::Enum>(before));
let (editor, enum_) = SyntaxEditor::with_ast_node(&ast_from_text::<ast::Enum>(before));
if let Some(it) = enum_.variant_list() {
it.add_variant(&mut editor, &variant)
it.add_variant(&editor, &variant)
}
let edit = editor.finish();
let after = edit.new_root.to_string();