Commit Graph

318 Commits

Author SHA1 Message Date
camc314 6a0e19cfaa feat(linter/eslint/no-unmodified-loop-condition): support checkConditionalExpressions option (#26249)
## Summary

- add the ESLint-compatible `checkConditionalExpressions` option to `no-unmodified-loop-condition`, defaulting to `false`
- port tests added by eslint/eslint#21175 and add regression coverage for repeated references within and across binary groups

Closes #26182.
2026-09-02 10:39:45 +00:00
Yuji Sugiura cd00a2c635 chore(oxlint): regenerate config types by cargo lintgen (#26195)
Follow up on #26193. (Also fixes main CI failures)

`json-schema-to-typescript`: `^15.0.4` → `^16.0.0` changed the output.
2026-08-31 13:25:13 +09:00
camc314 d5be0375e6 docs(linter/typescript/switch-exhaustiveness-check): clarify default case comment pattern (#26100)
## Summary
- clarify that `defaultCaseCommentPattern` recognizes a trailing comment in place of an omitted `default` clause
- document the required location, absence of a live `default`, and the `considerDefaultExhaustiveForUnions` requirement for union switches
- regenerate the JSON schema and TypeScript configuration types

Fixes #26087
2026-08-26 08:14:27 +00:00
Boshen 1193c9dbaf chore(oxfmt): dogfood operator position at line start (#25937)
dogfood
2026-08-20 14:36:47 +00:00
Boshen 228e8e0f85 fix(linter): resolve inactive React compiler rules (#25830)
Enable React Compiler memo dependency validation so `react/memo-dependencies` reports missing and extra values. Remove `react/gating` until Oxlint exposes compiler gating options.

Validated with `just ready`.

AI-assisted.
2026-08-18 16:16:24 +08:00
ch3rry aa49d86046 fix(linter): allow spread rule options in config types (#25675)
## Summary

- represent variadic rule options as a severity followed by zero or more
option values
- regenerate the Oxlint configuration schema and TypeScript declarations
- add a type-level regression for mapped options spread into
`no-restricted-globals`

## Root cause

The schema wrapper materialized the first `additionalItems` entry as a
required tuple element and set `minItems` to 2. A dynamic TypeScript
spread has type `T[]` and may be empty, so it cannot satisfy that
required position even though the severity-only form is already valid
through `RuleNoConfig`.

Keeping severity as the only fixed tuple item and leaving the rule
options in `additionalItems` generates `[severity, ...options]`, which
accepts both an empty spread and populated spreads without changing
runtime rule behavior.

Closes #25666


## AI assistance

Implemented with assistance from OpenAI Codex. The contributor remains
responsible for reviewing, understanding, and submitting the change
under the repository AI usage policy.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-17 14:11:07 +01:00
Boshen 892238149b refactor(linter): remove inactive react config rule (#25740)
Remove the inactive `react/config` rule and its generated metadata. Oxlint uses fixed, valid React Compiler options, so the rule cannot produce actionable diagnostics.

AI-assisted: Codex was used to implement and validate this change.
2026-08-16 12:39:27 +00:00
Boshen 8c4552dfa6 feat(linter)!: split react/react-compiler into per-category rules (#25500)
Splits the experimental `react/react-compiler` rule into 24 category-specific rules matching `eslint-plugin-react-hooks` v7.

- Runs React Compiler once per file and routes structured diagnostics to each enabled rule.
- Removes `react/react-compiler` and `reportAllBailouts`, with rules categorized by user-facing lint intent.
- Adds per-rule documentation and deduplicates shared React lint URLs.
- Preserves standardized compiler diagnostics while reporting each finding under its Oxlint rule name.

Breaking change: configurations using `react/react-compiler` must migrate to the category-specific rules.

Written with Claude Code and Codex.
2026-08-15 14:56:58 +00:00
camc314 beb724dce2 fix(linter/eslint/no-unused-vars): report bare underscore parameters (#25663)
## Summary

- report a bare underscore parameter when no args ignore pattern is configured
- preserve the optimized underscore-prefix behavior for explicit argsIgnorePattern configuration
- update focused rule coverage and generated documentation

Closes #25626
2026-08-14 13:16:16 +00:00
Mikhail Baev 285820eed6 fix(linter/no-large-snapshots): precompile and document allowed snapshot matchers (#25611)
issue #23594

- Move regex compilation to configuration parsing to avoid recompiling
patterns for every snapshot entry
- Document the matching behavior of allowedSnapshots (first interpret as
regex, if not valid match as string)
- Fix a small typo where both example sections were labeled “incorrect"
- Replace manual config parsing with DefaultRuleConfig
2026-08-14 10:47:51 +01:00
Boshen 4df5835fc3 fix(linter): allow capitalized built-in calls (#25516)
Fixes #24405.

The React Compiler global registry omitted `BigInt` and `Symbol`, causing `CapitalizedCalls` false positives. Register both primitives and expose the upstream-compatible `environment.validateNoCapitalizedCalls` option.

Validated with `just ready`.

AI-assisted: Codex was used to investigate and implement this change.
2026-08-12 03:51:52 +00:00
Mikhail Baev ccb8fe89db feat(linter/jsdoc): implement no-blank-blocks rule (#25207)
this PR implements `jsdoc/no-blank-blocks` rule, issue #1170
2026-08-05 22:38:24 +01:00
Mikhail Baev 9573937df3 fix(linter/typescript): validate ban-ts-comment description_format (#25320)
adds validation for the `descriptionFormat` regex option from #23594 and
replaces manual config parsing with `DefaultRuleConfig`
2026-08-05 20:21:36 +01:00
Cole Ellison d4a897ce22 feat(linter/eslint): implement one-var rule (#24470)
## Summary

Adds a native Oxlint implementation of [ESLint's `one-var`
rule](https://eslint.org/docs/latest/rules/one-var). This implementation
is a port of the [eslint rule
source](https://github.com/eslint/eslint/blob/main/lib/rules/one-var.js),
test suite, and autofix logic.

Related #479

## AI Disclosure

GPT 5.6 Sol was used to assist with implementation of this rule.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-05 15:10:29 +01:00
Cole Ellison 5ab9340637 feat(linter/jsx-a11y/anchor-has-content): add options to match eslint (#24571)
## Description

Eslint supports [a `components`
option](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/anchor-has-content.md)
for `jsx-a11y/anchor-has-content` that specified additional components
to treat as anchor elements. This adds equivalent support for that
option.

Note: I am not certain if this is something that should instead be read
off of
[`settings.jsx-a11y.components`](https://oxc.rs/docs/guide/usage/linter/config-file-reference.html#settings-jsx-a11y-components),
as that could list `{ MyAnchor: 'a' }`. Doing that would enable implicit
application of rules to custom components based on rendered entity, but
that may be the wrong use case, as the custom component definition
itself could be responsible for rendering required children.

## AI disclosure

I used GPT 5.6 Sol to assist in implementation of this fix. I've
reviewed all generated code and test coverage.

---------

Signed-off-by: Cameron <cameron.clark@hey.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-05 11:57:23 +01:00
camc314 9d4592c72f fix(linter): reject duplicate JS plugin names (#25243)
## Summary
- reject JS plugins whose normalized names collide
- keep registered plugin names isolated per LSP workspace
- add a CLI regression fixture covering two plugins that expose the same rule name

Fixes #25164
2026-08-03 09:40:27 +00:00
Mikhail Baev 5c0fa61ddb fix(linter/eslint/no-warning-comments): unify config structs and remove manual options docs (#25151)
this PR unifies 2 config structs for `eslint/no-warning-comments` and
removes the manually written options doc, related issue: #14743.

Doc after fix:

<img width="919" height="1295" alt="image"
src="https://github.com/user-attachments/assets/dab8f999-fffa-4a77-8d6d-39746cfa3860"
/>
2026-08-01 19:26:30 +01:00
camc314 9dc7756729 docs(linter/typescript/no-unnecessary-condition): clarify options (#25110)
## Summary

- document the exact allowConstantLoopConditions behavior, including the four directly allowed literals
- explain how always differs from only-allowed-literals
- add a checkTypePredicates example and regenerate the published configuration schema

Closes #25098
2026-07-30 10:29:51 +00:00
Boshen 3ff2e0e6fa docs(linter): clarify config extends types (#24936)
The generated config reference only described the JSON schema's `string[]` form. Clarify that `oxlint.config.ts` accepts imported `OxlintConfig[]`, add an example and public JSDoc, and regenerate the derived artifacts.

Closes #20238.

Validated with the website generator suite, targeted TypeScript checks, and the relevant Oxlint tests. The full `just ready` run reached an unrelated parallel suppression-fixture cleanup race; the failing test passes in isolation.

AI-assisted.
2026-07-27 01:51:16 +00:00
vigneshwar 8d31dfa393 feat(linter): verify eslint/no-restricted-globals config schema (#24598)
Part of #22955. Follow-up to the resolved #23617.

## What

`eslint/no-restricted-globals` stayed in `NO_VERIFIED_VALID_SCHEMA`
after #23617 was resolved, because the derived schema described the
internal `NoRestrictedGlobalsConfig` struct (a `globals` hash map)
rather than the user-facing positional-array format the rule actually
parses.

This PR adds a hand-written `JsonSchema` following the existing
`no-restricted-imports` pattern, describing the three accepted
positional item forms:

1. `"event"` — a global name string
2. `{ "name": "event", "message": "…" }` — a name/message object
3. `{ "globals": [ … ], "checkGlobalObject": true, "globalObjects": [ …
] }` — the object form added in #23617

Generated TS declaration:

```ts
"no-restricted-globals"?:
  RuleNoConfig | [AllowWarnDeny, NoRestrictedGlobalsConfigEnum, ...NoRestrictedGlobalsConfigEnum[]];
export type NoRestrictedGlobalsConfigEnum = string | RestrictedGlobal | NoRestrictedGlobalsObjectConfig;
```

Verified against the #22955 checklist: reflects all accepted user
configuration forms, denies unknown fields on object forms, and produces
no `[k: string]: unknown` in the TS declaration. `from_configuration`
and rule behavior are unchanged; rule tests pass.

Note: this branch removes only the `no-restricted-globals` entry from
`NO_VERIFIED_VALID_SCHEMA`; #24586 (separate PR) removes the
`filename-case` entry, so whichever merges second will have a trivial
conflict in that array.

## Disclosure

This contribution was developed with assistance from Claude Code
(Anthropic); I have reviewed and tested all changes.

---------

Signed-off-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-26 16:55:55 +02:00
Bartok 7069621199 feat(linter): verify jest/vitest prefer-lowercase-title config schema (#24724)
## Summary

- Unskip `jest/prefer-lowercase-title` and
`vitest/prefer-lowercase-title` from `NO_VERIFIED_VALID_SCHEMA`.
- PreferLowercaseTitleConfig already derives `Deserialize` +
`JsonSchema` with `deny_unknown_fields` and docs for all public options,
so the generated schema/types can describe the real config.
- Regenerates `npm/oxlint/configuration_schema.json` and
`apps/oxlint/src-js/package/config.generated.ts`.

## Motivation

Part of #22955. These two plugin names shared a clean config struct
already used at runtime; they were still emit-as-`DummyRule` only
because of the broader #23186 split note (mainly about `valid-title`
option divergence). Leaving `valid-title` skipped.

Generated config now exposes:

- `allowedPrefixes: string[]` (default `[]`)
- `ignore: string[]` (default `[]`)
- `ignoreTopLevelDescribe: boolean` (default `false`)
- `lowercaseFirstCharacterOnly: boolean` (default `true`)
- `additionalProperties: false` / no `[k: string]: unknown`

## Verification

- `cargo test -p website_linter` — 8 passed
- `cargo test -p oxc_linter --features ruledocs
test_rules_with_custom_configuration_have_schema` — passed
- `cargo test -p oxc_linter prefer_lowercase_title --lib` — 2 passed
(jest + vitest)
- Inspected generated schema/TS: not DummyRule; no index signature

## AI disclosure

Assisted by AI (Hermes/Sera). I reviewed the existing
PreferLowercaseTitleConfig against the GFI checklist, regenerated
schema/types locally, and ran the tests above.

---
**Agent-Owner:** `sera` · **Platform:** hermes · **Claim:** `sera`

---
<!-- fleet-pr-claim: agent_id=sera platform=hermes -->
**Agent-Owner:** `sera` · **Platform:** hermes · **Claim-TTL:** 24h

---------

Co-authored-by: Bartok9 <259807879+Bartok9@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-26 10:30:37 +08:00
camc314 016cf2acd6 feat(linter/oxc): add bad-match-all-arg rule (#24900)
## Summary

- add oxc/bad-match-all-arg for non-global regular expressions passed to matchAll
- share cycle-safe RegExp flag resolution with bad-replace-all-arg
- support callable and global-qualified RegExp constructors
- update generated metadata, diagnostics, timings, and CLI rule-count snapshots

Closes #24823.
2026-07-24 14:48:45 +00:00
Mikhail Baev cdc941e5f8 feat(linter/n): implement exports-style rule (#24087)
this PR implements `n/exports-style` rule. Issue #493

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-22 16:50:23 +01:00
周星星同学 9213560fe7 fix(config): preserve defineConfig field JSDoc (#24326)
## Summary

- contextually type oxlint and oxfmt `defineConfig` object arguments as
their config interfaces
- keep the identity-helper return type so literal inference is preserved
- restore field-level JSDoc hover for config object properties in
editors

## Validation

Manual expansion of `just ready` because `just` is not installed in my
local shell:

- `pnpm install`
- `typos`
- `cargo lintgen`
- `cargo shear --fix --check-test-targets` (returned 0; emitted an
unrelated existing redundant-ignore warning for `oxc_lexer` in workspace
metadata)
- `cargo fmt`
- `node --run fmt`
- `cargo ck`
- `env -u NO_COLOR cargo test --all-features`
- `cargo lint -- --deny warnings`
- `RUSTDOCFLAGS='-D warnings' cargo doc --no-deps
--document-private-items --all-features`
- `cargo run -p oxc_ast_tools`

TypeScript language-service probe using VS Code's bundled TypeScript
SDK:

- old `defineConfig<T extends Config>(config: T): T` returned no docs
for object fields
- new `defineConfig<T extends Config>(config: T & Config): T` returned
JSDoc for `oxlint.ignorePatterns` and `oxfmt.semi`
- invalid property/type probes still reported TS2561 and TS2322
- return literal inference stayed unchanged for representative
oxlint/oxfmt config objects

## AI Assistance

This PR was prepared with AI assistance. I reviewed the change,
validation approach, and PR contents before submission.

Co-authored-by: cixiangtao <cixiangtao@kanyun.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-22 16:41:41 +01:00
Mikhail Baev 1ad6f6c823 feat(linter/eslint): implement id-denylist rule (#24632)
this PR implements `eslint/id-denylist`, issue #479
2026-07-22 16:30:20 +01:00
Connor Shea dd18383ee1 feat(linter/node): implement no-top-level-await rule (#24634)
This implements
[`no-top-level-await`](https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-top-level-await.md)
from the Node ESLint plugin (#493).

AI Disclosure: Generated with Claude Code. Reviewed and tested by me.

I have an alternative implementation using a Program visitor but it made
no difference performance-wise on vscode or in benchmarking outside
extreme cases, so I don't think it's really worth the trouble vs the
simpler implementation here. It's still in the commit history if that
implementation is preferred.

There is one notable difference between this and the original
implementation, which is that the `convertPath` option is not
implemented, and the checking of `package.json`/`.npmignore` is not
implemented (it was used for checking if the given module was actually
exposed in the library) as there's no way to check against those in
oxlint. There's an argument to be made that this makes the rule not
worth implementing, and I'm open to that argument if we'd prefer to mark
this rule as unsupported instead.

All tests were ported from the original rule (excluding those reliant on
the mentioned config options/checks that were skipped). I've also had
Claude add a few additional test cases (see commit
40418f7e63) on top to cover behavior that
wasn't tested previously. I have confirmed that all of these tests are
identical to the behavior of the upstream rule, but I can remove them if
we don't want to have any divergence from the upstream test suite.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 14:10:52 +01:00
camc314 8694167be7 fix(linter/eslint/prefer-destructuring): handle typed declarations (#24616)
## Summary

- skip prefer-destructuring diagnostics for variable declarations with type annotations by default
- add enforceForDeclarationWithTypeAnnotation for typescript-eslint compatibility
- report without an autofix when annotated declarations are explicitly enforced, preserving the declared type
- cover object, computed-property, array, renamed-property, and reporter configuration cases

This matches the current `@typescript-eslint/prefer-`destructuring behavior.

Fixes #24615.
2026-07-17 14:32:23 +00:00
Cole Ellison 16a65f269c feat(linter/react): implement function-component-definition rule (#24471)
## Summary

Adds a native Oxlint implementation of the [`eslint-plugin-react`
`function-component-definition`
rule](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md).
This implementation is a port of the [rule
source](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/lib/rules/function-component-definition.js),
test suite, and autofix logic.

Related #1022

## AI Disclosure

GPT 5.6 Sol was used to assist with implementation of this rule.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-14 18:34:00 +01:00
Mikhail Baev 7f1f585b86 feat(linter): reuse jest/padding-around-test-blocks for vitest/padding-around-test-blocks (#24519)
this PR moves `jest/padding-around-test-blocks` to the shared
jest_vitest rules, so it can be reused by both the jest and vitest
rules.

issue #4656

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-14 18:22:11 +01:00
camc314 99978a8bbb feat(linter/import/consistent-type-specifier-style): support prefer-top-level-if-only-type-imports option (#24502)
## Summary

- Re-port upstream support for prefer-top-level-if-only-type-imports.
- Allow mixed value/type imports while requiring top-level syntax for imports containing only types.
- Preserve Oxlint's existing default and declaration-file behavior.
- Regenerate the JSON schema and TypeScript configuration types.

## Reference

https://github.com/oxc-project/oxc/issues/1117#issuecomment-4966827537
2026-07-14 09:25:16 +00:00
connorshea 7f80cac4fd perf(linter/vue/prop-name-casing): precompile ignoreProps regex pattern (#24413)
`is_ignored` in `vue/prop-name-casing` recompiled each slash-wrapped `ignoreProps` pattern with `Regex::new` for every prop it checked. This compiles the patterns once in `from_configuration` into an `Exact`/`Pattern(Regex)` matcher enum stored on the options (`serde`/`schemars`-skipped field), and matches against that.

Invalid regex patterns are dropped at compile time, which preserves the previous behavior (they could never match before either, and were not compared as literals).

### Benchmark

Interleaved paired-sample benchmark (N=40, alternating order, `--silent`), release binaries built from this branch and its merge-base.

Fixture: 220 Vue SFCs / 35,200 props / 36.5K lines, single-rule oxlintrc with `ignoreProps: ["ignored_prop", "/^legacy/", "/_deprecated$/", "/^(alpha|beta)_/", "/[/"]` (one exact pattern, three regexes, one invalid regex).

| | baseline | this branch |
|---|---|---|
| rule on | 66.87 ms | 16.69 ms |
| parse only | 8.47 ms | 8.41 ms |

Paired Δ of **+50.17 ms** (sd 2.18, t=146, faster in 40/40 pairs). The parse-only differential is null (+0.06 ms, t=0.2), so the saving is attributable to the rule and not to binary layout.

That works out to 4.0× on this fixture, but the multiplier is fixture-dependent — the work removed scales with `regex_pattern_count × prop_count`, so denser configs show a larger ratio. The ~50 ms saved across 35K props is the more transferable number.

### Correctness

Verified with `--format=json` (**without** `--silent`, which empties the JSON reporter's `diagnostics` array): both binaries emit the same 10,560 diagnostics, identical after sorting — the array order varies between runs because files are linted in parallel. The fixture includes canary props that are only ignored via the regex patterns, plus an invalid regex; the ignore semantics are unchanged.

### Disclosure

This change was implemented and benchmarked with AI assistance (Claude Code), and has been reviewed by the submitter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-13 09:42:13 +00:00
connorshea 33805b9691 perf(linter/jsdoc/require-param): compile checkTypesPattern regex once (#24420)
AI Disclosure: Generated with Claude Code, reviewed and tested by me. I don't think there's a particularly good reason to use a RwLock like this?

This can be split into separate PRs if preferred, as it also adds the type for this rule to the generated definitions and JSON Schema.

The rule kept compiled `checkTypesPattern` regexes in a global `OnceLock<RwLock<FxHashMap<String, Regex>>>`. Every `run()` on a JSDoc-documented function:

- cloned the pattern `String` to use as the map key,
- took the RwLock **write** lock even on cache hits, serializing all linter threads through a single lock, and
- held the guard across the entire parameter check.

The pattern is fixed at configuration time, so the cache is unnecessary: this PR deserializes the option directly into a `Regex` field on the config (same approach as #24412 / #24417) and deletes the cache entirely.

## Benchmark

Paired interleaved samples (N=40), release builds, fixture of 64 files × 400 fully-documented JSDoc functions (25,600 `run()` calls, all hitting the regex path, zero violations) with only `jsdoc/require-param` enabled:

| Run | Baseline (8de6fca) | This PR | Result |
|---|---|---|---|
| Rule enabled | 56.95 ms | 18.25 ms | **3.12×**, t=132.8, 40/0 wins |
| Parse-only null control (same fixture) | 11.05 ms | 10.75 ms | 1.03×, t=1.5 — noise |

Subtracting the ~11 ms parse floor, rule execution drops from ~46 ms to ~7 ms (~6.4×). The win is mostly the removed cross-thread lock contention, so it scales with file count on multi-core machines.

## Correctness

- Diagnostics are byte-identical between baseline and this PR on a mixed pass/fail canary, under both the default config and a custom `checkTypesPattern` config (which changes reporting, confirming the option deserializes and takes effect).
- `oxc_linter` lib tests (1,169), `oxlint` tests (396), and clippy pass; the generated website rule-doc page is byte-identical (`schemars(with = "String", default)` preserves the documented default).

## Invalid patterns are now a config error, not a panic

An invalid `checkTypesPattern` previously panicked lazily, on the first checked function. It now fails config loading with a proper diagnostic:

```
Failed to parse oxlint configuration file.

  x Invalid configuration for rule `jsdoc/require-param`:
  |   regex parse error:
  |     ^(unclosed
  |      ^
  | error: unclosed group
```

To get there, two things changed:

- The regex deserializer lives in `utils/config.rs` alongside the existing `deserialize_regex_option` / `deserialize_regex_vec` / `deserialize_required_regex_option` family, and builds via `RegexBuilder` with `D::Error::custom` like they all do.
- `from_configuration` propagates the serde error instead of dropping it with `.ok()`. The linter already has the plumbing for this — `config/rules.rs` turns an `Err` into `OverrideRulesError::RuleConfiguration` — the `.ok()` was just discarding it.

### Behavior change worth flagging

Now that `from_configuration` no longer swallows errors, this config's `deny_unknown_fields` is load-bearing for the first time. A config carrying an `eslint-plugin-jsdoc` option that oxc doesn't implement (e.g. `unnamedRootBase`) previously fell back to defaults silently; it now fails to load with an "unknown field" error. No lint *results* change, but a user porting an eslint-plugin-jsdoc config that oxc previously tolerated will now see a config error.

That surfaced in the ported test suite: eight cases configure `unnamedRootBase` (×5), `enableFixer` (×2), `enableRootFixer`, and `autoIncrementBase`, none of which this rule implements. They're commented out, and the snapshot is regenerated accordingly.

If maintainers would rather keep the lenient behavior, the alternative is to validate `checkTypesPattern` up front and keep the `.ok()` fallback for everything else — that removes the panic without touching any test or changing config tolerance. Happy to switch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-13 09:27:37 +00:00
Boshen 0433a8376a feat(linter/eslint/no-inner-declarations): add namespaces option (#24044)
Adds a `namespaces` option to `eslint/no-inner-declarations`:

```json
["error", "both", { "namespaces": "allow" }]
```

With `namespaces: "allow"`, `function`/`var` declarations placed directly inside a TypeScript `namespace`/`module` body are no longer reported. Declarations nested inside blocks within a namespace (e.g. `namespace N { if (x) { function f() {} } }`) are still reported. The default (`disallow`) is unchanged.

Closes #21143
2026-07-13 01:59:31 +00:00
leaysgur 83378351e4 fix(linter): error on ignorePatterns that cannot match files aoutside the config directory (#24341)
Follow up on #24339

- Added the same guard as Oxfmt
- Since they are identical, I moved them into `oxc_config` so they can be shared
2026-07-10 09:05:48 +00:00
leaysgur 2ce5a33ecc fix(linter): resolve ignorePatterns relative to the config dir (#24339)
Fixes #24310

Root config's `ignorePatterns` are now resolved relative to the directory containing the config file, instead of CWD.

Also fixes a latent issue: a `--config <path>` containing `..` silently disabled all `ignorePatterns` (the unnormalized parent dir never prefix-matches lint target paths). Explicit config paths are now lexically normalized, same as Oxfmt.

### Behavior change

The new anchoring applies in all cases, including `--config` / LSP `configPath`. This intentionally differs from ESLint, which resolves alternate-config ignore patterns relative to CWD:

- `extends`, `overrides[].files`, and JS plugin specifiers are already config-file-relative, including via `--config`
  - rooting only `ignorePatterns` at CWD would give one file two coordinate systems
- Wrappers like Vite+ pass `--config <workspace-root config>` as an implementation detail while CWD stays at the invocation directory, so "`--config` means CWD-relative" does not hold in practice
  - #24276

Impact should be small: bare names (`dist`, `*.min.js`) and `**/`-prefixed patterns are unaffected by the anchor.

The updated `config_ignore_patterns/with_oxlintrc` snapshot shows the `--config` case.
2026-07-10 08:39:56 +00:00
leaysgur b732abd8dd chore(oxfmt): update prettier to 3.9.4 (#24201)
Update to the latest before our release.
2026-07-06 02:00:31 +00:00
Mikhail Baev a2c97f348c feat(linter/unicorn): implement explicit-timer-delay rule (#23612)
this PR implements `unicorn/explicit-timer-delay`, issue #684

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-03 16:08:33 +01:00
camc314 bdb51c73da fix(linter/jest/prefer-ending-with-an-expect): validate config patterns (#24122)
## Summary

- deserialize rule options through `DefaultRuleConfig`
- convert and validate configured assertion function patterns during deserialization
- propagate invalid regex configuration errors instead of panicking at lint runtime

Closes [oxc-project/oxc#23644](https://github.com/oxc-project/oxc/pull/23644)
2026-07-03 14:31:16 +00:00
Shekhu☺️ 85735cb5df feat(linter/unicorn): implement no-confusing-array-with rule (#23638)
Implements unicorn/no-confusing-array-with, which flags two ways
Array#with() calls can silently misbehave:

A literal negative index (array.with(-1, value)). Unlike
slice()/splice(), with() treats a negative index as an offset from the
end of the array, which is easy to assume incorrectly.
.length used as the index (array.with(array.length, value)), which is
always out of bounds and always produces a RangeError / unintended
result, since valid indices run 0 .. length - 1.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-03 15:06:08 +01:00
Todor Andonov cb4fbb927f feat(linter/eslint): implement no-unreachable-loop rule (#23975)
## Summary

- add native `eslint/no-unreachable-loop` support
- support the ESLint `ignore` option for loop statement types
- reuse `no-unreachable`'s effective CFG reachability helper
(`effective_unreachable_blocks`)
- generate oxlint config schema/types and rule metadata

## Why

`no-unreachable-loop` is currently missing from Oxlint's ESLint rule
coverage. The rule catches loops whose body cannot reach a second
iteration, while preserving ESLint-compatible behavior for unreachable
loops and configured ignored loop types.

## Performance

The effective-reachability helper is a whole-CFG traversal. It is only
needed to recognize a loop that is dead code *after* an infinite loop;
the next-iteration search prunes infinite loops on its own. So the
analysis runs on the CFG's base reachability first and builds the
corrected map only when a loop would otherwise be reported *and* is a
static infinite loop — a rare path the common case never hits. This
keeps the rule self-contained and brings the `linter[binder.ts]` and
`linter[kitchen-sink.tsx]` benches from a ~4-5% regression down to
noise.

## AI Assistance

This PR was implemented with AI assistance.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-02 21:07:07 +01:00
camc314 dc321127fa feat(linter/eslint/no-constant-binary-expression): check relational comparisons (#24088)
## Summary

- add `checkRelationalComparisons` support to `no-constant-binary-expression`
- default the Oxc option to `true` and allow explicit opt-out with `false`
- port the ESLint relational comparison test cases into the existing rule fixture
2026-07-02 19:33:13 +00:00
Boshen d963967079 feat(linter/unicorn/no-array-sort): add allowAfterSpread option (#24043)
Adds an `allowAfterSpread` option (default `false`) to `unicorn/no-array-sort`. When enabled, sorting a freshly-spread array (`[...iterable].sort()`) is allowed — it doesn't mutate an existing array and avoids the extra allocation `toSorted()` would incur when sorting a non-array iterable such as a `Set`.

`array.sort()` is still reported (not a spread), and `[...array].sort()` is still reported when the option is off.

Closes #20544
2026-07-02 07:19:18 +00:00
Boshen 45d607d485 fix(linter/react/forbid-component-props): make allow/disallow lists optional in schema (#24024)
`ForbidItemObject` derives `JsonSchema`, but its manual `Deserialize` impl already defaults the four allow/disallow `Vec` fields. Without `#[serde(default)]`, schemars marked them as `required` in the generated configuration schema, so editors/tooling wrongly required all four (`allowedFor`, `allowedForPatterns`, `disallowedFor`, `disallowedForPatterns`) whenever the object form of `react/forbid-component-props` was used.

Add `#[serde(default)]` to the four fields and regenerate the schema — the `required` array is dropped and each field gets `"default": []`.

Closes #23732
2026-07-02 01:25:23 +00:00
Mikhail Baev 743e22293b feat(linter/react): add disallowedValues option for forbid-dom-props rule (#23970)
fixes #23049. Tests regenerated from upstream
2026-06-30 09:06:52 +01:00
camc314 742be3616f fix(refactor/node/handle-callback-err): reject invalid regex config (#23740)
Reject invalid caret-prefixed `node/handle-callback-err` patterns during configuration parsing instead of falling back to literal string matching.

`^`-prefixed options are documented as regex patterns, so malformed regex input should surface as a config error.

Part of #23594
2026-06-23 11:09:29 +00:00
Sysix 1c8f50c67f feat(linter): add schema for eslint/no-restricted-import (#23642) 2026-06-23 08:27:16 +00:00
Sysix b1b83d5b9f refactor(linter): remove second | undefined from DummyRuleMap ts generation (#23684) 2026-06-21 13:54:06 +00:00
Sysix 0dc2405411 feat(linter): add schema for eslint/no-restricted-properties (#23619) 2026-06-20 20:38:31 +00:00
Sysix b638d0ee1d feat(linter): add schema for node/callback-return (#23615)
- Avoided looping over `array` of `array`, we only want to know the first level of structure for detecting a tuple config
- refactored some code and introduced a `.clone()` at the beginning. Hope this is fine for the rule doc code path. Feeling sometimes stupid without AI quick fixes :')
- enabled `node-callback-return` schema, which is the only rule that accepts a array as a config
  - https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/callback-return.md
2026-06-20 20:38:31 +00:00
Sysix 6d355ab8b3 refactor(linter): remove number_as_object_schema helper (#23614)
The helper generated just `number`. With the `Enum` approach, the generator creates a `u32` with `minimum: 0.0` for the JSON schema.
2026-06-20 20:28:54 +00:00