@@ -17,7 +17,7 @@ use syntax::{
17
17
use crate :: {
18
18
AssistId ,
19
19
assist_context:: { AssistContext , Assists } ,
20
- utils:: invert_boolean_expression_legacy,
20
+ utils:: { invert_boolean_expression_legacy, is_never_block } ,
21
21
} ;
22
22
23
23
// Assist: convert_to_guarded_return
@@ -54,9 +54,13 @@ fn if_expr_to_guarded_return(
54
54
acc : & mut Assists ,
55
55
ctx : & AssistContext < ' _ > ,
56
56
) -> Option < ( ) > {
57
- if if_expr. else_branch ( ) . is_some ( ) {
58
- return None ;
59
- }
57
+ let else_block = match if_expr. else_branch ( ) {
58
+ Some ( ast:: ElseBranch :: Block ( block_expr) ) if is_never_block ( & ctx. sema , & block_expr) => {
59
+ Some ( block_expr)
60
+ }
61
+ Some ( _) => return None ,
62
+ _ => None ,
63
+ } ;
60
64
61
65
let cond = if_expr. condition ( ) ?;
62
66
@@ -96,7 +100,11 @@ fn if_expr_to_guarded_return(
96
100
97
101
let parent_container = parent_block. syntax ( ) . parent ( ) ?;
98
102
99
- let early_expression: ast:: Expr = early_expression ( parent_container, & ctx. sema ) ?;
103
+ let early_expression = else_block
104
+ . or_else ( || {
105
+ early_expression ( parent_container, & ctx. sema ) . map ( ast:: make:: tail_only_block_expr)
106
+ } ) ?
107
+ . reset_indent ( ) ;
100
108
101
109
then_block. syntax ( ) . first_child_or_token ( ) . map ( |t| t. kind ( ) == T ! [ '{' ] ) ?;
102
110
@@ -123,21 +131,14 @@ fn if_expr_to_guarded_return(
123
131
&& let ( Some ( pat) , Some ( expr) ) = ( let_expr. pat ( ) , let_expr. expr ( ) )
124
132
{
125
133
// If-let.
126
- let let_else_stmt = make:: let_else_stmt (
127
- pat,
128
- None ,
129
- expr,
130
- ast:: make:: tail_only_block_expr ( early_expression. clone ( ) ) ,
131
- ) ;
134
+ let let_else_stmt =
135
+ make:: let_else_stmt ( pat, None , expr, early_expression. clone ( ) ) ;
132
136
let let_else_stmt = let_else_stmt. indent ( if_indent_level) ;
133
137
let_else_stmt. syntax ( ) . clone ( )
134
138
} else {
135
139
// If.
136
140
let new_expr = {
137
- let then_branch = make:: block_expr (
138
- once ( make:: expr_stmt ( early_expression. clone ( ) ) . into ( ) ) ,
139
- None ,
140
- ) ;
141
+ let then_branch = clean_stmt_block ( & early_expression) ;
141
142
let cond = invert_boolean_expression_legacy ( expr) ;
142
143
make:: expr_if ( cond, then_branch, None ) . indent ( if_indent_level)
143
144
} ;
@@ -272,6 +273,17 @@ fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
272
273
chains
273
274
}
274
275
276
+ fn clean_stmt_block ( block : & ast:: BlockExpr ) -> ast:: BlockExpr {
277
+ if block. statements ( ) . next ( ) . is_none ( )
278
+ && let Some ( tail_expr) = block. tail_expr ( )
279
+ && block. modifier ( ) . is_none ( )
280
+ {
281
+ make:: block_expr ( once ( make:: expr_stmt ( tail_expr) . into ( ) ) , None )
282
+ } else {
283
+ block. clone ( )
284
+ }
285
+ }
286
+
275
287
#[ cfg( test) ]
276
288
mod tests {
277
289
use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -421,6 +433,53 @@ fn main() {
421
433
) ;
422
434
}
423
435
436
+ #[ test]
437
+ fn convert_if_let_has_never_type_else_block ( ) {
438
+ check_assist (
439
+ convert_to_guarded_return,
440
+ r#"
441
+ fn main() {
442
+ if$0 let Ok(x) = Err(92) {
443
+ foo(x);
444
+ } else {
445
+ // needless comment
446
+ return;
447
+ }
448
+ }
449
+ "# ,
450
+ r#"
451
+ fn main() {
452
+ let Ok(x) = Err(92) else {
453
+ // needless comment
454
+ return;
455
+ };
456
+ foo(x);
457
+ }
458
+ "# ,
459
+ ) ;
460
+
461
+ check_assist (
462
+ convert_to_guarded_return,
463
+ r#"
464
+ fn main() {
465
+ if$0 let Ok(x) = Err(92) {
466
+ foo(x);
467
+ } else {
468
+ return
469
+ }
470
+ }
471
+ "# ,
472
+ r#"
473
+ fn main() {
474
+ let Ok(x) = Err(92) else {
475
+ return
476
+ };
477
+ foo(x);
478
+ }
479
+ "# ,
480
+ ) ;
481
+ }
482
+
424
483
#[ test]
425
484
fn convert_if_let_result_inside_let ( ) {
426
485
check_assist (
0 commit comments