diff --git a/crates/ide-assists/src/handlers/merge_nested_if.rs b/crates/ide-assists/src/handlers/merge_nested_if.rs index 73cb8204f209..64de84a7d4ba 100644 --- a/crates/ide-assists/src/handlers/merge_nested_if.rs +++ b/crates/ide-assists/src/handlers/merge_nested_if.rs @@ -1,7 +1,7 @@ use ide_db::syntax_helpers::node_ext::is_pattern_cond; use syntax::{ T, - ast::{self, AstNode, BinaryOp}, + ast::{self, AstNode, BinaryOp, edit::AstNodeEdit}, }; use crate::{ @@ -89,6 +89,58 @@ pub(crate) fn merge_nested_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt }) } +// Assist: merge_nested_else_if +// +// This transforms `if x {} else { if y {} }` into `if x {} else if y {}`, +// This assist can only be applied with the cursor on `else`. +// +// ``` +// fn main() { +// if x == 3 { +// true +// } $0else { +// if x == 2 { +// false +// } else { +// true +// } +// } +// } +// ``` +// -> +// ``` +// fn main() { +// if x == 3 { +// true +// } else if x == 2 { +// false +// } else { +// true +// } +// } +// ``` +pub(crate) fn merge_nested_else_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let else_keyword = ctx.find_token_syntax_at_offset(T![else])?; + let expr = ast::IfExpr::cast(else_keyword.parent()?)?; + let ast::ElseBranch::Block(else_block) = expr.else_branch()? else { return None }; + let ast::Expr::IfExpr(else_expr) = else_block.tail_expr()? else { return None }; + + if else_block.statements().next().is_some() { + return None; + } + + let target = else_keyword.text_range(); + acc.add( + AssistId::refactor_rewrite("merge_nested_else_if"), + "Merge nested else if", + target, + |edit| { + let else_expr = else_expr.dedent(1.into()).into(); + edit.replace_ast(ast::Expr::BlockExpr(else_block), else_expr); + }, + ) +} + /// Returns whether the given if condition has logical operators. fn has_logic_op_or(expr: &ast::Expr) -> bool { match expr { diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 4682c0473238..9974f15f92e8 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -322,6 +322,7 @@ mod handlers { merge_imports::merge_imports, merge_match_arms::merge_match_arms, merge_nested_if::merge_nested_if, + merge_nested_if::merge_nested_else_if, move_bounds::move_bounds_to_where_clause, move_const_to_impl::move_const_to_impl, move_from_mod_rs::move_from_mod_rs, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 91348be97eb7..fbcf8088039f 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2476,6 +2476,37 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_merge_nested_else_if() { + check_doc_test( + "merge_nested_else_if", + r#####" +fn main() { + if x == 3 { + true + } $0else { + if x == 2 { + false + } else { + true + } + } +} +"#####, + r#####" +fn main() { + if x == 3 { + true + } else if x == 2 { + false + } else { + true + } +} +"#####, + ) +} + #[test] fn doctest_merge_nested_if() { check_doc_test(