aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src')
-rw-r--r--crates/assists/src/handlers/extract_assignment.rs101
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::{
40pub(crate) fn extract_assigment(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 40pub(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
66fn 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
58fn exprify_if(statement: &ast::IfExpr, name: &hir::Name) -> Option<ast::Expr> { 85fn 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#"
158fn 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#"
174fn 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#"
310fn 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}