diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/handlers/extract_assignment.rs | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/crates/assists/src/handlers/extract_assignment.rs b/crates/assists/src/handlers/extract_assignment.rs index 604297705..281cf5d24 100644 --- a/crates/assists/src/handlers/extract_assignment.rs +++ b/crates/assists/src/handlers/extract_assignment.rs | |||
@@ -40,25 +40,52 @@ use crate::{ | |||
40 | pub(crate) fn extract_assigment(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 40 | pub(crate) fn extract_assigment(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
41 | let name = ctx.find_node_at_offset::<ast::NameRef>()?.as_name(); | 41 | let name = ctx.find_node_at_offset::<ast::NameRef>()?.as_name(); |
42 | 42 | ||
43 | let if_statement = ctx.find_node_at_offset::<ast::IfExpr>()?; | 43 | let (old_stmt, new_stmt) = if let Some(if_expr) = ctx.find_node_at_offset::<ast::IfExpr>() { |
44 | ( | ||
45 | ast::Expr::cast(if_expr.syntax().to_owned())?, | ||
46 | exprify_if(&if_expr, &name)?.indent(if_expr.indent_level()), | ||
47 | ) | ||
48 | } else if let Some(match_expr) = ctx.find_node_at_offset::<ast::MatchExpr>() { | ||
49 | (ast::Expr::cast(match_expr.syntax().to_owned())?, exprify_match(&match_expr, &name)?) | ||
50 | } else { | ||
51 | return None; | ||
52 | }; | ||
44 | 53 | ||
45 | let new_stmt = exprify_if(&if_statement, &name)?.indent(if_statement.indent_level()); | ||
46 | let expr_stmt = make::expr_stmt(new_stmt); | 54 | let expr_stmt = make::expr_stmt(new_stmt); |
47 | 55 | ||
48 | acc.add( | 56 | acc.add( |
49 | AssistId("extract_assignment", AssistKind::RefactorExtract), | 57 | AssistId("extract_assignment", AssistKind::RefactorExtract), |
50 | "Extract assignment", | 58 | "Extract assignment", |
51 | if_statement.syntax().text_range(), | 59 | old_stmt.syntax().text_range(), |
52 | move |edit| { | 60 | move |edit| { |
53 | edit.replace(if_statement.syntax().text_range(), format!("{} = {};", name, expr_stmt)); | 61 | edit.replace(old_stmt.syntax().text_range(), format!("{} = {};", name, expr_stmt)); |
54 | }, | 62 | }, |
55 | ) | 63 | ) |
56 | } | 64 | } |
57 | 65 | ||
66 | fn exprify_match(match_expr: &ast::MatchExpr, name: &hir::Name) -> Option<ast::Expr> { | ||
67 | let new_arm_list = match_expr | ||
68 | .match_arm_list()? | ||
69 | .arms() | ||
70 | .map(|arm| { | ||
71 | if let ast::Expr::BlockExpr(block) = arm.expr()? { | ||
72 | let new_block = exprify_block(&block, name)?.indent(block.indent_level()); | ||
73 | Some(arm.replace_descendant(block, new_block)) | ||
74 | } else { | ||
75 | None | ||
76 | } | ||
77 | }) | ||
78 | .collect::<Option<Vec<_>>>()?; | ||
79 | let new_arm_list = match_expr | ||
80 | .match_arm_list()? | ||
81 | .replace_descendants(match_expr.match_arm_list()?.arms().zip(new_arm_list)); | ||
82 | Some(make::expr_match(match_expr.expr()?, new_arm_list)) | ||
83 | } | ||
84 | |||
58 | fn exprify_if(statement: &ast::IfExpr, name: &hir::Name) -> Option<ast::Expr> { | 85 | fn exprify_if(statement: &ast::IfExpr, name: &hir::Name) -> Option<ast::Expr> { |
59 | let then_branch = exprify_block(&statement.then_branch()?, name)?; | 86 | let then_branch = exprify_block(&statement.then_branch()?, name)?; |
60 | let else_branch = match statement.else_branch()? { | 87 | let else_branch = match statement.else_branch()? { |
61 | ast::ElseBranch::Block(block) => ast::ElseBranch::Block(exprify_block(&block, name)?), | 88 | ast::ElseBranch::Block(ref block) => ast::ElseBranch::Block(exprify_block(block, name)?), |
62 | ast::ElseBranch::IfExpr(expr) => { | 89 | ast::ElseBranch::IfExpr(expr) => { |
63 | mark::hit!(test_extract_assigment_chained_if); | 90 | mark::hit!(test_extract_assigment_chained_if); |
64 | ast::ElseBranch::IfExpr(ast::IfExpr::cast( | 91 | ast::ElseBranch::IfExpr(ast::IfExpr::cast( |
@@ -97,7 +124,7 @@ mod tests { | |||
97 | use crate::tests::{check_assist, check_assist_not_applicable}; | 124 | use crate::tests::{check_assist, check_assist_not_applicable}; |
98 | 125 | ||
99 | #[test] | 126 | #[test] |
100 | fn test_extract_assignment() { | 127 | fn test_extract_assignment_if() { |
101 | check_assist( | 128 | check_assist( |
102 | extract_assigment, | 129 | extract_assigment, |
103 | r#" | 130 | r#" |
@@ -124,6 +151,45 @@ fn foo() { | |||
124 | } | 151 | } |
125 | 152 | ||
126 | #[test] | 153 | #[test] |
154 | fn test_extract_assignment_match() { | ||
155 | check_assist( | ||
156 | extract_assigment, | ||
157 | r#" | ||
158 | fn foo() { | ||
159 | let mut a = 1; | ||
160 | |||
161 | match 1 { | ||
162 | 1 => { | ||
163 | <|>a = 2; | ||
164 | }, | ||
165 | 2 => { | ||
166 | a = 3; | ||
167 | }, | ||
168 | 3 => { | ||
169 | a = 4; | ||
170 | } | ||
171 | } | ||
172 | }"#, | ||
173 | r#" | ||
174 | fn foo() { | ||
175 | let mut a = 1; | ||
176 | |||
177 | a = match 1 { | ||
178 | 1 => { | ||
179 | 2 | ||
180 | }, | ||
181 | 2 => { | ||
182 | 3 | ||
183 | }, | ||
184 | 3 => { | ||
185 | 4 | ||
186 | } | ||
187 | }; | ||
188 | }"#, | ||
189 | ); | ||
190 | } | ||
191 | |||
192 | #[test] | ||
127 | fn test_extract_assignment_not_last_not_applicable() { | 193 | fn test_extract_assignment_not_last_not_applicable() { |
128 | check_assist_not_applicable( | 194 | check_assist_not_applicable( |
129 | extract_assigment, | 195 | extract_assigment, |
@@ -222,7 +288,7 @@ fn foo() { | |||
222 | } | 288 | } |
223 | 289 | ||
224 | #[test] | 290 | #[test] |
225 | fn extract_assignment_missing_assigment_not_applicable() { | 291 | fn extract_assignment_if_missing_assigment_not_applicable() { |
226 | check_assist_not_applicable( | 292 | check_assist_not_applicable( |
227 | extract_assigment, | 293 | extract_assigment, |
228 | r#" | 294 | r#" |
@@ -235,4 +301,25 @@ fn foo() { | |||
235 | }"#, | 301 | }"#, |
236 | ) | 302 | ) |
237 | } | 303 | } |
304 | |||
305 | #[test] | ||
306 | fn extract_assignment_match_missing_assigment_not_applicable() { | ||
307 | check_assist_not_applicable( | ||
308 | extract_assigment, | ||
309 | r#" | ||
310 | fn foo() { | ||
311 | let mut a = 1; | ||
312 | |||
313 | match 1 { | ||
314 | 1 => { | ||
315 | <|>a = 2; | ||
316 | }, | ||
317 | 2 => { | ||
318 | a = 3; | ||
319 | }, | ||
320 | 3 => {}, | ||
321 | } | ||
322 | }"#, | ||
323 | ) | ||
324 | } | ||
238 | } | 325 | } |