|
1 |
| -use std::iter::once; |
| 1 | +use std::iter; |
2 | 2 |
|
| 3 | +use either::Either; |
3 | 4 | use ide_db::syntax_helpers::node_ext::is_pattern_cond;
|
4 | 5 | use syntax::{
|
5 | 6 | ast::{
|
@@ -52,18 +53,30 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
|
52 | 53 | |edit| {
|
53 | 54 | let while_indent_level = IndentLevel::from_node(while_expr.syntax());
|
54 | 55 |
|
55 |
| - let break_block = |
56 |
| - make::block_expr(once(make::expr_stmt(make::expr_break(None, None)).into()), None) |
57 |
| - .indent(while_indent_level); |
| 56 | + let break_block = make::block_expr( |
| 57 | + iter::once(make::expr_stmt(make::expr_break(None, None)).into()), |
| 58 | + None, |
| 59 | + ) |
| 60 | + .indent(while_indent_level); |
58 | 61 | let block_expr = if is_pattern_cond(while_cond.clone()) {
|
59 | 62 | let if_expr = make::expr_if(while_cond, while_body, Some(break_block.into()));
|
60 |
| - let stmts = once(make::expr_stmt(if_expr).into()); |
| 63 | + let stmts = iter::once(make::expr_stmt(if_expr).into()); |
61 | 64 | make::block_expr(stmts, None)
|
62 | 65 | } else {
|
63 | 66 | let if_cond = invert_boolean_expression(while_cond);
|
64 |
| - let if_expr = make::expr_if(if_cond, break_block, None); |
65 |
| - let stmts = once(make::expr_stmt(if_expr).into()).chain(while_body.statements()); |
66 |
| - make::block_expr(stmts, while_body.tail_expr()) |
| 67 | + let if_expr = make::expr_if(if_cond, break_block, None).syntax().clone().into(); |
| 68 | + let elements = while_body.stmt_list().map_or_else( |
| 69 | + || Either::Left(iter::empty()), |
| 70 | + |stmts| { |
| 71 | + Either::Right(stmts.syntax().children_with_tokens().filter(|node_or_tok| { |
| 72 | + // Filter out the trailing expr |
| 73 | + !node_or_tok |
| 74 | + .as_node() |
| 75 | + .is_some_and(|node| ast::Expr::can_cast(node.kind())) |
| 76 | + })) |
| 77 | + }, |
| 78 | + ); |
| 79 | + make::hacky_block_expr(iter::once(if_expr).chain(elements), while_body.tail_expr()) |
67 | 80 | };
|
68 | 81 |
|
69 | 82 | let replacement = make::expr_loop(block_expr.indent(while_indent_level));
|
@@ -182,6 +195,74 @@ fn main() {
|
182 | 195 | bar();
|
183 | 196 | }
|
184 | 197 | }
|
| 198 | +"#, |
| 199 | + ); |
| 200 | + } |
| 201 | + |
| 202 | + #[test] |
| 203 | + fn preserve_comments() { |
| 204 | + check_assist( |
| 205 | + convert_while_to_loop, |
| 206 | + r#" |
| 207 | +fn main() { |
| 208 | + let mut i = 0; |
| 209 | +
|
| 210 | + $0while i < 5 { |
| 211 | + // comment 1 |
| 212 | + dbg!(i); |
| 213 | + // comment 2 |
| 214 | + i += 1; |
| 215 | + // comment 3 |
| 216 | + } |
| 217 | +} |
| 218 | +"#, |
| 219 | + r#" |
| 220 | +fn main() { |
| 221 | + let mut i = 0; |
| 222 | +
|
| 223 | + loop { |
| 224 | + if i >= 5 { |
| 225 | + break; |
| 226 | + } |
| 227 | + // comment 1 |
| 228 | + dbg!(i); |
| 229 | + // comment 2 |
| 230 | + i += 1; |
| 231 | + // comment 3 |
| 232 | + } |
| 233 | +} |
| 234 | +"#, |
| 235 | + ); |
| 236 | + |
| 237 | + check_assist( |
| 238 | + convert_while_to_loop, |
| 239 | + r#" |
| 240 | +fn main() { |
| 241 | + let v = vec![1, 2, 3]; |
| 242 | + let iter = v.iter(); |
| 243 | +
|
| 244 | + $0while let Some(i) = iter.next() { |
| 245 | + // comment 1 |
| 246 | + dbg!(i); |
| 247 | + // comment 2 |
| 248 | + } |
| 249 | +} |
| 250 | +"#, |
| 251 | + r#" |
| 252 | +fn main() { |
| 253 | + let v = vec![1, 2, 3]; |
| 254 | + let iter = v.iter(); |
| 255 | +
|
| 256 | + loop { |
| 257 | + if let Some(i) = iter.next() { |
| 258 | + // comment 1 |
| 259 | + dbg!(i); |
| 260 | + // comment 2 |
| 261 | + } else { |
| 262 | + break; |
| 263 | + } |
| 264 | + } |
| 265 | +} |
185 | 266 | "#,
|
186 | 267 | );
|
187 | 268 | }
|
|
0 commit comments