- Exclude Prettier's `_errors_/` and `range/` fixtures from `js-in-vue`
- Rename `issue-19667.ts` to `.tsx` so it parses
- Treat both sides failing to parse as a failure
JSON reporting creates a zero-context span scanner per diagnostic. Its prefix scan walks every newline and updates an empty context queue, even though the existing one-context-line path already counts LF breaks in bulk.
Use bulk LF counting and a reverse newline lookup for zero-context prefixes too. Prefixes containing CR retain the existing path. The regression test compares every byte cut against the generic scanner, including empty input, LF, mixed CR/CRLF and multibyte text.
On VS Code with a fixed cached stream of approximately 276,000 diagnostics, the complete JSON-output command fell from 4.79s to 1.74s on an M2 Max. Two release measurement rounds each used one warm-up and three measured runs: wall time improved 62–64%, frontend instructions fell from roughly 59–60B to 35B, and peak RSS stayed broadly unchanged. Complete diagnostic multisets matched. The baseline strips symbols and the patched build retains them; optimization settings match. These are cached-replay command timings, not isolated rendering-phase timings.
Oxlint skipped the final `else { if (b) {} }` in `if (a) {} else if (d) {} else { if (b) {} }`, which ESLint reports. Follow the chain through alternate branches before applying the existing guard for an enclosing `if` body, preserving dangling-`else` protection.
Addresses report 14 (`eslint/no-lonely-if`) in #27746.
`sort-imports` stopped at the first non-import statement, so leading variable declarations and interleaved statements hid later sorting violations. Check all top-level imports while preserving ESLint's declaration grouping and member-sort options, with regression and autofix coverage.
Addresses report 7 (`eslint/sort-imports`) in #27746.
`arr.slice(-1)[0]` now reports once, including on the right of assignments. Route slice-index checks through the computed-member visitor and distinguish write targets from destructuring default values; keep parentheses balanced in fixes.
Addresses report 6 (`unicorn/prefer-at`) of #27746. Adds diagnostic and autofix regressions.
## Why
`oxlint --fix` currently turns valid code into a syntax error here
(oxlint 1.87.0, checked with `node --check`):
```js
foo(function() {} ? a : b); // -> foo(() => {} ? a : b); SyntaxError
new Foo(function() {} ? a : b); // -> new Foo(() => {} ? a : b); SyntaxError
foo(async function() {} ? a : b); // -> foo(async () => {} ? a : b); SyntaxError
```
ESLint had the same bug (eslint/eslint#21368) and fixed it in
eslint/eslint#21373 by not treating a function in the test of a
conditional as a callback. This ports that fix.
Found while running ESLint's upstream test file for this rule through
oxlint.
## Problem
`get_callback_info` kept walking up through a `ConditionalExpression`
even when the function was the conditional's `test`. A function used as
a test is not the callback, the conditional's result is. ESLint treats
these as valid (tests/lib/rules/prefer-arrow-callback.js L52-L59).
Before, oxlint reported `Unexpected function expression` for each of
these:
```js
foo(function() {} ? a : b);
foo(function() { this; }.bind(this) ? a : b);
foo(bar ? function() {} ? a : b : c);
new Foo(function() {} ? a : b);
```
After, none are reported. Functions in the consequent or alternate are
still callbacks, for example `foo(bar ? function() {} : function() {})`
is still reported and fixed.
## Changes
- In the `ConditionalExpression` arm, stop when the node is the `test`.
Only continue for the consequent and alternate.
- Add the eight upstream valid cases (L52-L59) to the pass vector. No
snapshot change, since only pass cases were added.
## Testing
`cargo test -p oxc_linter --lib prefer_arrow_callback`, `cargo fmt`,
`cargo clippy -p oxc_linter --all-targets -- -D warnings` all pass.
---
Written with the help of an agent (Claude Code, claude-opus-5-5
orchestrating claude-sonnet-5-5).
---------
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
Addresses report 18 (`unicorn/prefer-native-coercion-functions`) in #27746.
Oxlint skipped both `{ m(v) { return String(v); } }` and `{ m: function(v) { return String(v); } }`, which Unicorn reports. Restrict the object-property exclusion to the setter's value function, so ordinary methods, function-valued properties, and functions in computed keys are checked while setters remain excluded.
- Bump `oxc-yaml-parser` to 0.0.7
- handles NUL as content, BOM only outside a document, markers only at column 0
- Keep `---`/`...` content on the `---` line, keep `?` on a root key starting with a marker, and indent a flow scalar continuation line starting with a marker
- Add `---` before a document whose first text is U+FEFF
Values such as `{ b: "a\\b" }` were skipped whenever the property key was not a string literal. Only exempt non-computed string-literal keys so property values are reported and fixed consistently with Unicorn.
Addresses report 8 (`unicorn/prefer-string-raw`) in #27746.
Oxlint skipped concatenations nested inside an unrelated `+`, such as `a + (b ? "|" + c : "")` or a concatenation in a callback body. ESLint reports those inner chains independently.
Only group directly connected additions through parentheses, and keep string classification consistent at TypeScript expression boundaries.
Addresses report 10 (`eslint/prefer-template`) in #27746.
Instead of accepting `VariableDeclarator` and looking for the
`BindingIdentifier`, we can accept a `BindingIdentifier` directly and
avoid the need for an `unreachable!` call.
The expression containing the `unreachable!` call is redundant, we
already check those cases elsewhere. Instead of returning `bool` in
`is_statement_list_parent`, we now return the list of statements (if
any) for the given `AstKind` so we don't need to check the node kind
later.
Adds a new `NumberLiteral` enum to enumerate all (2) cases that we
realistically want to handle, eliminating the need for a `unreachable!`
call and also eliminating the call to a intended-for-debug-only
`debug_name` function.
The `ImportImportName` enum supports the smaller set of cases that we
want to handle, so refactoring to use that eliminates the need for
`unreachable!()`.
The unreachable case here is redundant, because we already check the
same condition earlier in the lint rule. By rearranging, the branch can
be avoided completely.
Ensure that all cases are handled by adding a new `ReturnKind` enum,
which replaces the multiple independent `bool` states. This way, the
boolean states become interconnected and we can exhaustively handle
cases.
`variable_declaration_kind` implicitly relies on the assumption that
`VariableDeclaration` contains a `VariableDeclarator`. _Probably_ this
will always be true, but it seems good to ensure our code will never
crash from this potentially changing in the future. It only requires
minor changes at each call site, since we change the return type to
`Option`.