{"record":{"id":"dfb816e664392ba5","repo":"oxc-project/oxc","slug":"bad-comparison-sequence","errorCode":null,"errorMessage":"Bad comparison sequence","messagePattern":"Bad comparison sequence","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/oxc/bad_comparison_sequence.rs","lineNumber":15,"sourceCode":"use oxc_ast::{\n    AstKind,\n    ast::{BinaryExpression, Expression},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{AstNode, context::LintContext, rule::Rule};\n\nfn bad_comparison_sequence_diagnostic(\n    comparison_result: Span,\n    compared_against: Span,\n) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Bad comparison sequence\")\n        .with_help(\"Comparison result should not be used directly as an operand of another comparison. If you need to compare three or more operands, you should connect each comparison operation with logical AND operator (`&&`)\")\n        .with_labels([\n            comparison_result.label(\"This comparison expression produces a boolean\"),\n            compared_against.label(\"That boolean is then compared with this operand\"),\n        ])\n}\n\n#[derive(Debug, Default, Clone)]\npub struct BadComparisonSequence;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// This rule applies when the comparison operator is applied two or more times in a row.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Because comparison operator is a binary operator, it is impossible to compare three or more operands at once.","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/oxc/bad_comparison_sequence.rs#L1-L33","documentation":"Diagnostic from oxlint rule oxc/bad-comparison-sequence (correctness category). JavaScript comparisons are binary and left-associative: `a == b == c` parses as `(a == b) == c`, i.e. the boolean from the first comparison is compared against c — not a three-way check as in Python. The rule fires when the left operand of an equality or relational expression is itself an equality or relational expression of the same class, and labels both spans: which comparison produces the boolean, and which operand that boolean is then compared against.","triggerScenarios":"A BinaryExpression whose operator is equality (==/!=/===/!==) or relational (</<=/>/>=) AND whose left operand is a BinaryExpression of the same class (both equality, or both relational). Triggers: if (a == b == c), if (x < y <= z), and chained forms like a == b == c == d. ParenthesizedExpression boundaries and statement/declaration boundaries cap the walk so a chain reports exactly once (the ancestor check has_no_bad_comparison_in_parents suppresses inner duplicates).","commonSituations":"Developers coming from Python, where a < b < c chains natively; math-range checks (if (lo < x < hi)) typed without unpacking; the expression compiles and 'works' — the boolean just coerces (true == 1) so tests built on the same assumption pass while the logic is wrong.","solutions":["Split into pairwise comparisons joined by &&: a === b && b === c","For range checks: lo < x && x < hi","Extract each comparison into a well-named boolean (const inRange = lo < x && x < hi) for readability"],"exampleFix":"// before\nif (a == b == c) {\n  console.log('a, b, and c are the same'); // actually (a == b) == c\n}\n\n// after\nif (a == b && b == c) {\n  console.log('a, b, and c are the same');\n}","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n\"rules\": { \"oxc/bad-comparison-sequence\": \"error\" }\n\nnpx oxlint -c .oxlintrc.json --deny-warning .","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unlearn Python chaining: in JS every comparison takes exactly two operands, so split chains with &&","Write range checks as lo < x && x < hi and consider extracting them into a named helper (inRange)","Add boundary tests around comparisons — chained-comparison bugs produce wrong-but-plausible booleans that unit tests catch immediately"],"tags":["oxc","javascript","operators","comparison","logic-bug","oxlint"],"backgroundTag":"chained-comparison-operators","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"}