oxc-project/oxc · error · OxcDiagnostic

Misrefactored assign op. Variable appears on both sides of a

Error message

Misrefactored assign op. Variable appears on both sides of an assignment operation

What it means

Oxlint rule `oxc/misrefactored-assign-op` (ported from clippy's misrefactored_assign_op) flags compound assignments whose right-hand side repeats the assigned target under the same operator: `a op= a op b`, and for commutative operators (+, *, |, ^, &) also `a op= b op a`. These are almost always a half-finished refactor between `a = a op b` and `a op= b`; e.g. `a += a + 1` actually computes `a = a + (a + 1)`. Member targets (`obj.x += obj.x + 1`) are matched too, and the rule provides an autofix to `a op= b`.

Source

Thrown at crates/oxc_linter/src/rules/oxc/misrefactored_assign_op.rs:19

// Based on https://github.com/rust-lang/rust-clippy//blob/c9a43b18f11219fa70fe632b29518581fcd589c8/clippy_lints/src/operators/misrefactored_assign_op.rs
use oxc_ast::{
    AstKind,
    ast::{AssignmentTarget, Expression, SimpleAssignmentTarget, match_member_expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator};

use crate::{
    AstNode,
    context::LintContext,
    rule::Rule,
    utils::{is_same_expression, is_same_member_expression},
};

fn misrefactored_assign_op_diagnostic(span: Span, suggestion: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Misrefactored assign op. Variable appears on both sides of an assignment operation",
    )
    .with_help(format!("Did you mean `{suggestion}`?"))
    .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct MisrefactoredAssignOp;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// https://rust-lang.github.io/rust-clippy/master/#/misrefactored_assign_op
    ///
    /// Checks for `a op= a op b` or `a op= b op a` patterns.
    ///
    /// ### Why is this bad?
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Apply the suggested form (autofix available): drop the duplicated target from the right-hand side
  2. If both operations were truly intended (`a = a + (a + 1)`), rewrite it as a plain assignment with parentheses so the grouping is explicit
  3. Re-run tests on arithmetic-heavy code after any assignment refactor

Example fix

// before
a += a + 1; // computes a = a + (a + 1)

// after
a += 1;
Defensive patterns

Strategy: validation

Validate before calling

// .oxlintrc.json — suspicious rule with autofix
{
  "rules": { "oxc/misrefactored-assign-op": "error" }
}
// CLI (applies the fix): npx oxlint --fix src/

Prevention

When it happens

Trigger: `a += a + 1` (fix: `a += 1`); `a -= a - 1` (fix: `a -= 1`); `a *= 42 * a` (fix: `a *= 42`); `a /= a / 2`; `obj.x += obj.x + n`.

Common situations: Mechanical refactors from `a = a + b` to `a += b` that leave the old right-hand side; codemod or sed rewrites; merging statements by hand.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/d5c95c340f8bdeee. Report an issue: GitHub.