mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-30 21:16:27 +03:00
Merge pull request #21826 from Shourya742/2026-02-03-migrate-utils-to-new-syntax-editor
Replace make usage with SyntaxFactory in few ide-assists utils methods
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
use ide_db::{famous_defs::FamousDefs, syntax_helpers::suggest_name};
|
||||
use syntax::{
|
||||
AstNode,
|
||||
ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel, make, syntax_factory::SyntaxFactory},
|
||||
ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel, syntax_factory::SyntaxFactory},
|
||||
syntax_editor::Position,
|
||||
};
|
||||
|
||||
@@ -57,13 +57,13 @@ pub(crate) fn convert_for_loop_to_while_let(
|
||||
{
|
||||
(expr, Some(make.name_ref(method.as_str())))
|
||||
} else if let ast::Expr::RefExpr(_) = iterable {
|
||||
(make::expr_paren(iterable).into(), Some(make.name_ref("into_iter")))
|
||||
(make.expr_paren(iterable).into(), Some(make.name_ref("into_iter")))
|
||||
} else {
|
||||
(iterable, Some(make.name_ref("into_iter")))
|
||||
};
|
||||
|
||||
let iterable = if let Some(method) = method {
|
||||
make::expr_method_call(iterable, method, make::arg_list([])).into()
|
||||
make.expr_method_call(iterable, method, make.arg_list([])).into()
|
||||
} else {
|
||||
iterable
|
||||
};
|
||||
@@ -89,17 +89,18 @@ pub(crate) fn convert_for_loop_to_while_let(
|
||||
for_loop.syntax(),
|
||||
&mut editor,
|
||||
for_loop.attrs().map(|it| it.clone_for_update()),
|
||||
&make,
|
||||
);
|
||||
|
||||
editor.insert(
|
||||
Position::before(for_loop.syntax()),
|
||||
make::tokens::whitespace(format!("\n{indent}").as_str()),
|
||||
make.whitespace(format!("\n{indent}").as_str()),
|
||||
);
|
||||
editor.insert(Position::before(for_loop.syntax()), mut_expr.syntax());
|
||||
|
||||
let opt_pat = make.tuple_struct_pat(make::ext::ident_path("Some"), [pat]);
|
||||
let opt_pat = make.tuple_struct_pat(make.ident_path("Some"), [pat]);
|
||||
let iter_next_expr = make.expr_method_call(
|
||||
make.expr_path(make::ext::ident_path(&tmp_var)),
|
||||
make.expr_path(make.ident_path(&tmp_var)),
|
||||
make.name_ref("next"),
|
||||
make.arg_list([]),
|
||||
);
|
||||
|
||||
+28
-21
@@ -10,14 +10,14 @@
|
||||
ast::{
|
||||
self,
|
||||
edit::{AstNodeEdit, IndentLevel},
|
||||
make,
|
||||
syntax_factory::SyntaxFactory,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AssistId,
|
||||
assist_context::{AssistContext, Assists},
|
||||
utils::{invert_boolean_expression_legacy, is_never_block},
|
||||
utils::{invert_boolean_expression, is_never_block},
|
||||
};
|
||||
|
||||
// Assist: convert_to_guarded_return
|
||||
@@ -69,6 +69,7 @@ fn if_expr_to_guarded_return(
|
||||
acc: &mut Assists,
|
||||
ctx: &AssistContext<'_>,
|
||||
) -> Option<()> {
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
let else_block = match if_expr.else_branch() {
|
||||
Some(ast::ElseBranch::Block(block_expr)) if is_never_block(&ctx.sema, &block_expr) => {
|
||||
Some(block_expr)
|
||||
@@ -88,7 +89,7 @@ fn if_expr_to_guarded_return(
|
||||
return None;
|
||||
}
|
||||
|
||||
let let_chains = flat_let_chain(cond);
|
||||
let let_chains = flat_let_chain(cond, &make);
|
||||
|
||||
let then_branch = if_expr.then_branch()?;
|
||||
let then_block = then_branch.stmt_list()?;
|
||||
@@ -110,7 +111,8 @@ fn if_expr_to_guarded_return(
|
||||
|
||||
let early_expression = else_block
|
||||
.or_else(|| {
|
||||
early_expression(parent_container, &ctx.sema).map(ast::make::tail_only_block_expr)
|
||||
early_expression(parent_container, &ctx.sema, &make)
|
||||
.map(ast::make::tail_only_block_expr)
|
||||
})?
|
||||
.reset_indent();
|
||||
|
||||
@@ -133,6 +135,7 @@ fn if_expr_to_guarded_return(
|
||||
"Convert to guarded return",
|
||||
target,
|
||||
|edit| {
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
let if_indent_level = IndentLevel::from_node(if_expr.syntax());
|
||||
let replacement = let_chains.into_iter().map(|expr| {
|
||||
if let ast::Expr::LetExpr(let_expr) = &expr
|
||||
@@ -140,15 +143,15 @@ fn if_expr_to_guarded_return(
|
||||
{
|
||||
// If-let.
|
||||
let let_else_stmt =
|
||||
make::let_else_stmt(pat, None, expr, early_expression.clone());
|
||||
make.let_else_stmt(pat, None, expr, early_expression.clone());
|
||||
let let_else_stmt = let_else_stmt.indent(if_indent_level);
|
||||
let_else_stmt.syntax().clone()
|
||||
} else {
|
||||
// If.
|
||||
let new_expr = {
|
||||
let then_branch = clean_stmt_block(&early_expression);
|
||||
let cond = invert_boolean_expression_legacy(expr);
|
||||
make::expr_if(cond, then_branch, None).indent(if_indent_level)
|
||||
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()
|
||||
}
|
||||
@@ -159,7 +162,7 @@ fn if_expr_to_guarded_return(
|
||||
.enumerate()
|
||||
.flat_map(|(i, node)| {
|
||||
(i != 0)
|
||||
.then(|| make::tokens::whitespace(newline).into())
|
||||
.then(|| make.whitespace(newline).into())
|
||||
.into_iter()
|
||||
.chain(node.children_with_tokens())
|
||||
})
|
||||
@@ -201,12 +204,13 @@ fn let_stmt_to_guarded_return(
|
||||
let happy_pattern = try_enum.happy_pattern(pat);
|
||||
let target = let_stmt.syntax().text_range();
|
||||
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
let early_expression: ast::Expr = {
|
||||
let parent_block =
|
||||
let_stmt.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?;
|
||||
let parent_container = parent_block.syntax().parent()?;
|
||||
|
||||
early_expression(parent_container, &ctx.sema)?
|
||||
early_expression(parent_container, &ctx.sema, &make)?
|
||||
};
|
||||
|
||||
acc.add(
|
||||
@@ -215,9 +219,10 @@ fn let_stmt_to_guarded_return(
|
||||
target,
|
||||
|edit| {
|
||||
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(
|
||||
let let_else_stmt = make.let_else_stmt(
|
||||
happy_pattern,
|
||||
let_stmt.ty(),
|
||||
expr.reset_indent(),
|
||||
@@ -228,6 +233,7 @@ fn let_stmt_to_guarded_return(
|
||||
};
|
||||
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);
|
||||
},
|
||||
)
|
||||
@@ -236,38 +242,39 @@ fn let_stmt_to_guarded_return(
|
||||
fn early_expression(
|
||||
parent_container: SyntaxNode,
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
make: &SyntaxFactory,
|
||||
) -> Option<ast::Expr> {
|
||||
let return_none_expr = || {
|
||||
let none_expr = make::expr_path(make::ext::ident_path("None"));
|
||||
make::expr_return(Some(none_expr))
|
||||
let none_expr = make.expr_path(make.ident_path("None"));
|
||||
make.expr_return(Some(none_expr))
|
||||
};
|
||||
if let Some(fn_) = ast::Fn::cast(parent_container.clone())
|
||||
&& let Some(fn_def) = sema.to_def(&fn_)
|
||||
&& let Some(TryEnum::Option) = TryEnum::from_ty(sema, &fn_def.ret_type(sema.db))
|
||||
{
|
||||
return Some(return_none_expr());
|
||||
return Some(return_none_expr().into());
|
||||
}
|
||||
if let Some(body) = ast::ClosureExpr::cast(parent_container.clone()).and_then(|it| it.body())
|
||||
&& let Some(ret_ty) = sema.type_of_expr(&body).map(TypeInfo::original)
|
||||
&& let Some(TryEnum::Option) = TryEnum::from_ty(sema, &ret_ty)
|
||||
{
|
||||
return Some(return_none_expr());
|
||||
return Some(return_none_expr().into());
|
||||
}
|
||||
|
||||
Some(match parent_container.kind() {
|
||||
WHILE_EXPR | LOOP_EXPR | FOR_EXPR => make::expr_continue(None),
|
||||
FN | CLOSURE_EXPR => make::expr_return(None),
|
||||
WHILE_EXPR | LOOP_EXPR | FOR_EXPR => make.expr_continue(None).into(),
|
||||
FN | CLOSURE_EXPR => make.expr_return(None).into(),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
|
||||
fn flat_let_chain(mut expr: ast::Expr, make: &SyntaxFactory) -> Vec<ast::Expr> {
|
||||
let mut chains = vec![];
|
||||
let mut reduce_cond = |rhs| {
|
||||
if !matches!(rhs, ast::Expr::LetExpr(_))
|
||||
&& let Some(last) = chains.pop_if(|last| !matches!(last, ast::Expr::LetExpr(_)))
|
||||
{
|
||||
chains.push(make::expr_bin_op(rhs, ast::BinaryOp::LogicOp(ast::LogicOp::And), last));
|
||||
chains.push(make.expr_bin_op(rhs, ast::BinaryOp::LogicOp(ast::LogicOp::And), last));
|
||||
} else {
|
||||
chains.push(rhs);
|
||||
}
|
||||
@@ -286,12 +293,12 @@ fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
|
||||
chains
|
||||
}
|
||||
|
||||
fn clean_stmt_block(block: &ast::BlockExpr) -> ast::BlockExpr {
|
||||
fn clean_stmt_block(block: &ast::BlockExpr, make: &SyntaxFactory) -> ast::BlockExpr {
|
||||
if block.statements().next().is_none()
|
||||
&& let Some(tail_expr) = block.tail_expr()
|
||||
&& block.modifier().is_none()
|
||||
{
|
||||
make::block_expr(once(make::expr_stmt(tail_expr).into()), None)
|
||||
make.block_expr(once(make.expr_stmt(tail_expr).into()), None)
|
||||
} else {
|
||||
block.clone()
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
ast::{
|
||||
self, HasLoopBody,
|
||||
edit::{AstNodeEdit, IndentLevel},
|
||||
make,
|
||||
syntax_factory::SyntaxFactory,
|
||||
},
|
||||
syntax_editor::{Element, Position},
|
||||
};
|
||||
@@ -14,7 +14,7 @@
|
||||
use crate::{
|
||||
AssistId,
|
||||
assist_context::{AssistContext, Assists},
|
||||
utils::invert_boolean_expression_legacy,
|
||||
utils::invert_boolean_expression,
|
||||
};
|
||||
|
||||
// Assist: convert_while_to_loop
|
||||
@@ -52,44 +52,47 @@ 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 while_indent_level = IndentLevel::from_node(while_expr.syntax());
|
||||
|
||||
let break_block = make::block_expr(
|
||||
iter::once(make::expr_stmt(make::expr_break(None, None)).into()),
|
||||
None,
|
||||
)
|
||||
.indent(IndentLevel(1));
|
||||
let break_block = make
|
||||
.block_expr(
|
||||
iter::once(make.expr_stmt(make.expr_break(None, None).into()).into()),
|
||||
None,
|
||||
)
|
||||
.indent(IndentLevel(1));
|
||||
|
||||
edit.replace_all(
|
||||
while_kw.syntax_element()..=while_cond.syntax().syntax_element(),
|
||||
vec![make::token(T![loop]).syntax_element()],
|
||||
vec![make.token(T![loop]).syntax_element()],
|
||||
);
|
||||
|
||||
if is_pattern_cond(while_cond.clone()) {
|
||||
let then_branch = while_body.reset_indent().indent(IndentLevel(1));
|
||||
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);
|
||||
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());
|
||||
} else {
|
||||
let if_cond = invert_boolean_expression_legacy(while_cond);
|
||||
let if_expr = make::expr_if(if_cond, break_block, None).indent(while_indent_level);
|
||||
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(
|
||||
Position::after(&l_curly),
|
||||
make::tokens::whitespace(&format!("\n{while_indent_level}")),
|
||||
make.whitespace(&format!("\n{while_indent_level}")),
|
||||
);
|
||||
}
|
||||
edit.insert_all(
|
||||
Position::after(&l_curly),
|
||||
vec![
|
||||
make::tokens::whitespace(&format!("\n{}", while_indent_level + 1)).into(),
|
||||
make.whitespace(&format!("\n{}", while_indent_level + 1)).into(),
|
||||
if_expr.syntax().syntax_element(),
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
edit.add_mappings(make.finish_with_mappings());
|
||||
builder.add_file_edits(ctx.vfs_file_id(), edit);
|
||||
},
|
||||
)
|
||||
|
||||
+4
-7
@@ -381,23 +381,20 @@ fn build_usage_edit(
|
||||
Some(field_expr) => Some({
|
||||
let field_name: SmolStr = field_expr.name_ref()?.to_string().into();
|
||||
let new_field_name = field_names.get(&field_name)?;
|
||||
let new_expr = ast::make::expr_path(ast::make::ext::ident_path(new_field_name));
|
||||
let new_expr = make.expr_path(make.ident_path(new_field_name));
|
||||
|
||||
// If struct binding is a reference, we might need to deref field usages
|
||||
if data.is_ref {
|
||||
let (replace_expr, ref_data) = determine_ref_and_parens(ctx, &field_expr);
|
||||
(
|
||||
replace_expr.syntax().clone_for_update(),
|
||||
ref_data.wrap_expr(new_expr).syntax().clone_for_update(),
|
||||
)
|
||||
(replace_expr.syntax().clone(), ref_data.wrap_expr(new_expr, make).syntax().clone())
|
||||
} else {
|
||||
(field_expr.syntax().clone(), new_expr.syntax().clone_for_update())
|
||||
(field_expr.syntax().clone(), new_expr.syntax().clone())
|
||||
}
|
||||
}),
|
||||
None => Some((
|
||||
usage.name.syntax().as_node().unwrap().clone(),
|
||||
make.expr_macro(
|
||||
ast::make::ext::ident_path("todo"),
|
||||
make.ident_path("todo"),
|
||||
make.token_tree(syntax::SyntaxKind::L_PAREN, []),
|
||||
)
|
||||
.syntax()
|
||||
|
||||
+7
-7
@@ -8,7 +8,7 @@
|
||||
AstNode, AstToken, NodeOrToken,
|
||||
SyntaxKind::WHITESPACE,
|
||||
SyntaxToken, T,
|
||||
ast::{self, TokenTree, make, syntax_factory::SyntaxFactory},
|
||||
ast::{self, TokenTree, syntax_factory::SyntaxFactory},
|
||||
};
|
||||
|
||||
// Assist: extract_expressions_from_format_string
|
||||
@@ -57,6 +57,7 @@ pub(crate) fn extract_expressions_from_format_string(
|
||||
"Extract format expressions",
|
||||
tt.syntax().text_range(),
|
||||
|edit| {
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
// 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);
|
||||
@@ -94,14 +95,14 @@ pub(crate) fn extract_expressions_from_format_string(
|
||||
let mut new_tt_bits = raw_tokens;
|
||||
let mut placeholder_indexes = vec![];
|
||||
|
||||
new_tt_bits.push(NodeOrToken::Token(make::tokens::literal(&new_fmt)));
|
||||
new_tt_bits.push(NodeOrToken::Token(make.expr_literal(&new_fmt).token().clone()));
|
||||
|
||||
for arg in extracted_args {
|
||||
if matches!(arg, Arg::Expr(_) | Arg::Placeholder) {
|
||||
// insert ", " before each arg
|
||||
new_tt_bits.extend_from_slice(&[
|
||||
NodeOrToken::Token(make::token(T![,])),
|
||||
NodeOrToken::Token(make::tokens::single_space()),
|
||||
NodeOrToken::Token(make.token(T![,])),
|
||||
NodeOrToken::Token(make.whitespace(" ")),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -109,7 +110,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);
|
||||
let mut expr_tt = utils::tt_from_syntax(expr, &make);
|
||||
new_tt_bits.append(&mut expr_tt);
|
||||
}
|
||||
Arg::Placeholder => {
|
||||
@@ -120,7 +121,7 @@ pub(crate) fn extract_expressions_from_format_string(
|
||||
}
|
||||
None => {
|
||||
placeholder_indexes.push(new_tt_bits.len());
|
||||
new_tt_bits.push(NodeOrToken::Token(make::token(T![_])));
|
||||
new_tt_bits.push(NodeOrToken::Token(make.token(T![_])));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +130,6 @@ pub(crate) fn extract_expressions_from_format_string(
|
||||
}
|
||||
|
||||
// Insert new args
|
||||
let make = SyntaxFactory::with_mappings();
|
||||
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());
|
||||
|
||||
+36
-33
@@ -4,7 +4,7 @@
|
||||
ast::{
|
||||
self, AstNode, HasGenericParams, HasName, HasVisibility as _,
|
||||
edit::{AstNodeEdit, IndentLevel},
|
||||
make,
|
||||
syntax_factory::SyntaxFactory,
|
||||
},
|
||||
syntax_editor::Position,
|
||||
};
|
||||
@@ -100,7 +100,6 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||
let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
|
||||
continue;
|
||||
};
|
||||
let field = make::ext::field_from_idents(["self", &field_name])?;
|
||||
|
||||
acc.add_group(
|
||||
&GroupLabel("Generate delegate methods…".to_owned()),
|
||||
@@ -108,10 +107,14 @@ 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
|
||||
.field_from_idents(["self", &field_name])
|
||||
.expect("always be a valid expression");
|
||||
// Create the function
|
||||
let method_source = match ctx.sema.source(method) {
|
||||
Some(source) => {
|
||||
let v = source.value.clone_for_update();
|
||||
let v = source.value;
|
||||
let source_scope = ctx.sema.scope(v.syntax());
|
||||
let target_scope = ctx.sema.scope(strukt.syntax());
|
||||
if let (Some(s), Some(t)) = (source_scope, target_scope) {
|
||||
@@ -132,42 +135,42 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||
let is_unsafe = method_source.unsafe_token().is_some();
|
||||
let is_gen = method_source.gen_token().is_some();
|
||||
|
||||
let fn_name = make::name(&name);
|
||||
let fn_name = make.name(&name);
|
||||
|
||||
let type_params = method_source.generic_param_list();
|
||||
let where_clause = method_source.where_clause();
|
||||
let params =
|
||||
method_source.param_list().unwrap_or_else(|| make::param_list(None, []));
|
||||
method_source.param_list().unwrap_or_else(|| make.param_list(None, []));
|
||||
|
||||
// compute the `body`
|
||||
let arg_list = method_source
|
||||
.param_list()
|
||||
.map(convert_param_list_to_arg_list)
|
||||
.unwrap_or_else(|| make::arg_list([]));
|
||||
.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 = make.expr_method_call(field, make.name_ref(&name), arg_list).into();
|
||||
let tail_expr_finished =
|
||||
if is_async { make::expr_await(tail_expr) } else { tail_expr };
|
||||
let body = make::block_expr([], Some(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::fn_(
|
||||
None,
|
||||
vis,
|
||||
fn_name,
|
||||
type_params,
|
||||
where_clause,
|
||||
params,
|
||||
body,
|
||||
ret_type,
|
||||
is_async,
|
||||
is_const,
|
||||
is_unsafe,
|
||||
is_gen,
|
||||
)
|
||||
.indent(IndentLevel(1));
|
||||
let f = make
|
||||
.fn_(
|
||||
None,
|
||||
vis,
|
||||
fn_name,
|
||||
type_params,
|
||||
where_clause,
|
||||
params,
|
||||
body,
|
||||
ret_type,
|
||||
is_async,
|
||||
is_const,
|
||||
is_unsafe,
|
||||
is_gen,
|
||||
)
|
||||
.indent(IndentLevel(1));
|
||||
let item = ast::AssocItem::Fn(f.clone());
|
||||
|
||||
let mut editor = edit.make_editor(strukt.syntax());
|
||||
@@ -179,7 +182,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||
Some(item)
|
||||
}
|
||||
None => {
|
||||
let assoc_item_list = make::assoc_item_list(Some(vec![item]));
|
||||
let assoc_item_list = make.assoc_item_list(vec![item]);
|
||||
editor.insert(
|
||||
Position::last_child_of(impl_def.syntax()),
|
||||
assoc_item_list.syntax(),
|
||||
@@ -192,17 +195,16 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||
let ty_params = strukt.generic_param_list();
|
||||
let ty_args = ty_params.as_ref().map(|it| it.to_generic_args());
|
||||
let where_clause = strukt.where_clause();
|
||||
let assoc_item_list = make::assoc_item_list(Some(vec![item]));
|
||||
let assoc_item_list = make.assoc_item_list(vec![item]);
|
||||
|
||||
let impl_def = make::impl_(
|
||||
let impl_def = make.impl_(
|
||||
None,
|
||||
ty_params,
|
||||
ty_args,
|
||||
make::ty_path(make::ext::ident_path(name)),
|
||||
syntax::ast::Type::PathType(make.ty_path(make.ident_path(name))),
|
||||
where_clause,
|
||||
Some(assoc_item_list),
|
||||
)
|
||||
.clone_for_update();
|
||||
);
|
||||
|
||||
// Fixup impl_def indentation
|
||||
let indent = strukt.indent_level();
|
||||
@@ -213,7 +215,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
|
||||
editor.insert_all(
|
||||
Position::after(strukt.syntax()),
|
||||
vec![
|
||||
make::tokens::whitespace(&format!("\n\n{indent}")).into(),
|
||||
make.whitespace(&format!("\n\n{indent}")).into(),
|
||||
impl_def.syntax().clone().into(),
|
||||
],
|
||||
);
|
||||
@@ -227,6 +229,7 @@ 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);
|
||||
},
|
||||
)?;
|
||||
|
||||
@@ -782,7 +782,7 @@ fn func_assoc_item(
|
||||
};
|
||||
|
||||
// Build argument list with self expression prepended
|
||||
let other_args = convert_param_list_to_arg_list(l);
|
||||
let other_args = convert_param_list_to_arg_list(l, &make);
|
||||
let all_args: Vec<ast::Expr> =
|
||||
std::iter::once(tail_expr_self).chain(other_args.args()).collect();
|
||||
let args = make.arg_list(all_args);
|
||||
@@ -790,13 +790,13 @@ fn func_assoc_item(
|
||||
make.expr_call(make.expr_path(qualified_path), args).into()
|
||||
}
|
||||
None => make
|
||||
.expr_call(make.expr_path(qualified_path), convert_param_list_to_arg_list(l))
|
||||
.expr_call(make.expr_path(qualified_path), convert_param_list_to_arg_list(l, &make))
|
||||
.into(),
|
||||
},
|
||||
None => make
|
||||
.expr_call(
|
||||
make.expr_path(qualified_path),
|
||||
convert_param_list_to_arg_list(make.param_list(None, Vec::new())),
|
||||
convert_param_list_to_arg_list(make.param_list(None, Vec::new()), &make),
|
||||
)
|
||||
.into(),
|
||||
};
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use ide_db::syntax_helpers::node_ext::is_pattern_cond;
|
||||
use syntax::{
|
||||
T,
|
||||
ast::{self, AstNode},
|
||||
ast::{self, AstNode, syntax_factory::SyntaxFactory},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AssistId,
|
||||
assist_context::{AssistContext, Assists},
|
||||
utils::invert_boolean_expression_legacy,
|
||||
utils::invert_boolean_expression,
|
||||
};
|
||||
|
||||
// Assist: invert_if
|
||||
@@ -50,7 +50,8 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
|
||||
};
|
||||
|
||||
acc.add(AssistId::refactor_rewrite("invert_if"), "Invert if", if_range, |edit| {
|
||||
let flip_cond = invert_boolean_expression_legacy(cond.clone());
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
let flip_cond = invert_boolean_expression(&make, cond.clone());
|
||||
edit.replace_ast(cond, flip_cond);
|
||||
|
||||
let else_node = else_block.syntax();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
SyntaxKind::WHITESPACE,
|
||||
TextRange,
|
||||
ast::{
|
||||
AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make,
|
||||
AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit,
|
||||
prec::ExprPrecedence, syntax_factory::SyntaxFactory,
|
||||
},
|
||||
syntax_editor::Element,
|
||||
@@ -53,14 +53,15 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
|
||||
let space_after_arrow = match_arm.fat_arrow_token()?.next_sibling_or_token();
|
||||
|
||||
let arm_expr = match_arm.expr()?;
|
||||
let make = SyntaxFactory::without_mappings();
|
||||
let if_branch = chain([&match_arm], &rest_arms)
|
||||
.rfold(None, |else_branch, arm| {
|
||||
if let Some(guard) = arm.guard() {
|
||||
let then_branch = crate::utils::wrap_block(&arm.expr()?);
|
||||
let then_branch = crate::utils::wrap_block(&arm.expr()?, &make);
|
||||
let guard_condition = guard.condition()?.reset_indent();
|
||||
Some(make::expr_if(guard_condition, then_branch, else_branch).into())
|
||||
Some(make.expr_if(guard_condition, then_branch, else_branch).into())
|
||||
} else {
|
||||
arm.expr().map(|it| crate::utils::wrap_block(&it).into())
|
||||
arm.expr().map(|it| crate::utils::wrap_block(&it, &make).into())
|
||||
}
|
||||
})?
|
||||
.indent(arm_expr.indent_level());
|
||||
@@ -84,7 +85,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
|
||||
if let Some(element) = space_after_arrow
|
||||
&& element.kind() == WHITESPACE
|
||||
{
|
||||
edit.replace(element, make::tokens::single_space());
|
||||
edit.replace(element, make.whitespace(" "));
|
||||
}
|
||||
|
||||
edit.delete(guard.syntax());
|
||||
|
||||
@@ -86,14 +86,14 @@ pub fn extract_trivial_expression(block_expr: &ast::BlockExpr) -> Option<ast::Ex
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn wrap_block(expr: &ast::Expr) -> ast::BlockExpr {
|
||||
pub(crate) fn wrap_block(expr: &ast::Expr, make: &SyntaxFactory) -> ast::BlockExpr {
|
||||
if let ast::Expr::BlockExpr(block) = expr
|
||||
&& let Some(first) = block.syntax().first_token()
|
||||
&& first.kind() == T!['{']
|
||||
{
|
||||
block.reset_indent()
|
||||
} else {
|
||||
make::block_expr(None, Some(expr.reset_indent().indent(1.into())))
|
||||
make.block_expr(None, Some(expr.reset_indent().indent(1.into())))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,11 +275,6 @@ pub(crate) fn invert_boolean_expression(make: &SyntaxFactory, expr: ast::Expr) -
|
||||
invert_special_case(make, &expr).unwrap_or_else(|| make.expr_prefix(T![!], expr).into())
|
||||
}
|
||||
|
||||
// FIXME: Migrate usages of this function to the above function and remove this.
|
||||
pub(crate) fn invert_boolean_expression_legacy(expr: ast::Expr) -> ast::Expr {
|
||||
invert_special_case_legacy(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr).into())
|
||||
}
|
||||
|
||||
fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Expr> {
|
||||
match expr {
|
||||
ast::Expr::BinExpr(bin) => {
|
||||
@@ -343,62 +338,11 @@ fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Ex
|
||||
}
|
||||
}
|
||||
|
||||
fn invert_special_case_legacy(expr: &ast::Expr) -> Option<ast::Expr> {
|
||||
match expr {
|
||||
ast::Expr::BinExpr(bin) => {
|
||||
let bin = bin.clone_subtree();
|
||||
let op_token = bin.op_token()?;
|
||||
let rev_token = match op_token.kind() {
|
||||
T![==] => T![!=],
|
||||
T![!=] => T![==],
|
||||
T![<] => T![>=],
|
||||
T![<=] => T![>],
|
||||
T![>] => T![<=],
|
||||
T![>=] => T![<],
|
||||
// Parenthesize other expressions before prefixing `!`
|
||||
_ => {
|
||||
return Some(
|
||||
make::expr_prefix(T![!], make::expr_paren(expr.clone()).into()).into(),
|
||||
);
|
||||
}
|
||||
};
|
||||
let mut bin_editor = SyntaxEditor::new(bin.syntax().clone());
|
||||
bin_editor.replace(op_token, make::token(rev_token));
|
||||
ast::Expr::cast(bin_editor.finish().new_root().clone())
|
||||
}
|
||||
ast::Expr::MethodCallExpr(mce) => {
|
||||
let receiver = mce.receiver()?;
|
||||
let method = mce.name_ref()?;
|
||||
let arg_list = mce.arg_list()?;
|
||||
|
||||
let method = match method.text().as_str() {
|
||||
"is_some" => "is_none",
|
||||
"is_none" => "is_some",
|
||||
"is_ok" => "is_err",
|
||||
"is_err" => "is_ok",
|
||||
_ => return None,
|
||||
};
|
||||
Some(make::expr_method_call(receiver, make::name_ref(method), arg_list).into())
|
||||
}
|
||||
ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::UnaryOp::Not => match pe.expr()? {
|
||||
ast::Expr::ParenExpr(parexpr) => parexpr.expr(),
|
||||
_ => pe.expr(),
|
||||
},
|
||||
ast::Expr::Literal(lit) => match lit.kind() {
|
||||
ast::LiteralKind::Bool(b) => match b {
|
||||
true => Some(ast::Expr::Literal(make::expr_literal("false"))),
|
||||
false => Some(ast::Expr::Literal(make::expr_literal("true"))),
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_attributes(
|
||||
before: impl Element,
|
||||
edit: &mut SyntaxEditor,
|
||||
attrs: impl IntoIterator<Item = ast::Attr>,
|
||||
make: &SyntaxFactory,
|
||||
) {
|
||||
let mut attrs = attrs.into_iter().peekable();
|
||||
if attrs.peek().is_none() {
|
||||
@@ -410,9 +354,7 @@ pub(crate) fn insert_attributes(
|
||||
edit.insert_all(
|
||||
syntax::syntax_editor::Position::before(elem),
|
||||
attrs
|
||||
.flat_map(|attr| {
|
||||
[attr.syntax().clone().into(), make::tokens::whitespace(&whitespace).into()]
|
||||
})
|
||||
.flat_map(|attr| [attr.syntax().clone().into(), make.whitespace(&whitespace).into()])
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
@@ -1095,18 +1037,21 @@ pub(crate) fn trimmed_text_range(source_file: &SourceFile, initial_range: TextRa
|
||||
|
||||
/// Convert a list of function params to a list of arguments that can be passed
|
||||
/// into a function call.
|
||||
pub(crate) fn convert_param_list_to_arg_list(list: ast::ParamList) -> ast::ArgList {
|
||||
pub(crate) fn convert_param_list_to_arg_list(
|
||||
list: ast::ParamList,
|
||||
make: &SyntaxFactory,
|
||||
) -> ast::ArgList {
|
||||
let mut args = vec![];
|
||||
for param in list.params() {
|
||||
if let Some(ast::Pat::IdentPat(pat)) = param.pat()
|
||||
&& let Some(name) = pat.name()
|
||||
{
|
||||
let name = name.to_string();
|
||||
let expr = make::expr_path(make::ext::ident_path(&name));
|
||||
let expr = make.expr_path(make.ident_path(&name));
|
||||
args.push(expr);
|
||||
}
|
||||
}
|
||||
make::arg_list(args)
|
||||
make.arg_list(args)
|
||||
}
|
||||
|
||||
/// Calculate the number of hashes required for a raw string containing `s`
|
||||
@@ -1191,7 +1136,10 @@ pub(crate) fn replace_record_field_expr(
|
||||
|
||||
/// Creates a token tree list from a syntax node, creating the needed delimited sub token trees.
|
||||
/// Assumes that the input syntax node is a valid syntax tree.
|
||||
pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree, SyntaxToken>> {
|
||||
pub(crate) fn tt_from_syntax(
|
||||
node: SyntaxNode,
|
||||
make: &SyntaxFactory,
|
||||
) -> Vec<NodeOrToken<ast::TokenTree, SyntaxToken>> {
|
||||
let mut tt_stack = vec![(None, vec![])];
|
||||
|
||||
for element in node.descendants_with_tokens() {
|
||||
@@ -1219,7 +1167,7 @@ pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree
|
||||
"mismatched opening and closing delimiters"
|
||||
);
|
||||
|
||||
let sub_tt = make::token_tree(delimiter.expect("unbalanced delimiters"), tt);
|
||||
let sub_tt = make.token_tree(delimiter.expect("unbalanced delimiters"), tt);
|
||||
parent_tt.push(NodeOrToken::Node(sub_tt));
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! based on the parent of the existing expression.
|
||||
use syntax::{
|
||||
AstNode, T,
|
||||
ast::{self, FieldExpr, MethodCallExpr, make, syntax_factory::SyntaxFactory},
|
||||
ast::{self, FieldExpr, MethodCallExpr, syntax_factory::SyntaxFactory},
|
||||
};
|
||||
|
||||
use crate::AssistContext;
|
||||
@@ -119,13 +119,13 @@ pub(crate) struct RefData {
|
||||
|
||||
impl RefData {
|
||||
/// Derefs `expr` and wraps it in parens if necessary
|
||||
pub(crate) fn wrap_expr(&self, mut expr: ast::Expr) -> ast::Expr {
|
||||
pub(crate) fn wrap_expr(&self, mut expr: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
|
||||
if self.needs_deref {
|
||||
expr = make::expr_prefix(T![*], expr).into();
|
||||
expr = make.expr_prefix(T![*], expr).into();
|
||||
}
|
||||
|
||||
if self.needs_parentheses {
|
||||
expr = make::expr_paren(expr).into();
|
||||
expr = make.expr_paren(expr).into();
|
||||
}
|
||||
|
||||
expr
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
|
||||
ast::{
|
||||
self, HasArgList, HasAttrs, HasGenericArgs, HasGenericParams, HasLoopBody, HasName,
|
||||
HasTypeBounds, HasVisibility, Param, RangeItem, make,
|
||||
HasTypeBounds, HasVisibility, Lifetime, Param, RangeItem, make,
|
||||
},
|
||||
syntax_editor::SyntaxMappingBuilder,
|
||||
};
|
||||
@@ -1765,6 +1765,65 @@ pub fn ty_ref(&self, ty: ast::Type, is_mut: bool) -> ast::Type {
|
||||
}
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn field_from_idents<'a>(
|
||||
&self,
|
||||
parts: impl std::iter::IntoIterator<Item = &'a str>,
|
||||
) -> Option<ast::Expr> {
|
||||
make::ext::field_from_idents(parts)
|
||||
}
|
||||
|
||||
pub fn expr_await(&self, expr: ast::Expr) -> ast::AwaitExpr {
|
||||
let ast::Expr::AwaitExpr(ast) = make::expr_await(expr.clone()).clone_for_update() else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_break(&self, label: Option<Lifetime>, expr: Option<ast::Expr>) -> ast::BreakExpr {
|
||||
let ast::Expr::BreakExpr(ast) =
|
||||
make::expr_break(label.clone(), expr.clone()).clone_for_update()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
if let Some(label) = label {
|
||||
builder.map_node(label.syntax().clone(), ast.lifetime().unwrap().syntax().clone());
|
||||
}
|
||||
if let Some(expr) = expr {
|
||||
builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
|
||||
}
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
pub fn expr_continue(&self, label: Option<Lifetime>) -> ast::ContinueExpr {
|
||||
let ast::Expr::ContinueExpr(ast) = make::expr_continue(label.clone()).clone_for_update()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if let Some(mut mapping) = self.mappings() {
|
||||
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
|
||||
if let Some(label) = label {
|
||||
builder.map_node(label.syntax().clone(), ast.lifetime().unwrap().syntax().clone());
|
||||
}
|
||||
builder.finish(&mut mapping);
|
||||
}
|
||||
|
||||
ast
|
||||
}
|
||||
}
|
||||
|
||||
// `ext` constructors
|
||||
|
||||
Reference in New Issue
Block a user