Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/replace_if_let_with_match.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/replace_if_let_with_match.rs | 150 |
1 files changed, 109 insertions, 41 deletions
diff --git a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs index b7e5344712..8ff30fce5b 100644 --- a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs @@ -3,7 +3,11 @@ use std::iter::successors; use ide_db::{RootDatabase, defs::NameClass, ty_filter::TryEnum}; use syntax::{ AstNode, Edition, SyntaxKind, T, TextRange, - ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, + ast::{ + self, HasName, + edit::{AstNodeEdit, IndentLevel}, + syntax_factory::SyntaxFactory, + }, syntax_editor::SyntaxEditor, }; @@ -53,9 +57,8 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' let if_exprs = successors(Some(if_expr.clone()), |expr| match expr.else_branch()? { ast::ElseBranch::IfExpr(expr) => Some(expr), ast::ElseBranch::Block(block) => { - let block = unwrap_trivial_block(block).clone_for_update(); - block.reindent_to(IndentLevel(1)); - else_block = Some(block); + let block = unwrap_trivial_block(block); + else_block = Some(block.reset_indent().indent(IndentLevel(1))); None } }); @@ -82,12 +85,13 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' (Some(pat), guard) } }; - if let Some(guard) = &guard { - guard.dedent(indent); - guard.indent(IndentLevel(1)); - } - let body = if_expr.then_branch()?.clone_for_update(); - body.indent(IndentLevel(1)); + let guard = if let Some(guard) = &guard { + Some(guard.dedent(indent).indent(IndentLevel(1))) + } else { + guard + }; + + let body = if_expr.then_branch()?.indent(IndentLevel(1)); cond_bodies.push((cond, guard, body)); } @@ -109,7 +113,8 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' let else_arm = make_else_arm(ctx, &make, else_block, &cond_bodies); let make_match_arm = |(pat, guard, body): (_, Option<ast::Expr>, ast::BlockExpr)| { - body.reindent_to(IndentLevel::single()); + // Dedent from original position, then indent for match arm + let body = body.dedent(indent); let body = unwrap_trivial_block(body); match (pat, guard.map(|it| make.match_guard(it))) { (Some(pat), guard) => make.match_arm(pat, guard, body), @@ -122,8 +127,8 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' } }; let arms = cond_bodies.into_iter().map(make_match_arm).chain([else_arm]); - let match_expr = make.expr_match(scrutinee_to_be_expr, make.match_arm_list(arms)); - match_expr.indent(indent); + let expr = scrutinee_to_be_expr.reset_indent(); + let match_expr = make.expr_match(expr, make.match_arm_list(arms)).indent(indent); match_expr.into() }; @@ -131,10 +136,9 @@ 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` - match_expr.dedent(indent); - match_expr.indent(IndentLevel(1)); - let block_expr = make.block_expr([], Some(match_expr)); - block_expr.indent(indent); + let block_expr = make + .block_expr([], Some(match_expr.dedent(indent).indent(IndentLevel(1)))) + .indent(indent); block_expr.into() } else { match_expr @@ -242,7 +246,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' first_arm.guard(), second_arm.guard(), )?; - let scrutinee = match_expr.expr()?; + let scrutinee = match_expr.expr()?.reset_indent(); let guard = guard.and_then(|it| it.condition()); let let_ = match &if_let_pat { @@ -267,10 +271,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' // wrap them in another BlockExpr. match expr { ast::Expr::BlockExpr(block) if block.modifier().is_none() => block, - expr => { - expr.indent(IndentLevel(1)); - make.block_expr([], Some(expr)) - } + expr => make.block_expr([], Some(expr.indent(IndentLevel(1)))), } }; @@ -292,18 +293,17 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' } else { condition }; - let then_expr = then_expr.clone_for_update(); - let else_expr = else_expr.clone_for_update(); - then_expr.reindent_to(IndentLevel::single()); - else_expr.reindent_to(IndentLevel::single()); + let then_expr = then_expr.reset_indent(); + 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.expr_if( - condition, - then_block, - else_expr.map(make_block_expr).map(ast::ElseBranch::Block), - ); - if_let_expr.indent(IndentLevel::from_node(match_expr.syntax())); + let if_let_expr = make + .expr_if( + condition, + then_block, + else_expr.map(make_block_expr).map(ast::ElseBranch::Block), + ) + .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()); @@ -848,6 +848,31 @@ fn foo(x: Option<i32>) { } #[test] + fn special_case_option_ref() { + check_assist( + replace_if_let_with_match, + r#" +//- minicore: option +fn foo(x: &Option<i32>) { + $0if let Some(x) = x { + println!("{}", x) + } else { + println!("none") + } +} +"#, + r#" +fn foo(x: &Option<i32>) { + match x { + Some(x) => println!("{}", x), + None => println!("none"), + } +} +"#, + ); + } + + #[test] fn special_case_inverted_option() { check_assist( replace_if_let_with_match, @@ -929,7 +954,9 @@ fn foo(x: Result<i32, ()>) { r#" fn main() { if true { - $0if let Ok(rel_path) = path.strip_prefix(root_path) { + $0if let Ok(rel_path) = path.strip_prefix(root_path) + .and(x) + { let rel_path = RelativePathBuf::from_path(rel_path) .ok()?; Some((*id, rel_path)) @@ -944,7 +971,9 @@ fn main() { r#" fn main() { if true { - match path.strip_prefix(root_path) { + match path.strip_prefix(root_path) + .and(x) + { Ok(rel_path) => { let rel_path = RelativePathBuf::from_path(rel_path) .ok()?; @@ -966,7 +995,9 @@ fn main() { r#" fn main() { if true { - $0if let Ok(rel_path) = path.strip_prefix(root_path) { + $0if let Ok(rel_path) = path.strip_prefix(root_path) + .and(x) + { Foo { x: 1 } @@ -981,7 +1012,9 @@ fn main() { r#" fn main() { if true { - match path.strip_prefix(root_path) { + match path.strip_prefix(root_path) + .and(x) + { Ok(rel_path) => { Foo { x: 1 @@ -996,7 +1029,34 @@ fn main() { } } "#, - ) + ); + + check_assist( + replace_if_let_with_match, + r#" +fn main() { + if true { + $0if true + && false + { + foo() + } + } +} +"#, + r#" +fn main() { + if true { + match true + && false + { + true => foo(), + false => (), + } + } +} +"#, + ); } #[test] @@ -1851,7 +1911,9 @@ fn foo(x: Result<i32, ()>) { r#" fn main() { if true { - $0match path.strip_prefix(root_path) { + $0match path.strip_prefix(root_path) + .and(x) + { Ok(rel_path) => Foo { x: 2 } @@ -1865,7 +1927,9 @@ fn main() { r#" fn main() { if true { - if let Ok(rel_path) = path.strip_prefix(root_path) { + if let Ok(rel_path) = path.strip_prefix(root_path) + .and(x) + { Foo { x: 2 } @@ -1884,7 +1948,9 @@ fn main() { r#" fn main() { if true { - $0match path.strip_prefix(root_path) { + $0match path.strip_prefix(root_path) + .and(x) + { Ok(rel_path) => { let rel_path = RelativePathBuf::from_path(rel_path) .ok()?; @@ -1902,7 +1968,9 @@ fn main() { r#" fn main() { if true { - if let Ok(rel_path) = path.strip_prefix(root_path) { + if let Ok(rel_path) = path.strip_prefix(root_path) + .and(x) + { let rel_path = RelativePathBuf::from_path(rel_path) .ok()?; Some((*id, rel_path)) |