From 72c6b0714142f45b7c8989b2bc54de22c4a38c6d Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Tue, 30 Dec 2025 10:57:15 +0800 Subject: [PATCH] Migrate `move_arm_cond_to_match_guard` assist to use `SyntaxEditor` --- .../ide-assists/src/handlers/move_guard.rs | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs index 8daf86923d92..1c0c6e43d53b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs @@ -1,6 +1,11 @@ +use itertools::Itertools; use syntax::{ SyntaxKind::WHITESPACE, - ast::{AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make}, + ast::{ + AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make, + syntax_factory::SyntaxFactory, + }, + syntax_editor::Element, }; use crate::{AssistContext, AssistId, Assists}; @@ -131,8 +136,10 @@ pub(crate) fn move_arm_cond_to_match_guard( AssistId::refactor_rewrite("move_arm_cond_to_match_guard"), "Move condition to match guard", replace_node.text_range(), - |edit| { - edit.delete(match_arm.syntax().text_range()); + |builder| { + let make = SyntaxFactory::without_mappings(); + let mut replace_arms = vec![]; + // Dedent if if_expr is in a BlockExpr let dedent = if needs_dedent { cov_mark::hit!(move_guard_ifelse_in_block); @@ -141,47 +148,30 @@ pub(crate) fn move_arm_cond_to_match_guard( cov_mark::hit!(move_guard_ifelse_else_block); 0 }; - let then_arm_end = match_arm.syntax().text_range().end(); let indent_level = match_arm.indent_level(); - let spaces = indent_level; - let mut first = true; for (cond, block) in conds_blocks { - if !first { - edit.insert(then_arm_end, format!("\n{spaces}")); - } else { - first = false; - } - let guard = format!("{match_pat} if {cond} => "); - edit.insert(then_arm_end, guard); let only_expr = block.statements().next().is_none(); - match &block.tail_expr() { - Some(then_expr) if only_expr => { - edit.insert(then_arm_end, then_expr.syntax().text()); - edit.insert(then_arm_end, ","); - } - _ => { - let to_insert = block.dedent(dedent.into()).syntax().text(); - edit.insert(then_arm_end, to_insert) - } - } + let expr = match block.tail_expr() { + Some(then_expr) if only_expr => then_expr, + _ => block.dedent(dedent.into()).into(), + }; + let guard = make.match_guard(cond); + let new_arm = make.match_arm(match_pat.clone(), Some(guard), expr); + replace_arms.push(new_arm); } - if let Some(e) = tail { + if let Some(block) = tail { cov_mark::hit!(move_guard_ifelse_else_tail); - let guard = format!("\n{spaces}{match_pat} => "); - edit.insert(then_arm_end, guard); - let only_expr = e.statements().next().is_none(); - match &e.tail_expr() { + let only_expr = block.statements().next().is_none(); + let expr = match block.tail_expr() { Some(expr) if only_expr => { cov_mark::hit!(move_guard_ifelse_expr_only); - edit.insert(then_arm_end, expr.syntax().text()); - edit.insert(then_arm_end, ","); + expr } - _ => { - let to_insert = e.dedent(dedent.into()).syntax().text(); - edit.insert(then_arm_end, to_insert) - } - } + _ => block.dedent(dedent.into()).into(), + }; + let new_arm = make.match_arm(match_pat, None, expr); + replace_arms.push(new_arm); } else { // There's no else branch. Add a pattern without guard, unless the following match // arm is `_ => ...` @@ -193,9 +183,21 @@ pub(crate) fn move_arm_cond_to_match_guard( { cov_mark::hit!(move_guard_ifelse_has_wildcard); } - _ => edit.insert(then_arm_end, format!("\n{spaces}{match_pat} => {{}}")), + _ => { + let block_expr = make.expr_empty_block().into(); + replace_arms.push(make.match_arm(match_pat, None, block_expr)); + } } } + + 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()); + + builder.add_file_edits(ctx.vfs_file_id(), edit); }, ) }