{"record":{"id":"d5c95c340f8bdeee","repo":"oxc-project/oxc","slug":"misrefactored-assign-op-variable-appears-on-both","errorCode":null,"errorMessage":"Misrefactored assign op. Variable appears on both sides of an assignment operation","messagePattern":"Misrefactored assign op\\. Variable appears on both sides of an assignment operation","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/oxc/misrefactored_assign_op.rs","lineNumber":19,"sourceCode":"// Based on https://github.com/rust-lang/rust-clippy//blob/c9a43b18f11219fa70fe632b29518581fcd589c8/clippy_lints/src/operators/misrefactored_assign_op.rs\nuse oxc_ast::{\n    AstKind,\n    ast::{AssignmentTarget, Expression, SimpleAssignmentTarget, match_member_expression},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\nuse oxc_syntax::operator::{AssignmentOperator, BinaryOperator};\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::Rule,\n    utils::{is_same_expression, is_same_member_expression},\n};\n\nfn misrefactored_assign_op_diagnostic(span: Span, suggestion: &str) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\n        \"Misrefactored assign op. Variable appears on both sides of an assignment operation\",\n    )\n    .with_help(format!(\"Did you mean `{suggestion}`?\"))\n    .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct MisrefactoredAssignOp;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// https://rust-lang.github.io/rust-clippy/master/#/misrefactored_assign_op\n    ///\n    /// Checks for `a op= a op b` or `a op= b op a` patterns.\n    ///\n    /// ### Why is this bad?\n    ///","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/oxc/misrefactored_assign_op.rs#L1-L37","documentation":"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`.","triggerScenarios":"`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`.","commonSituations":"Mechanical refactors from `a = a + b` to `a += b` that leave the old right-hand side; codemod or sed rewrites; merging statements by hand.","solutions":["Apply the suggested form (autofix available): drop the duplicated target from the right-hand side","If both operations were truly intended (`a = a + (a + 1)`), rewrite it as a plain assignment with parentheses so the grouping is explicit","Re-run tests on arithmetic-heavy code after any assignment refactor"],"exampleFix":"// before\na += a + 1; // computes a = a + (a + 1)\n\n// after\na += 1;","handlingStrategy":"validation","validationCode":"// .oxlintrc.json — suspicious rule with autofix\n{\n  \"rules\": { \"oxc/misrefactored-assign-op\": \"error\" }\n}\n// CLI (applies the fix): npx oxlint --fix src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When converting `a = a op b` to `a op= b`, delete the duplicated target on the right","After codemods touching assignments, run oxlint and arithmetic tests","Prefer writing the compound form directly instead of editing the long form in place"],"tags":["oxlint","oxc","assignment","refactoring","logic-bug","javascript"],"backgroundTag":"misrefactored-compound-assignment","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}