{"record":{"id":"86a491e54ed10856","repo":"oxc-project/oxc","slug":"unexpected-use-of-comma-operator","errorCode":null,"errorMessage":"Unexpected use of comma operator","messagePattern":"Unexpected use of comma operator","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_sequences.rs","lineNumber":14,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::{GetSpan, Span};\nuse schemars::JsonSchema;\nuse serde::Deserialize;\n\nuse crate::{\n    AstNode, ast_util::outermost_paren_parent, context::LintContext, rule::DefaultRuleConfig,\n    rule::Rule,\n};\n\nfn no_sequences_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected use of comma operator\")\n        .with_help(\"Do not use the comma operator. If you intended to write a sequence, wrap it in parentheses.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Clone, JsonSchema, Deserialize)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\npub struct NoSequences {\n    /// If this option is set to `false`, this rule disallows the comma operator\n    /// even when the expression sequence is explicitly wrapped in parentheses.\n    allow_in_parentheses: bool,\n}\n\nimpl Default for NoSequences {\n    fn default() -> Self {\n        Self { allow_in_parentheses: true }\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_sequences.rs#L1-L32","documentation":"oxlint's port of ESLint `no-sequences`. It flags the comma operator, which evaluates both operands and returns the last — a construct that hides side effects and is frequently a typo for semicolons or for array literals. With `allowInParentheses: false` (oxlint default), even explicitly parenthesized sequences like `(a, b)` are flagged; setting it true permits sequences wrapped in parentheses.","triggerScenarios":"`x = (1, 2);`, `const y = (a(), b);`, `if ((a, b)) ...`, `return 1, 2;` — the rule inspects SequenceExpression nodes found via `outermost_paren_parent`. Sequence expressions in `for` headers are the conventional tolerated location.","commonSituations":"Minified/hand-compressed code pasted into a repo; obfuscated snippets; accidental comma where a semicolon or `&&` was intended.","solutions":["Split into separate statements: `a(); const y = b;`.","If both results are needed, use an array `const [r1, r2] = [a(), b];` or chaining with `&&`.","For deliberate short sequences, keep them in a `for` header or set `\"allowInParentheses\": true`."],"exampleFix":"// before\nconst y = (sideEffect(), value);\n\n// after\nsideEffect();\nconst y = value;","handlingStrategy":"validation","validationCode":"// Find comma-operator sequences outside for-headers\nfunction sequenceOutsideFor(src) {\n  const noFor = src.replace(/for\\s*\\([^)]*\\)/g, '');\n  return /\\((?:[^()]*,)+[^()]*\\)(?!\\s*\\()/.test(noFor) && /,/.test(noFor.replace(/\\[[^\\]]*\\]/g, ''));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to separate statements; reach for `&&` chaining only when short-circuiting is the point.","Keep the only comma sequences in `for` headers (`for (let i = 0, j = n; ...)`).","Run new third-party snippets through oxlint before pasting them into the codebase."],"tags":["lint","eslint","no-sequences","expressions","best-practices"],"backgroundTag":"comma-operator-misuse","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}