@@ -30,24 +30,23 @@ use crate::{
30
30
// ```
31
31
pub ( crate ) fn convert_match_to_let_else ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
32
32
let let_stmt: ast:: LetStmt = ctx. find_node_at_offset ( ) ?;
33
- let binding = find_binding ( let_stmt. pat ( ) ? ) ?;
33
+ let binding = let_stmt. pat ( ) ?;
34
34
35
- let initializer = match let_stmt. initializer ( ) {
36
- Some ( ast:: Expr :: MatchExpr ( it) ) => it,
37
- _ => return None ,
38
- } ;
35
+ let Some ( ast:: Expr :: MatchExpr ( initializer) ) = let_stmt. initializer ( ) else { return None } ;
39
36
let initializer_expr = initializer. expr ( ) ?;
40
37
41
- let ( extracting_arm, diverging_arm) = match find_arms ( ctx, & initializer) {
42
- Some ( it) => it,
43
- None => return None ,
44
- } ;
38
+ let Some ( ( extracting_arm, diverging_arm) ) = find_arms ( ctx, & initializer) else { return None } ;
45
39
if extracting_arm. guard ( ) . is_some ( ) {
46
40
cov_mark:: hit!( extracting_arm_has_guard) ;
47
41
return None ;
48
42
}
49
43
50
- let diverging_arm_expr = diverging_arm. expr ( ) ?;
44
+ let diverging_arm_expr = match diverging_arm. expr ( ) ? {
45
+ ast:: Expr :: BlockExpr ( block) if block. modifier ( ) . is_none ( ) && block. label ( ) . is_none ( ) => {
46
+ block. to_string ( )
47
+ }
48
+ other => format ! ( "{{ {other} }}" ) ,
49
+ } ;
51
50
let extracting_arm_pat = extracting_arm. pat ( ) ?;
52
51
let extracted_variable = find_extracted_variable ( ctx, & extracting_arm) ?;
53
52
@@ -56,24 +55,16 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'
56
55
"Convert match to let-else" ,
57
56
let_stmt. syntax ( ) . text_range ( ) ,
58
57
|builder| {
59
- let extracting_arm_pat = rename_variable ( & extracting_arm_pat, extracted_variable, binding) ;
58
+ let extracting_arm_pat =
59
+ rename_variable ( & extracting_arm_pat, extracted_variable, binding) ;
60
60
builder. replace (
61
61
let_stmt. syntax ( ) . text_range ( ) ,
62
- format ! ( "let {extracting_arm_pat} = {initializer_expr} else {{ { diverging_arm_expr} }} ;" )
62
+ format ! ( "let {extracting_arm_pat} = {initializer_expr} else {diverging_arm_expr};" ) ,
63
63
)
64
64
} ,
65
65
)
66
66
}
67
67
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
-
77
68
// Given a match expression, find extracting and diverging arms.
78
69
fn find_arms (
79
70
ctx : & AssistContext < ' _ > ,
@@ -124,7 +115,7 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
124
115
}
125
116
126
117
// Rename `extracted` with `binding` in `pat`.
127
- fn rename_variable ( pat : & ast:: Pat , extracted : ast:: Name , binding : ast:: IdentPat ) -> SyntaxNode {
118
+ fn rename_variable ( pat : & ast:: Pat , extracted : ast:: Name , binding : ast:: Pat ) -> SyntaxNode {
128
119
let syntax = pat. syntax ( ) . clone_for_update ( ) ;
129
120
let extracted_syntax = syntax. covering_element ( extracted. syntax ( ) . text_range ( ) ) ;
130
121
@@ -136,7 +127,7 @@ fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat)
136
127
if let Some ( name_ref) = record_pat_field. field_name ( ) {
137
128
ted:: replace (
138
129
record_pat_field. syntax ( ) ,
139
- ast:: make:: record_pat_field ( ast:: make:: name_ref ( & name_ref. text ( ) ) , binding. into ( ) )
130
+ ast:: make:: record_pat_field ( ast:: make:: name_ref ( & name_ref. text ( ) ) , binding)
140
131
. syntax ( )
141
132
. clone_for_update ( ) ,
142
133
) ;
@@ -410,4 +401,52 @@ fn foo(opt: Option<i32>) -> Option<i32> {
410
401
"# ,
411
402
) ;
412
403
}
404
+
405
+ #[ test]
406
+ fn complex_pattern ( ) {
407
+ check_assist (
408
+ convert_match_to_let_else,
409
+ r#"
410
+ //- minicore: option
411
+ fn f() {
412
+ let (x, y) = $0match Some((0, 1)) {
413
+ Some(it) => it,
414
+ None => return,
415
+ };
416
+ }
417
+ "# ,
418
+ r#"
419
+ fn f() {
420
+ let Some((x, y)) = Some((0, 1)) else { return };
421
+ }
422
+ "# ,
423
+ ) ;
424
+ }
425
+
426
+ #[ test]
427
+ fn diverging_block ( ) {
428
+ check_assist (
429
+ convert_match_to_let_else,
430
+ r#"
431
+ //- minicore: option
432
+ fn f() {
433
+ let x = $0match Some(()) {
434
+ Some(it) => it,
435
+ None => {//comment
436
+ println!("nope");
437
+ return
438
+ },
439
+ };
440
+ }
441
+ "# ,
442
+ r#"
443
+ fn f() {
444
+ let Some(x) = Some(()) else {//comment
445
+ println!("nope");
446
+ return
447
+ };
448
+ }
449
+ "# ,
450
+ ) ;
451
+ }
413
452
}
0 commit comments