diff options
-rw-r--r-- | crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs | 79 |
1 files changed, 50 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 3220f2f46..2dc4fbcd4 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 | |||
@@ -1,6 +1,5 @@ | |||
1 | use ide_db::helpers::FamousDefs; | 1 | use ide_db::helpers::FamousDefs; |
2 | use stdx::format_to; | 2 | use syntax::{AstNode, ast::{self, make, ArgListOwner, edit::AstNodeEdit}}; |
3 | use syntax::{AstNode, ast::{self, ArgListOwner}}; | ||
4 | 3 | ||
5 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | 4 | use crate::{AssistContext, AssistId, AssistKind, Assists}; |
6 | 5 | ||
@@ -47,7 +46,7 @@ pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContex | |||
47 | let (total_expr, parent) = validate_method_call_expr(&ctx.sema, total_expr)?; | 46 | let (total_expr, parent) = validate_method_call_expr(&ctx.sema, total_expr)?; |
48 | 47 | ||
49 | let param_list = closure.param_list()?; | 48 | let param_list = closure.param_list()?; |
50 | let param = param_list.params().next()?; | 49 | let param = param_list.params().next()?.pat()?; |
51 | let body = closure.body()?; | 50 | let body = closure.body()?; |
52 | 51 | ||
53 | acc.add( | 52 | acc.add( |
@@ -55,16 +54,15 @@ pub(crate) fn convert_iter_for_each_to_for(acc: &mut Assists, ctx: &AssistContex | |||
55 | "Replace this `Iterator::for_each` with a for loop", | 54 | "Replace this `Iterator::for_each` with a for loop", |
56 | total_expr.syntax().text_range(), | 55 | total_expr.syntax().text_range(), |
57 | |builder| { | 56 | |builder| { |
58 | let mut buf = String::new(); | 57 | let original_indentation = total_expr.indent_level(); |
59 | 58 | ||
60 | format_to!(buf, "for {} in {} ", param, parent); | 59 | let block = match body { |
60 | ast::Expr::BlockExpr(block) => block, | ||
61 | _ => make::block_expr(Vec::new(), Some(body)) | ||
62 | }.reset_indent().indent(original_indentation); | ||
61 | 63 | ||
62 | match body { | 64 | let expr_for_loop = make::expr_for_loop(param, parent, block); |
63 | ast::Expr::BlockExpr(body) => format_to!(buf, "{}", body), | 65 | builder.replace_ast(total_expr, expr_for_loop) |
64 | _ => format_to!(buf, "{{\n{}\n}}", body) | ||
65 | } | ||
66 | |||
67 | builder.replace(total_expr.syntax().text_range(), buf) | ||
68 | }, | 66 | }, |
69 | ) | 67 | ) |
70 | } | 68 | } |
@@ -94,45 +92,68 @@ mod tests { | |||
94 | 92 | ||
95 | use super::*; | 93 | use super::*; |
96 | 94 | ||
95 | fn check_assist_with_fixtures(before: &str, after: &str) { | ||
96 | let before = &format!( | ||
97 | "//- /main.rs crate:main deps:core,empty_iter{}{}", | ||
98 | before, | ||
99 | FamousDefs::FIXTURE, | ||
100 | ); | ||
101 | check_assist(convert_iter_for_each_to_for, before, after); | ||
102 | } | ||
103 | |||
97 | #[test] | 104 | #[test] |
98 | fn test_for_each_in_method() { | 105 | fn test_for_each_in_method() { |
99 | check_assist( | 106 | check_assist_with_fixtures( |
100 | convert_iter_for_each_to_for, | 107 | r#" |
101 | r" | ||
102 | fn main() { | 108 | fn main() { |
103 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | 109 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; |
104 | x.iter().$0for_each(|(x, y)| { | 110 | x.iter().$0for_each(|(x, y)| { |
105 | dbg!(x, y) | 111 | println!("x: {}, y: {}", x, y); |
106 | }); | 112 | }); |
107 | }", | 113 | }"#, |
108 | r" | 114 | r#" |
115 | fn main() { | ||
116 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | ||
117 | for (x, y) in x.iter() { | ||
118 | println!("x: {}, y: {}", x, y); | ||
119 | }; | ||
120 | }"#, | ||
121 | ) | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn test_for_each_without_braces() { | ||
126 | check_assist_with_fixtures( | ||
127 | r#" | ||
128 | fn main() { | ||
129 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | ||
130 | x.iter().$0for_each(|(x, y)| println!("x: {}, y: {}", x, y)); | ||
131 | }"#, | ||
132 | r#" | ||
109 | fn main() { | 133 | fn main() { |
110 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | 134 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; |
111 | for (x, y) in x.iter() { | 135 | for (x, y) in x.iter() { |
112 | dbg!(x, y) | 136 | println!("x: {}, y: {}", x, y) |
113 | }; | 137 | }; |
114 | }", | 138 | }"#, |
115 | ) | 139 | ) |
116 | } | 140 | } |
117 | 141 | ||
118 | #[test] | 142 | #[test] |
119 | fn test_for_each_in_closure() { | 143 | fn test_for_each_in_closure() { |
120 | check_assist( | 144 | check_assist_with_fixtures( |
121 | convert_iter_for_each_to_for, | 145 | r#" |
122 | r" | ||
123 | fn main() { | 146 | fn main() { |
124 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | 147 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; |
125 | x.iter().for_each($0|(x, y)| { | 148 | x.iter().for_each($0|(x, y)| println!("x: {}, y: {}", x, y)); |
126 | dbg!(x, y) | 149 | }"#, |
127 | }); | 150 | r#" |
128 | }", | ||
129 | r" | ||
130 | fn main() { | 151 | fn main() { |
131 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; | 152 | let x = vec![(1, 1), (2, 2), (3, 3), (4, 4)]; |
132 | for (x, y) in x.iter() { | 153 | for (x, y) in x.iter() { |
133 | dbg!(x, y) | 154 | println!("x: {}, y: {}", x, y) |
134 | }; | 155 | }; |
135 | }", | 156 | }"#, |
136 | ) | 157 | ) |
137 | } | 158 | } |
138 | } \ No newline at end of file | 159 | } \ No newline at end of file |