@@ -30,24 +30,23 @@ use crate::{
3030// ```
3131pub ( 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
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 } ;
3936 let initializer_expr = initializer. expr ( ) ?;
4037
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 } ;
4539 if extracting_arm. guard ( ) . is_some ( ) {
4640 cov_mark:: hit!( extracting_arm_has_guard) ;
4741 return None ;
4842 }
4943
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+ } ;
5150 let extracting_arm_pat = extracting_arm. pat ( ) ?;
5251 let extracted_variable = find_extracted_variable ( ctx, & extracting_arm) ?;
5352
@@ -56,24 +55,16 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'
5655 "Convert match to let-else" ,
5756 let_stmt. syntax ( ) . text_range ( ) ,
5857 |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) ;
6060 builder. replace (
6161 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};" ) ,
6363 )
6464 } ,
6565 )
6666}
6767
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-
7768// Given a match expression, find extracting and diverging arms.
7869fn find_arms (
7970 ctx : & AssistContext < ' _ > ,
@@ -124,7 +115,7 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
124115}
125116
126117// 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 {
128119 let syntax = pat. syntax ( ) . clone_for_update ( ) ;
129120 let extracted_syntax = syntax. covering_element ( extracted. syntax ( ) . text_range ( ) ) ;
130121
@@ -136,7 +127,7 @@ fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat)
136127 if let Some ( name_ref) = record_pat_field. field_name ( ) {
137128 ted:: replace (
138129 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)
140131 . syntax ( )
141132 . clone_for_update ( ) ,
142133 ) ;
@@ -410,4 +401,52 @@ fn foo(opt: Option<i32>) -> Option<i32> {
410401 "# ,
411402 ) ;
412403 }
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+ }
413452}
0 commit comments