Skip to content

Commit fb90bf9

Browse files
committed
feat: handle while let to loop
1 parent 8dd06ec commit fb90bf9

File tree

1 file changed

+34
-29
lines changed

1 file changed

+34
-29
lines changed

crates/ide_assists/src/handlers/convert_while_to_loop.rs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,14 @@ use crate::{
3939
// ```
4040
pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
4141
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)?;
4343
let while_body = while_expr.loop_body()?;
44-
let cond = while_expr.condition()?;
44+
let while_cond = while_expr.condition()?;
4545

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),
4949
};
50-
51-
let cond_expr = cond.expr()?;
52-
5350
let target = while_expr.syntax().text_range();
5451
acc.add(
5552
AssistId("convert_while_to_loop", AssistKind::RefactorRewrite),
@@ -58,27 +55,24 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> O
5855
|edit| {
5956
let while_indent_level = IndentLevel::from_node(while_expr.syntax());
6057

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+
}
8073
};
8174

75+
let replacement = make::expr_loop(block_expr.indent(while_indent_level));
8276
edit.replace(target, replacement.syntax().text())
8377
},
8478
)
@@ -160,15 +154,26 @@ fn main() {
160154
}
161155

162156
#[test]
163-
fn ignore_while_let() {
164-
check_assist_not_applicable(
157+
fn convert_while_let() {
158+
check_assist(
165159
convert_while_to_loop,
166160
r#"
167161
fn main() {
168162
while$0 let Some(_) = foo() {
169163
bar();
170164
}
171165
}
166+
"#,
167+
r#"
168+
fn main() {
169+
loop {
170+
if let Some(_) = foo() {
171+
bar();
172+
} else {
173+
break;
174+
}
175+
}
176+
}
172177
"#,
173178
);
174179
}

0 commit comments

Comments
 (0)