aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/handlers/pull_assignment_up.rs50
1 files changed, 34 insertions, 16 deletions
diff --git a/crates/ide_assists/src/handlers/pull_assignment_up.rs b/crates/ide_assists/src/handlers/pull_assignment_up.rs
index 28d14b9c3..3128faa68 100644
--- a/crates/ide_assists/src/handlers/pull_assignment_up.rs
+++ b/crates/ide_assists/src/handlers/pull_assignment_up.rs
@@ -60,6 +60,12 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
60 return None; 60 return None;
61 }; 61 };
62 62
63 if let Some(parent) = tgt.syntax().parent() {
64 if matches!(parent.kind(), syntax::SyntaxKind::BIN_EXPR | syntax::SyntaxKind::LET_STMT) {
65 return None;
66 }
67 }
68
63 acc.add( 69 acc.add(
64 AssistId("pull_assignment_up", AssistKind::RefactorExtract), 70 AssistId("pull_assignment_up", AssistKind::RefactorExtract),
65 "Pull assignment up", 71 "Pull assignment up",
@@ -74,7 +80,13 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
74 let tgt = edit.make_ast_mut(tgt); 80 let tgt = edit.make_ast_mut(tgt);
75 81
76 for (stmt, rhs) in assignments { 82 for (stmt, rhs) in assignments {
77 ted::replace(stmt.syntax(), rhs.syntax()); 83 let mut stmt = stmt.syntax().clone();
84 if let Some(parent) = stmt.parent() {
85 if ast::ExprStmt::cast(parent.clone()).is_some() {
86 stmt = parent.clone();
87 }
88 }
89 ted::replace(stmt, rhs.syntax());
78 } 90 }
79 let assign_expr = make::expr_assignment(collector.common_lhs, tgt.clone()); 91 let assign_expr = make::expr_assignment(collector.common_lhs, tgt.clone());
80 let assign_stmt = make::expr_stmt(assign_expr); 92 let assign_stmt = make::expr_stmt(assign_expr);
@@ -87,7 +99,7 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
87struct AssignmentsCollector<'a> { 99struct AssignmentsCollector<'a> {
88 sema: &'a hir::Semantics<'a, ide_db::RootDatabase>, 100 sema: &'a hir::Semantics<'a, ide_db::RootDatabase>,
89 common_lhs: ast::Expr, 101 common_lhs: ast::Expr,
90 assignments: Vec<(ast::ExprStmt, ast::Expr)>, 102 assignments: Vec<(ast::BinExpr, ast::Expr)>,
91} 103}
92 104
93impl<'a> AssignmentsCollector<'a> { 105impl<'a> AssignmentsCollector<'a> {
@@ -95,6 +107,7 @@ impl<'a> AssignmentsCollector<'a> {
95 for arm in match_expr.match_arm_list()?.arms() { 107 for arm in match_expr.match_arm_list()?.arms() {
96 match arm.expr()? { 108 match arm.expr()? {
97 ast::Expr::BlockExpr(block) => self.collect_block(&block)?, 109 ast::Expr::BlockExpr(block) => self.collect_block(&block)?,
110 ast::Expr::BinExpr(expr) => self.collect_expr(&expr)?,
98 _ => return None, 111 _ => return None,
99 } 112 }
100 } 113 }
@@ -114,24 +127,30 @@ impl<'a> AssignmentsCollector<'a> {
114 } 127 }
115 } 128 }
116 fn collect_block(&mut self, block: &ast::BlockExpr) -> Option<()> { 129 fn collect_block(&mut self, block: &ast::BlockExpr) -> Option<()> {
117 if block.tail_expr().is_some() { 130 let last_expr = block.tail_expr().or_else(|| {
118 return None; 131 if let ast::Stmt::ExprStmt(stmt) = block.statements().last()? {
119 } 132 stmt.expr()
120 133 } else {
121 let last_stmt = block.statements().last()?; 134 None
122 if let ast::Stmt::ExprStmt(stmt) = last_stmt {
123 if let ast::Expr::BinExpr(expr) = stmt.expr()? {
124 if expr.op_kind()? == ast::BinOp::Assignment
125 && is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
126 {
127 self.assignments.push((stmt, expr.rhs()?));
128 return Some(());
129 }
130 } 135 }
136 })?;
137
138 if let ast::Expr::BinExpr(expr) = last_expr {
139 return self.collect_expr(&expr);
131 } 140 }
132 141
133 None 142 None
134 } 143 }
144
145 fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> {
146 if expr.op_kind()? == ast::BinOp::Assignment
147 && is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
148 {
149 self.assignments.push((expr.clone(), expr.rhs()?));
150 return Some(());
151 }
152 None
153 }
135} 154}
136 155
137fn is_equivalent( 156fn is_equivalent(
@@ -241,7 +260,6 @@ fn foo() {
241 } 260 }
242 261
243 #[test] 262 #[test]
244 #[ignore]
245 fn test_pull_assignment_up_assignment_expressions() { 263 fn test_pull_assignment_up_assignment_expressions() {
246 check_assist( 264 check_assist(
247 pull_assignment_up, 265 pull_assignment_up,