diff options
Diffstat (limited to 'crates/ide_assists')
-rw-r--r-- | crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs index 73ef44685..5700e6167 100644 --- a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs | |||
@@ -28,50 +28,54 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
28 | /// } | 28 | /// } |
29 | /// ``` | 29 | /// ``` |
30 | pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 30 | pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
31 | let closure; | 31 | let method; |
32 | 32 | ||
33 | let total_expr = match ctx.find_node_at_offset::<ast::Expr>()? { | 33 | let stmt = if let Some(stmt) = ctx.find_node_at_offset::<ast::ExprStmt>() { |
34 | ast::Expr::MethodCallExpr(expr) => { | 34 | method = ast::MethodCallExpr::cast(stmt.syntax().first_child()?)?; |
35 | closure = match expr.arg_list()?.args().next()? { | 35 | Some(stmt) |
36 | ast::Expr::ClosureExpr(expr) => expr, | 36 | } else { |
37 | _ => { | 37 | method = match ctx.find_node_at_offset::<ast::Expr>()? { |
38 | return None; | 38 | ast::Expr::MethodCallExpr(expr) => expr, |
39 | } | 39 | ast::Expr::ClosureExpr(expr) => { |
40 | }; | 40 | ast::MethodCallExpr::cast(expr.syntax().ancestors().nth(2)?)? |
41 | 41 | } | |
42 | expr | 42 | _ => { |
43 | } | 43 | return None; |
44 | ast::Expr::ClosureExpr(expr) => { | 44 | } |
45 | closure = expr; | 45 | }; |
46 | ast::MethodCallExpr::cast(closure.syntax().ancestors().nth(2)?)? | 46 | None |
47 | } | 47 | }; |
48 | |||
49 | let closure = match method.arg_list()?.args().next()? { | ||
50 | ast::Expr::ClosureExpr(expr) => expr, | ||
48 | _ => { | 51 | _ => { |
49 | return None; | 52 | return None; |
50 | } | 53 | } |
51 | }; | 54 | }; |
52 | 55 | ||
53 | let (total_expr, parent) = validate_method_call_expr(&ctx.sema, total_expr)?; | 56 | let (method, parent) = validate_method_call_expr(&ctx.sema, method)?; |
54 | 57 | ||
55 | let param_list = closure.param_list()?; | 58 | let param_list = closure.param_list()?; |
56 | let param = param_list.params().next()?.pat()?; | 59 | let param = param_list.params().next()?.pat()?; |
57 | let body = closure.body()?; | 60 | let body = closure.body()?; |
58 | 61 | ||
62 | let indent = stmt.as_ref().map_or(method.indent_level(), |stmt| stmt.indent_level()); | ||
63 | let syntax = stmt.as_ref().map_or(method.syntax(), |stmt| stmt.syntax()); | ||
64 | |||
59 | acc.add( | 65 | acc.add( |
60 | AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite), | 66 | AssistId("convert_iter_for_each_to_for", AssistKind::RefactorRewrite), |
61 | "Replace this `Iterator::for_each` with a for loop", | 67 | "Replace this `Iterator::for_each` with a for loop", |
62 | total_expr.syntax().text_range(), | 68 | syntax.text_range(), |
63 | |builder| { | 69 | |builder| { |
64 | let original_indentation = total_expr.indent_level(); | ||
65 | |||
66 | let block = match body { | 70 | let block = match body { |
67 | ast::Expr::BlockExpr(block) => block, | 71 | ast::Expr::BlockExpr(block) => block, |
68 | _ => make::block_expr(Vec::new(), Some(body)), | 72 | _ => make::block_expr(Vec::new(), Some(body)), |
69 | } | 73 | } |
70 | .reset_indent() | 74 | .reset_indent() |
71 | .indent(original_indentation); | 75 | .indent(indent); |
72 | 76 | ||
73 | let expr_for_loop = make::expr_for_loop(param, parent, block); | 77 | let expr_for_loop = make::expr_for_loop(param, parent, block); |
74 | builder.replace_ast(total_expr, expr_for_loop) | 78 | builder.replace(syntax.text_range(), expr_for_loop.syntax().text()) |
75 | }, | 79 | }, |
76 | ) | 80 | ) |
77 | } | 81 | } |
@@ -125,7 +129,7 @@ impl Empty { | |||
125 | } | 129 | } |
126 | 130 | ||
127 | #[test] | 131 | #[test] |
128 | fn test_for_each_in_method() { | 132 | fn test_for_each_in_method_stmt() { |
129 | check_assist_with_fixtures( | 133 | check_assist_with_fixtures( |
130 | r#" | 134 | r#" |
131 | use empty_iter::*; | 135 | use empty_iter::*; |
@@ -141,14 +145,37 @@ fn main() { | |||
141 | let x = Empty; | 145 | let x = Empty; |
142 | for (x, y) in x.iter() { | 146 | for (x, y) in x.iter() { |
143 | println!("x: {}, y: {}", x, y); | 147 | println!("x: {}, y: {}", x, y); |
144 | }; | 148 | } |
145 | } | 149 | } |
146 | "#, | 150 | "#, |
147 | ) | 151 | ) |
148 | } | 152 | } |
149 | 153 | ||
150 | #[test] | 154 | #[test] |
151 | fn test_for_each_without_braces() { | 155 | fn test_for_each_in_method() { |
156 | check_assist_with_fixtures( | ||
157 | r#" | ||
158 | use empty_iter::*; | ||
159 | fn main() { | ||
160 | let x = Empty; | ||
161 | x.iter().$0for_each(|(x, y)| { | ||
162 | println!("x: {}, y: {}", x, y); | ||
163 | }) | ||
164 | }"#, | ||
165 | r#" | ||
166 | use empty_iter::*; | ||
167 | fn main() { | ||
168 | let x = Empty; | ||
169 | for (x, y) in x.iter() { | ||
170 | println!("x: {}, y: {}", x, y); | ||
171 | } | ||
172 | } | ||
173 | "#, | ||
174 | ) | ||
175 | } | ||
176 | |||
177 | #[test] | ||
178 | fn test_for_each_without_braces_stmt() { | ||
152 | check_assist_with_fixtures( | 179 | check_assist_with_fixtures( |
153 | r#" | 180 | r#" |
154 | use empty_iter::*; | 181 | use empty_iter::*; |
@@ -162,14 +189,14 @@ fn main() { | |||
162 | let x = Empty; | 189 | let x = Empty; |
163 | for (x, y) in x.iter() { | 190 | for (x, y) in x.iter() { |
164 | println!("x: {}, y: {}", x, y) | 191 | println!("x: {}, y: {}", x, y) |
165 | }; | 192 | } |
166 | } | 193 | } |
167 | "#, | 194 | "#, |
168 | ) | 195 | ) |
169 | } | 196 | } |
170 | 197 | ||
171 | #[test] | 198 | #[test] |
172 | fn test_for_each_in_closure() { | 199 | fn test_for_each_in_closure_stmt() { |
173 | check_assist_with_fixtures( | 200 | check_assist_with_fixtures( |
174 | r#" | 201 | r#" |
175 | use empty_iter::*; | 202 | use empty_iter::*; |
@@ -183,7 +210,7 @@ fn main() { | |||
183 | let x = Empty; | 210 | let x = Empty; |
184 | for (x, y) in x.iter() { | 211 | for (x, y) in x.iter() { |
185 | println!("x: {}, y: {}", x, y) | 212 | println!("x: {}, y: {}", x, y) |
186 | }; | 213 | } |
187 | } | 214 | } |
188 | "#, | 215 | "#, |
189 | ) | 216 | ) |