Skip to content

Commit 22c3a62

Browse files
committed
Add support for MatchExpr to extract_assigment assist
1 parent 1e91544 commit 22c3a62

File tree

1 file changed

+74
-9
lines changed

1 file changed

+74
-9
lines changed

crates/assists/src/handlers/extract_assignment.rs

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,52 @@ use crate::{
3939
pub(crate) fn extract_assigment(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
4040
let name = ctx.find_node_at_offset::<ast::NameRef>()?.to_string();
4141

42-
let if_statement = ctx.find_node_at_offset::<ast::IfExpr>()?;
42+
let (old_stmt, new_stmt) = if let Some(if_expr) = ctx.find_node_at_offset::<ast::IfExpr>() {
43+
(
44+
ast::Expr::cast(if_expr.syntax().to_owned())?,
45+
exprify_if(&if_expr, &name)?.indent(if_expr.indent_level()),
46+
)
47+
} else if let Some(match_expr) = ctx.find_node_at_offset::<ast::MatchExpr>() {
48+
(ast::Expr::cast(match_expr.syntax().to_owned())?, exprify_match(&match_expr, &name)?)
49+
} else {
50+
return None;
51+
};
4352

44-
let new_stmt =
45-
exprify_if(&if_statement, &name.to_string())?.indent(if_statement.indent_level());
4653
let expr_stmt = make::expr_stmt(new_stmt);
4754

4855
acc.add(
4956
AssistId("extract_assignment", AssistKind::RefactorExtract),
5057
"Extract assignment",
51-
if_statement.syntax().text_range(),
58+
old_stmt.syntax().text_range(),
5259
move |edit| {
53-
edit.replace(if_statement.syntax().text_range(), format!("{} = {};", name, expr_stmt));
60+
edit.replace(old_stmt.syntax().text_range(), format!("{} = {};", name, expr_stmt));
5461
},
5562
)
5663
}
5764

65+
fn exprify_match(match_expr: &ast::MatchExpr, name: &str) -> Option<ast::Expr> {
66+
let new_arm_list = match_expr
67+
.match_arm_list()?
68+
.arms()
69+
.map(|arm| {
70+
if let ast::Expr::BlockExpr(block) = arm.expr()? {
71+
let new_block = exprify_block(&block, name)?.indent(block.indent_level());
72+
Some(arm.replace_descendant(block, new_block))
73+
} else {
74+
None
75+
}
76+
})
77+
.collect::<Option<Vec<_>>>()?;
78+
let new_arm_list = match_expr
79+
.match_arm_list()?
80+
.replace_descendants(match_expr.match_arm_list()?.arms().zip(new_arm_list));
81+
Some(make::expr_match(match_expr.expr()?, new_arm_list))
82+
}
83+
5884
fn exprify_if(statement: &ast::IfExpr, name: &str) -> Option<ast::Expr> {
59-
let then_branch = exprify_block(statement.then_branch()?, name)?;
85+
let then_branch = exprify_block(&statement.then_branch()?, name)?;
6086
let else_branch = match statement.else_branch()? {
61-
ast::ElseBranch::Block(block) => ast::ElseBranch::Block(exprify_block(block, name)?),
87+
ast::ElseBranch::Block(ref block) => ast::ElseBranch::Block(exprify_block(block, name)?),
6288
ast::ElseBranch::IfExpr(expr) => {
6389
mark::hit!(test_extract_assigment_chained_if);
6490
ast::ElseBranch::IfExpr(ast::IfExpr::cast(
@@ -69,7 +95,7 @@ fn exprify_if(statement: &ast::IfExpr, name: &str) -> Option<ast::Expr> {
6995
Some(make::expr_if(statement.condition()?, then_branch, Some(else_branch)))
7096
}
7197

72-
fn exprify_block(block: ast::BlockExpr, name: &str) -> Option<ast::BlockExpr> {
98+
fn exprify_block(block: &ast::BlockExpr, name: &str) -> Option<ast::BlockExpr> {
7399
if block.expr().is_some() {
74100
return None;
75101
}
@@ -97,7 +123,7 @@ mod tests {
97123
use crate::tests::{check_assist, check_assist_not_applicable};
98124

99125
#[test]
100-
fn test_extract_assignment() {
126+
fn test_extract_assignment_if() {
101127
check_assist(
102128
extract_assigment,
103129
r#"
@@ -123,6 +149,45 @@ fn foo() {
123149
);
124150
}
125151

152+
#[test]
153+
fn test_extract_assignment_match() {
154+
check_assist(
155+
extract_assigment,
156+
r#"
157+
fn foo() {
158+
let mut a = 1;
159+
160+
match 1 {
161+
1 => {
162+
<|>a = 2;
163+
},
164+
2 => {
165+
a = 3;
166+
},
167+
3 => {
168+
a = 4;
169+
}
170+
}
171+
}"#,
172+
r#"
173+
fn foo() {
174+
let mut a = 1;
175+
176+
a = match 1 {
177+
1 => {
178+
2
179+
},
180+
2 => {
181+
3
182+
},
183+
3 => {
184+
4
185+
}
186+
};
187+
}"#,
188+
);
189+
}
190+
126191
#[test]
127192
fn test_extract_assignment_not_last_not_applicable() {
128193
check_assist_not_applicable(

0 commit comments

Comments
 (0)