Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1f20804

Browse files
author
Jonas Schievink
committed
Improve "match to let-else" assist
1 parent f1b257f commit 1f20804

File tree

1 file changed

+60
-15
lines changed

1 file changed

+60
-15
lines changed

crates/ide-assists/src/handlers/convert_match_to_let_else.rs

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::{
3030
// ```
3131
pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
3232
let let_stmt: ast::LetStmt = ctx.find_node_at_offset()?;
33-
let binding = find_binding(let_stmt.pat()?)?;
33+
let binding = let_stmt.pat()?;
3434

3535
let initializer = match let_stmt.initializer() {
3636
Some(ast::Expr::MatchExpr(it)) => it,
@@ -47,7 +47,12 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'
4747
return None;
4848
}
4949

50-
let diverging_arm_expr = diverging_arm.expr()?;
50+
let diverging_arm_expr = match diverging_arm.expr()? {
51+
ast::Expr::BlockExpr(block) if block.modifier().is_none() && block.label().is_none() => {
52+
block.to_string()
53+
}
54+
other => format!("{{ {other} }}"),
55+
};
5156
let extracting_arm_pat = extracting_arm.pat()?;
5257
let extracted_variable = find_extracted_variable(ctx, &extracting_arm)?;
5358

@@ -56,24 +61,16 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'
5661
"Convert match to let-else",
5762
let_stmt.syntax().text_range(),
5863
|builder| {
59-
let extracting_arm_pat = rename_variable(&extracting_arm_pat, extracted_variable, binding);
64+
let extracting_arm_pat =
65+
rename_variable(&extracting_arm_pat, extracted_variable, binding);
6066
builder.replace(
6167
let_stmt.syntax().text_range(),
62-
format!("let {extracting_arm_pat} = {initializer_expr} else {{ {diverging_arm_expr} }};")
68+
format!("let {extracting_arm_pat} = {initializer_expr} else {diverging_arm_expr};"),
6369
)
6470
},
6571
)
6672
}
6773

68-
// Given a pattern, find the name introduced to the surrounding scope.
69-
fn find_binding(pat: ast::Pat) -> Option<ast::IdentPat> {
70-
if let ast::Pat::IdentPat(ident) = pat {
71-
Some(ident)
72-
} else {
73-
None
74-
}
75-
}
76-
7774
// Given a match expression, find extracting and diverging arms.
7875
fn find_arms(
7976
ctx: &AssistContext<'_>,
@@ -124,7 +121,7 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
124121
}
125122

126123
// Rename `extracted` with `binding` in `pat`.
127-
fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat) -> SyntaxNode {
124+
fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::Pat) -> SyntaxNode {
128125
let syntax = pat.syntax().clone_for_update();
129126
let extracted_syntax = syntax.covering_element(extracted.syntax().text_range());
130127

@@ -136,7 +133,7 @@ fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat)
136133
if let Some(name_ref) = record_pat_field.field_name() {
137134
ted::replace(
138135
record_pat_field.syntax(),
139-
ast::make::record_pat_field(ast::make::name_ref(&name_ref.text()), binding.into())
136+
ast::make::record_pat_field(ast::make::name_ref(&name_ref.text()), binding)
140137
.syntax()
141138
.clone_for_update(),
142139
);
@@ -410,4 +407,52 @@ fn foo(opt: Option<i32>) -> Option<i32> {
410407
"#,
411408
);
412409
}
410+
411+
#[test]
412+
fn complex_pattern() {
413+
check_assist(
414+
convert_match_to_let_else,
415+
r#"
416+
//- minicore: option
417+
fn f() {
418+
let (x, y) = $0match Some((0, 1)) {
419+
Some(it) => it,
420+
None => return,
421+
};
422+
}
423+
"#,
424+
r#"
425+
fn f() {
426+
let Some((x, y)) = Some((0, 1)) else { return };
427+
}
428+
"#,
429+
);
430+
}
431+
432+
#[test]
433+
fn diverging_block() {
434+
check_assist(
435+
convert_match_to_let_else,
436+
r#"
437+
//- minicore: option
438+
fn f() {
439+
let x = $0match Some(()) {
440+
Some(it) => it,
441+
None => {//comment
442+
println!("nope");
443+
return
444+
},
445+
};
446+
}
447+
"#,
448+
r#"
449+
fn f() {
450+
let Some(x) = Some(()) else {//comment
451+
println!("nope");
452+
return
453+
};
454+
}
455+
"#,
456+
);
457+
}
413458
}

0 commit comments

Comments
 (0)