mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 01:42:54 +03:00
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:
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+4
-10
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+4
-5
@@ -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);
|
||||
},
|
||||
|
||||
+77
-85
@@ -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(_)
|
||||
|
||||
+6
-5
@@ -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()
|
||||
|
||||
+29
-31
@@ -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![,]
|
||||
{
|
||||
|
||||
+14
-23
@@ -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());
|
||||
}
|
||||
|
||||
+15
-17
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-59
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-15
@@ -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);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
+14
-20
@@ -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()]);
|
||||
|
||||
+17
-23
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+4
-5
@@ -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);
|
||||
},
|
||||
);
|
||||
|
||||
+15
-36
@@ -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);
|
||||
|
||||
+7
-10
@@ -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);
|
||||
},
|
||||
);
|
||||
|
||||
+3
-3
@@ -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![
|
||||
|
||||
+10
-9
@@ -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);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
+3
-4
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+33
-27
@@ -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()) {
|
||||
|
||||
+18
-17
@@ -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);
|
||||
})
|
||||
}
|
||||
|
||||
+10
-12
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+12
-15
@@ -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()
|
||||
|
||||
+28
-28
@@ -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);
|
||||
|
||||
+3
-4
@@ -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);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
+15
-15
@@ -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())
|
||||
|
||||
+15
-17
@@ -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()))
|
||||
|
||||
+9
-9
@@ -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);
|
||||
},
|
||||
)
|
||||
|
||||
+2
-3
@@ -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() {
|
||||
|
||||
+5
-5
@@ -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);
|
||||
})
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user