@@ -39,17 +39,14 @@ use crate::{
39
39
// ```
40
40
pub ( crate ) fn convert_while_to_loop ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
41
41
let while_kw = ctx. find_token_syntax_at_offset ( T ! [ while ] ) ?;
42
- let while_expr: ast :: WhileExpr = while_kw. parent ( ) . and_then ( ast:: WhileExpr :: cast) ?;
42
+ let while_expr = while_kw. parent ( ) . and_then ( ast:: WhileExpr :: cast) ?;
43
43
let while_body = while_expr. loop_body ( ) ?;
44
- let cond = while_expr. condition ( ) ?;
44
+ let while_cond = while_expr. condition ( ) ?;
45
45
46
- // Don't handle while let
47
- if cond . pat ( ) . is_some ( ) {
48
- return None ;
46
+ let if_cond = match while_cond . pat ( ) {
47
+ Some ( _ ) => while_expr . condition ( ) ? ,
48
+ None => make :: condition ( invert_boolean_expression ( while_cond . expr ( ) ? ) , None ) ,
49
49
} ;
50
-
51
- let cond_expr = cond. expr ( ) ?;
52
-
53
50
let target = while_expr. syntax ( ) . text_range ( ) ;
54
51
acc. add (
55
52
AssistId ( "convert_while_to_loop" , AssistKind :: RefactorRewrite ) ,
@@ -58,27 +55,24 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> O
58
55
|edit| {
59
56
let while_indent_level = IndentLevel :: from_node ( while_expr. syntax ( ) ) ;
60
57
61
- let replacement = {
62
- let if_expr = {
63
- let cond = invert_boolean_expression ( cond_expr) ;
64
- let then_branch = make:: block_expr (
65
- once ( make:: expr_stmt ( make:: expr_break ( None ) ) . into ( ) ) ,
66
- None ,
67
- ) ;
68
-
69
- make:: expr_if ( make:: condition ( cond, None ) , then_branch, None )
70
- } ;
71
-
72
- let if_expr = if_expr. indent ( while_indent_level) ;
73
- let stmts = once ( make:: expr_stmt ( if_expr) . into ( ) ) . chain ( while_body. statements ( ) ) ;
74
-
75
- let block_expr = make:: block_expr ( stmts, while_body. tail_expr ( ) ) ;
76
-
77
- let block_expr = block_expr. indent ( while_indent_level) ;
78
-
79
- make:: expr_loop ( block_expr)
58
+ let break_block =
59
+ make:: block_expr ( once ( make:: expr_stmt ( make:: expr_break ( None ) ) . into ( ) ) , None )
60
+ . indent ( while_indent_level) ;
61
+ let block_expr = match while_cond. pat ( ) {
62
+ Some ( _) => {
63
+ let if_expr = make:: expr_if ( if_cond, while_body, Some ( break_block. into ( ) ) ) ;
64
+ let stmts = once ( make:: expr_stmt ( if_expr) . into ( ) ) ;
65
+ make:: block_expr ( stmts, None )
66
+ }
67
+ None => {
68
+ let if_expr = make:: expr_if ( if_cond, break_block, None ) ;
69
+ let stmts =
70
+ once ( make:: expr_stmt ( if_expr) . into ( ) ) . chain ( while_body. statements ( ) ) ;
71
+ make:: block_expr ( stmts, while_body. tail_expr ( ) )
72
+ }
80
73
} ;
81
74
75
+ let replacement = make:: expr_loop ( block_expr. indent ( while_indent_level) ) ;
82
76
edit. replace ( target, replacement. syntax ( ) . text ( ) )
83
77
} ,
84
78
)
@@ -160,15 +154,26 @@ fn main() {
160
154
}
161
155
162
156
#[ test]
163
- fn ignore_while_let ( ) {
164
- check_assist_not_applicable (
157
+ fn convert_while_let ( ) {
158
+ check_assist (
165
159
convert_while_to_loop,
166
160
r#"
167
161
fn main() {
168
162
while$0 let Some(_) = foo() {
169
163
bar();
170
164
}
171
165
}
166
+ "# ,
167
+ r#"
168
+ fn main() {
169
+ loop {
170
+ if let Some(_) = foo() {
171
+ bar();
172
+ } else {
173
+ break;
174
+ }
175
+ }
176
+ }
172
177
"# ,
173
178
) ;
174
179
}
0 commit comments