Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 34 additions & 16 deletions crates/ide_assists/src/handlers/pull_assignment_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
return None;
};

if let Some(parent) = tgt.syntax().parent() {
if matches!(parent.kind(), syntax::SyntaxKind::BIN_EXPR | syntax::SyntaxKind::LET_STMT) {
return None;
}
}

acc.add(
AssistId("pull_assignment_up", AssistKind::RefactorExtract),
"Pull assignment up",
Expand All @@ -74,7 +80,13 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
let tgt = edit.make_ast_mut(tgt);

for (stmt, rhs) in assignments {
ted::replace(stmt.syntax(), rhs.syntax());
let mut stmt = stmt.syntax().clone();
if let Some(parent) = stmt.parent() {
if ast::ExprStmt::cast(parent.clone()).is_some() {
stmt = parent.clone();
}
}
ted::replace(stmt, rhs.syntax());
}
let assign_expr = make::expr_assignment(collector.common_lhs, tgt.clone());
let assign_stmt = make::expr_stmt(assign_expr);
Expand All @@ -87,14 +99,15 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
struct AssignmentsCollector<'a> {
sema: &'a hir::Semantics<'a, ide_db::RootDatabase>,
common_lhs: ast::Expr,
assignments: Vec<(ast::ExprStmt, ast::Expr)>,
assignments: Vec<(ast::BinExpr, ast::Expr)>,
}

impl<'a> AssignmentsCollector<'a> {
fn collect_match(&mut self, match_expr: &ast::MatchExpr) -> Option<()> {
for arm in match_expr.match_arm_list()?.arms() {
match arm.expr()? {
ast::Expr::BlockExpr(block) => self.collect_block(&block)?,
ast::Expr::BinExpr(expr) => self.collect_expr(&expr)?,
_ => return None,
}
}
Expand All @@ -114,24 +127,30 @@ impl<'a> AssignmentsCollector<'a> {
}
}
fn collect_block(&mut self, block: &ast::BlockExpr) -> Option<()> {
if block.tail_expr().is_some() {
return None;
}

let last_stmt = block.statements().last()?;
if let ast::Stmt::ExprStmt(stmt) = last_stmt {
if let ast::Expr::BinExpr(expr) = stmt.expr()? {
if expr.op_kind()? == ast::BinOp::Assignment
&& is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
{
self.assignments.push((stmt, expr.rhs()?));
return Some(());
}
let last_expr = block.tail_expr().or_else(|| {
if let ast::Stmt::ExprStmt(stmt) = block.statements().last()? {
stmt.expr()
} else {
None
}
})?;

if let ast::Expr::BinExpr(expr) = last_expr {
return self.collect_expr(&expr);
}

None
}

fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> {
if expr.op_kind()? == ast::BinOp::Assignment
&& is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
{
self.assignments.push((expr.clone(), expr.rhs()?));
return Some(());
}
None
}
}

fn is_equivalent(
Expand Down Expand Up @@ -241,7 +260,6 @@ fn foo() {
}

#[test]
#[ignore]
fn test_pull_assignment_up_assignment_expressions() {
check_assist(
pull_assignment_up,
Expand Down