mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
codex/fix-semantic-parameter-resolution
2019 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d5d575c1de |
chore(deps): update rust to v1.98.0 (#25945)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [rust](https://rust-lang.org/) ([source](https://redirect.github.com/rust-lang/rust), [changelog](https://redirect.github.com/rust-lang/rust/blob/main/RELEASES.md)) | toolchain | minor | `1.97.1` → `1.98.0` | --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zNS40IiwidXBkYXRlZEluVmVyIjoiNDQuMzUuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Cameron <cameron.clark@hey.com> |
||
|
|
1193c9dbaf |
chore(oxfmt): dogfood operator position at line start (#25937)
dogfood |
||
|
|
f7be7cc5d3 |
chore(deps): update dependency oxc-parser to ^0.146.0 (#25921)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [oxc-parser](https://oxc.rs/docs/guide/usage/parser) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/napi/parser)) | [`^0.145.0` → `^0.146.0`](https://renovatebot.com/diffs/npm/oxc-parser/0.145.0/0.146.0) |  |  |  |  | --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMy4yIiwidXBkYXRlZEluVmVyIjoiNDQuMzMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
2878ee943b |
chore(deps): update dependency @oxc-project/types to ^0.146.0 (#25915)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [@oxc-project/types](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxc-types)) | [`^0.145.0` → `^0.146.0`](https://renovatebot.com/diffs/npm/@oxc-project%2ftypes/0.145.0/0.146.0) |  |  |  |  | --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMy4yIiwidXBkYXRlZEluVmVyIjoiNDQuMzMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
82ebb48d68 |
chore(deps): update oxc to ^0.145.0 (#25878)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [@oxc-project/types](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxc-types)) | [`^0.144.0` → `^0.145.0`](https://renovatebot.com/diffs/npm/@oxc-project%2ftypes/0.144.0/0.145.0) |  |  |  |  | | [oxc-parser](https://oxc.rs/docs/guide/usage/parser) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/napi/parser)) | [`^0.144.0` → `^0.145.0`](https://renovatebot.com/diffs/npm/oxc-parser/0.144.0/0.145.0) |  |  |  |  | --- ### Release Notes <details> <summary>oxc-project/oxc (@​oxc-project/types)</summary> ### [`v0.145.0`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/npm/oxc-types/CHANGELOG.md#01450---2026-08-18) ##### 🐛 Bug Fixes - [`0c68b7f`](https://redirect.github.com/oxc-project/oxc/commit/0c68b7f) estree: Emit `decorators` on `FormalParameterRest` ([#​25582](https://redirect.github.com/oxc-project/oxc/issues/25582)) (camc314) </details> <details> <summary>oxc-project/oxc (oxc-parser)</summary> ### [`v0.145.0`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/napi/parser/CHANGELOG.md#01450---2026-08-18) ##### 🐛 Bug Fixes - [`db44651`](https://redirect.github.com/oxc-project/oxc/commit/db44651) napi: Disable reuseWorker in browser bindings ([#​25640](https://redirect.github.com/oxc-project/oxc/issues/25640)) (leaysgur) - [`0c68b7f`](https://redirect.github.com/oxc-project/oxc/commit/0c68b7f) estree: Emit `decorators` on `FormalParameterRest` ([#​25582](https://redirect.github.com/oxc-project/oxc/issues/25582)) (camc314) </details> --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMi42IiwidXBkYXRlZEluVmVyIjoiNDQuMzIuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
0db127cc16 |
release(apps): oxlint v1.79.0 && oxfmt v0.64.0 (#25866)
# Oxlint ### 💥 BREAKING CHANGES - |
||
|
|
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. |
||
|
|
c84ede371b |
perf(estree_tokens): share JS token update entry point (#25826)
Add a shared non-generic JS-style token update entry point so `oxc_linter` and `oxlint` do not each instantiate the ESTree token visitor. On `aarch64-apple-darwin`, `cargo build -p oxlint --release --features allocator` reduces the `oxlint` binary by 49,616 bytes (48.5 KiB, 0.39%), from 12,756,960 to 12,707,344 bytes. Validated with `just ready`. AI assistance was used for implementation and measurement. |
||
|
|
f0121edb71 |
perf(linter): share config deserialization entry point (#25820)
Share a non-generic JSON deserialization entry point across `oxc_linter` and `oxlint`, avoiding duplicate monomorphizations. Also deserialize well-known settings without deep-cloning the raw JSON value. Validated with `just ready`. AI assistance was used for implementation and measurement. |
||
|
|
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> |
||
|
|
9ed10b728d |
perf(linter): use unstable sorts for unique keys (#25778)
Switches order-independent sorts to unstable sorting and avoids cloning rule-table plugin names. Reduces the stripped `oxlint` release binary from 12,773,568 to 12,757,040 bytes: 16,528 bytes (0.13%). Validated with `cargo test -p oxc_linter` and focused oxlint JSON checks. AI assistance was used for analysis and implementation. |
||
|
|
efebf4c824 |
chore(deps): update npm packages (#25753)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [@napi-rs/wasm-runtime](https://napi.rs/) ([source](https://redirect.github.com/napi-rs/napi-rs/tree/HEAD/wasm-runtime)) | [`1.2.2` → `1.2.3`](https://renovatebot.com/diffs/npm/@napi-rs%2fwasm-runtime/1.2.2/1.2.3) |  |  |  |  | | [@typescript-eslint/parser](https://typescript-eslint.io/packages/parser) ([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)) | [`8.66.0` → `8.67.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.66.0/8.67.0) |  |  |  |  | | [@typescript-eslint/scope-manager](https://typescript-eslint.io/packages/scope-manager) ([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/scope-manager)) | [`8.66.0` → `8.67.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fscope-manager/8.66.0/8.67.0) |  |  |  |  | | [@typescript-eslint/visitor-keys](https://typescript-eslint.io) ([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/visitor-keys)) | [`8.66.0` → `8.67.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fvisitor-keys/8.66.0/8.67.0) |  |  |  |  | | [degit](https://redirect.github.com/Rich-Harris/degit) | [`3.6.6` → `3.7.0`](https://renovatebot.com/diffs/npm/degit/3.6.6/3.7.0) |  |  |  |  | | [eslint](https://eslint.org) ([source](https://redirect.github.com/eslint/eslint)) | [`10.8.0` → `10.8.1`](https://renovatebot.com/diffs/npm/eslint/10.8.0/10.8.1) |  |  |  |  | | [serialize-javascript](https://redirect.github.com/yahoo/serialize-javascript) | [`7.0.7` → `7.1.0`](https://renovatebot.com/diffs/npm/serialize-javascript/7.0.7/7.1.0) |  |  |  |  | | [svelte](https://svelte.dev) ([source](https://redirect.github.com/sveltejs/svelte/tree/HEAD/packages/svelte)) | [`5.56.8` → `5.56.9`](https://renovatebot.com/diffs/npm/svelte/5.56.8/5.56.9) |  |  |  |  | | [tsx](https://tsx.hirok.io) ([source](https://redirect.github.com/privatenumber/tsx)) | [`4.23.9` → `4.23.12`](https://renovatebot.com/diffs/npm/tsx/4.23.9/4.23.12) |  |  |  |  | --- ### Release Notes <details> <summary>napi-rs/napi-rs (@​napi-rs/wasm-runtime)</summary> ### [`v1.2.3`](https://redirect.github.com/napi-rs/napi-rs/blob/HEAD/wasm-runtime/CHANGELOG.md#123-2026-08-12) [Compare Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/wasm-runtime@1.2.2...@napi-rs/wasm-runtime@1.2.3) ##### Bug Fixes - **cli:** compatible with emnapi v1 & v2 ([#​3454](https://redirect.github.com/napi-rs/napi-rs/issues/3454)) ([aeba312](https://redirect.github.com/napi-rs/napi-rs/commit/aeba31217201e96435848fd17055478ff7cf8b98)) - **deps:** update emnapi to v2.0.0-alpha.4 ([#​3451](https://redirect.github.com/napi-rs/napi-rs/issues/3451)) ([b8ba732](https://redirect.github.com/napi-rs/napi-rs/commit/b8ba732c4611a54dde09dfe3da750f50726b51d9)) </details> <details> <summary>typescript-eslint/typescript-eslint (@​typescript-eslint/parser)</summary> ### [`v8.67.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8670-2026-08-10) [Compare Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.66.0...v8.67.0) This was a version bump only for parser to align it with other projects, there were no code changes. See [GitHub Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.67.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>typescript-eslint/typescript-eslint (@​typescript-eslint/scope-manager)</summary> ### [`v8.67.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/scope-manager/CHANGELOG.md#8670-2026-08-10) [Compare Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.66.0...v8.67.0) This was a version bump only for scope-manager to align it with other projects, there were no code changes. See [GitHub Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.67.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>typescript-eslint/typescript-eslint (@​typescript-eslint/visitor-keys)</summary> ### [`v8.67.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/visitor-keys/CHANGELOG.md#8670-2026-08-10) [Compare Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.66.0...v8.67.0) This was a version bump only for visitor-keys to align it with other projects, there were no code changes. See [GitHub Releases](https://redirect.github.com/typescript-eslint/typescript-eslint/releases/tag/v8.67.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. </details> <details> <summary>Rich-Harris/degit (degit)</summary> ### [`v3.7.0`](https://redirect.github.com/Rich-Harris/degit/compare/v3.6.6...v3.7.0) [Compare Source](https://redirect.github.com/Rich-Harris/degit/compare/v3.6.6...v3.7.0) </details> <details> <summary>eslint/eslint (eslint)</summary> ### [`v10.8.1`](https://redirect.github.com/eslint/eslint/releases/tag/v10.8.1) [Compare Source](https://redirect.github.com/eslint/eslint/compare/v10.8.0...v10.8.1) #### Bug Fixes - [`18eb0a7`](https://redirect.github.com/eslint/eslint/commit/18eb0a7e787b9fac3049ef3dad0e845d2bd940a4) fix: prevent ASI hazard in `no-unused-labels` autofix ([#​21173](https://redirect.github.com/eslint/eslint/issues/21173)) (dongkyu lee) - [`151ba3f`](https://redirect.github.com/eslint/eslint/commit/151ba3f5834a0909e8b9b1736f4889ac694c0104) fix: false positives in `getter-return` and `accessor-pairs` ([#​21163](https://redirect.github.com/eslint/eslint/issues/21163)) (Grit) - [`6898df9`](https://redirect.github.com/eslint/eslint/commit/6898df9364639ee64b9448a4cb6b08a30c16bd37) fix: ignore meta-property names in `id-denylist` ([#​21166](https://redirect.github.com/eslint/eslint/issues/21166)) (Pixel) - [`4d7db66`](https://redirect.github.com/eslint/eslint/commit/4d7db6628e2badf0857cb88734fe641c3874bce9) fix: ignore meta-property names in `id-match` ([#​21167](https://redirect.github.com/eslint/eslint/issues/21167)) (Pixel) - [`677214e`](https://redirect.github.com/eslint/eslint/commit/677214e7eea83d8bc6e4b79eea871577e1369d5f) fix: handle ASI hazards in no-unused-vars removeVar suggestion ([#​20935](https://redirect.github.com/eslint/eslint/issues/20935)) (kuldeep kumar) #### Documentation - [`7d0cbf8`](https://redirect.github.com/eslint/eslint/commit/7d0cbf81cfdb7526b5c4cb7b222ddc7f257db560) docs: Update README (GitHub Actions Bot) - [`0a05812`](https://redirect.github.com/eslint/eslint/commit/0a05812adb12598b32e85297b98df5ad14501d60) docs: add missing backticks to `no-duplicate-imports.js` ([#​21183](https://redirect.github.com/eslint/eslint/issues/21183)) (Lee Daeun) - [`678c90b`](https://redirect.github.com/eslint/eslint/commit/678c90b55da2889d4400cbf6e2584ab683faf202) docs: Update README (GitHub Actions Bot) - [`8a10424`](https://redirect.github.com/eslint/eslint/commit/8a104242e8e1c5614940fab7324346974cff7d26) docs: Update README (GitHub Actions Bot) - [`69bb948`](https://redirect.github.com/eslint/eslint/commit/69bb948061105426dbe6e3c931fcda783286e020) docs: Update README (GitHub Actions Bot) #### Chores - [`0a14800`](https://redirect.github.com/eslint/eslint/commit/0a148005051fded2ef1d14cc228ae505251b4b10) chore: update github/codeql-action action to v4.37.4 ([#​21196](https://redirect.github.com/eslint/eslint/issues/21196)) (renovate\[bot]) - [`05adcb1`](https://redirect.github.com/eslint/eslint/commit/05adcb13542061dc7fadde5cd58d23d405a96d93) test: fix failing ecosystem test for `eslint-plugin-unicorn` ([#​21191](https://redirect.github.com/eslint/eslint/issues/21191)) (Lazizbek Ergashev) - [`5611035`](https://redirect.github.com/eslint/eslint/commit/56110356652dd614b3cf0933538abb551fc6bd6f) test: add error locations info to `no-void` ([#​21185](https://redirect.github.com/eslint/eslint/issues/21185)) (Lee Daeun) - [`ee47333`](https://redirect.github.com/eslint/eslint/commit/ee47333aa681cfc3cb54df08c38f211ea219cc2a) ci: bump github/codeql-action from 4 to 4.37.3 ([#​21176](https://redirect.github.com/eslint/eslint/issues/21176)) (dependabot\[bot]) - [`f131c03`](https://redirect.github.com/eslint/eslint/commit/f131c034ad91bbf06bcbb6b5e931447a8e419a46) chore: improve ecosystem test failure reporting ([#​20937](https://redirect.github.com/eslint/eslint/issues/20937)) (crimsonjay0) - [`1f6edde`](https://redirect.github.com/eslint/eslint/commit/1f6eddee609b369b50993eab08d437dda4700991) chore: update ecosystem plugins ([#​21182](https://redirect.github.com/eslint/eslint/issues/21182)) (ESLint Bot) - [`d3266fb`](https://redirect.github.com/eslint/eslint/commit/d3266fb26c719c6b90a6cbe54bb120c9335ad19c) chore: unpin `webpack` dependency ([#​21172](https://redirect.github.com/eslint/eslint/issues/21172)) (Francesco Trotta) - [`65a6519`](https://redirect.github.com/eslint/eslint/commit/65a6519cc8733b4688558a8611397cf9d01dd55d) chore: add allowScripts field to package.json ([#​21092](https://redirect.github.com/eslint/eslint/issues/21092)) (GiHoon Noh) - [`22e5256`](https://redirect.github.com/eslint/eslint/commit/22e52568536e0009d4493dc888736bc163220c4b) ci: add `triage:no` label to Dependabot PRs ([#​21141](https://redirect.github.com/eslint/eslint/issues/21141)) (lumir) - [`55c9038`](https://redirect.github.com/eslint/eslint/commit/55c9038836c91b6bd5617f0c97bea2274c9cc0bf) ci: bump actions/labeler from 6 to 7 ([#​21159](https://redirect.github.com/eslint/eslint/issues/21159)) (dependabot\[bot]) - [`7280e78`](https://redirect.github.com/eslint/eslint/commit/7280e78183d4711a49916b6a49ba5efaa651a991) chore: update dependency prettier to v3.9.6 ([#​21162](https://redirect.github.com/eslint/eslint/issues/21162)) (renovate\[bot]) - [`eddbad6`](https://redirect.github.com/eslint/eslint/commit/eddbad60158d8cda86830fbe934a9d2282273b32) test: fix failing ecosystem test for `eslint-plugin-unicorn` ([#​21156](https://redirect.github.com/eslint/eslint/issues/21156)) (Francesco Trotta) - [`60a178d`](https://redirect.github.com/eslint/eslint/commit/60a178d5ef1b0c471be0831031ed7347f8f81dc2) chore: update ecosystem plugins ([#​21150](https://redirect.github.com/eslint/eslint/issues/21150)) (ESLint Bot) - [`f9f61dc`](https://redirect.github.com/eslint/eslint/commit/f9f61dc6112836f46a58a410c38b8c2faf10973f) test: add error locations to `no-unreachable` ([#​21151](https://redirect.github.com/eslint/eslint/issues/21151)) (JIYEON) - [`d086293`](https://redirect.github.com/eslint/eslint/commit/d08629382b0a6aaa042823b796e5100e60053b54) test: add error locations to `no-undef` ([#​21147](https://redirect.github.com/eslint/eslint/issues/21147)) (JIYEON) - [`cc01b67`](https://redirect.github.com/eslint/eslint/commit/cc01b67061bbf558aa25746883ea1cad847f7cf2) test: add error locations to `no-useless-catch` ([#​21144](https://redirect.github.com/eslint/eslint/issues/21144)) (devoil) - [`688e75e`](https://redirect.github.com/eslint/eslint/commit/688e75ede01b295d51f2f86c9d82da020a4c887e) chore: add missing backticks in JSDoc ([#​21143](https://redirect.github.com/eslint/eslint/issues/21143)) (Bo Hyun Kim) - [`7c1e175`](https://redirect.github.com/eslint/eslint/commit/7c1e17543ad396f50f65b003cf9142d43d3c63b0) test: add error locations to `require-await` ([#​21145](https://redirect.github.com/eslint/eslint/issues/21145)) (Grit) - [`588a26d`](https://redirect.github.com/eslint/eslint/commit/588a26ddce3c5a20f5b3f3d51ba1353cce7b4b0c) test: add error locations to `no-extra-label` ([#​21139](https://redirect.github.com/eslint/eslint/issues/21139)) (dongkyu lee) - [`059aa89`](https://redirect.github.com/eslint/eslint/commit/059aa895743639e3ab53d14f9d944ff4be042233) test: add error locations to `no-useless-concat` ([#​21140](https://redirect.github.com/eslint/eslint/issues/21140)) (dongkyu lee) - [`5a452a8`](https://redirect.github.com/eslint/eslint/commit/5a452a8ba53917d65c9d83c3959ed35c2f890613) test: add error locations to `no-const-assign` ([#​21138](https://redirect.github.com/eslint/eslint/issues/21138)) (dongkyu lee) </details> <details> <summary>yahoo/serialize-javascript (serialize-javascript)</summary> ### [`v7.1.0`](https://redirect.github.com/yahoo/serialize-javascript/releases/tag/v7.1.0) [Compare Source](https://redirect.github.com/yahoo/serialize-javascript/compare/v7.0.7...v7.1.0) #### What's Changed - feat: add Node.js 26 to test matrix by [@​okuryu](https://redirect.github.com/okuryu) in [#​224](https://redirect.github.com/yahoo/serialize-javascript/pull/224) - release: v7.1.0 by [@​okuryu](https://redirect.github.com/okuryu) in [#​225](https://redirect.github.com/yahoo/serialize-javascript/pull/225) **Full Changelog**: <https://github.com/yahoo/serialize-javascript/compare/v7.0.7...v7.1.0> </details> <details> <summary>sveltejs/svelte (svelte)</summary> ### [`v5.56.9`](https://redirect.github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#5569) [Compare Source](https://redirect.github.com/sveltejs/svelte/compare/svelte@5.56.8...svelte@5.56.9) ##### Patch Changes - fix: skip controlled each fast path while another batch is pending ([#​18625](https://redirect.github.com/sveltejs/svelte/pull/18625)) - fix: better whitespace handling inside printer ([#​18638](https://redirect.github.com/sveltejs/svelte/pull/18638)) - fix: don't duplicate comments in attributes ([#​18636](https://redirect.github.com/sveltejs/svelte/pull/18636)) - fix: preserve CSS comments in the AST printer ([#​18637](https://redirect.github.com/sveltejs/svelte/pull/18637)) </details> <details> <summary>privatenumber/tsx (tsx)</summary> ### [`v4.23.12`](https://redirect.github.com/privatenumber/tsx/releases/tag/v4.23.12) [Compare Source](https://redirect.github.com/privatenumber/tsx/compare/v4.23.11...v4.23.12) ##### Bug Fixes - shim `import.meta` when tokens are split by comments or newlines ([#​829](https://redirect.github.com/privatenumber/tsx/issues/829)) ([ed9d330](https://redirect.github.com/privatenumber/tsx/commit/ed9d33046a135de13a35fdfce12368b79d1b1518)), closes [#​828](https://redirect.github.com/privatenumber/tsx/issues/828) *** This release is also available on: - [npm package (@​latest dist-tag)](https://www.npmjs.com/package/tsx/v/4.23.12) ### [`v4.23.11`](https://redirect.github.com/privatenumber/tsx/compare/v4.23.10...bd3bc6448e957c1172eb91a0584ec7fec2d6a7ad) [Compare Source](https://redirect.github.com/privatenumber/tsx/compare/v4.23.10...v4.23.11) ### [`v4.23.10`](https://redirect.github.com/privatenumber/tsx/releases/tag/v4.23.10) [Compare Source](https://redirect.github.com/privatenumber/tsx/compare/v4.23.9...v4.23.10) ##### Bug Fixes - support nyc coverage discovery ([#​710](https://redirect.github.com/privatenumber/tsx/issues/710)) ([ec1bcd5](https://redirect.github.com/privatenumber/tsx/commit/ec1bcd5f711e5159b67cb0aea211f06cf2cfce8a)) *** This release is also available on: - [npm package (@​latest dist-tag)](https://www.npmjs.com/package/tsx/v/4.23.10) </details> --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMjkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Cameron <cameron.clark@hey.com> |
||
|
|
9c6f1912b5 |
chore(deps): update rust crates (#25756)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [futures](https://rust-lang.github.io/futures-rs) ([source](https://redirect.github.com/rust-lang/futures-rs)) | workspace.dependencies | patch | `0.3.33` → `0.3.34` | | [handlebars](https://redirect.github.com/sunng87/handlebars-rust) | workspace.dependencies | patch | `6.4.3` → `6.4.4` | | [javascript-globals](https://redirect.github.com/oxc-project/javascript-globals) | workspace.dependencies | patch | `1.5.1` → `1.5.2` | --- ### Release Notes <details> <summary>rust-lang/futures-rs (futures)</summary> ### [`v0.3.34`](https://redirect.github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#0334---2026-08-11) [Compare Source](https://redirect.github.com/rust-lang/futures-rs/compare/0.3.33...0.3.34) - Preserve cloned waker identity. ([#​3032](https://redirect.github.com/rust-lang/futures-rs/issues/3032)) - Updato `syn` to 3. ([#​3028](https://redirect.github.com/rust-lang/futures-rs/issues/3028)) </details> <details> <summary>sunng87/handlebars-rust (handlebars)</summary> ### [`v6.4.4`](https://redirect.github.com/sunng87/handlebars-rust/blob/HEAD/CHANGELOG.md#644---2026-08-12) [Compare Source](https://redirect.github.com/sunng87/handlebars-rust/compare/v6.4.3...v6.4.4) - \[Changed] We have to revert `preserve_json_order` as a default feature. Users who need this can still enable it for handlebars-rust, or enable `preserve_order` for you serde\_json. </details> <details> <summary>oxc-project/javascript-globals (javascript-globals)</summary> ### [`v1.5.2`](https://redirect.github.com/oxc-project/javascript-globals/blob/HEAD/CHANGELOG.md#152---2026-08-13) [Compare Source](https://redirect.github.com/oxc-project/javascript-globals/compare/javascript-globals-v1.5.1...javascript-globals-v1.5.2) ##### Other - Auto update globals from upstream ([#​268](https://redirect.github.com/oxc-project/javascript-globals/pull/268)) - Auto update globals from upstream ([#​265](https://redirect.github.com/oxc-project/javascript-globals/pull/265)) - Auto update globals from upstream ([#​261](https://redirect.github.com/oxc-project/javascript-globals/pull/261)) - *(deps)* update rust crate serde\_json to v1.0.151 ([#​259](https://redirect.github.com/oxc-project/javascript-globals/pull/259)) - *(deps)* update rust crate serde to v1.0.229 ([#​256](https://redirect.github.com/oxc-project/javascript-globals/pull/256)) - update sponsor section - *(deps)* update rust crate rustc-hash to v2.1.3 ([#​247](https://redirect.github.com/oxc-project/javascript-globals/pull/247)) - standardize rustfmt config - normalize README sponsor section - add crates environment to release workflow </details> --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - "before 10am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://redirect.github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMjkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Cameron <cameron.clark@hey.com> |
||
|
|
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. |
||
|
|
2dd7446b8f |
perf(diagnostics): preallocate graphical output (#25721)
Preallocate graphical reporter output from observed per-diagnostic size. Criterion: single ASCII -13.7%, batch ASCII -5.7%, Unicode/tab -2.0%. AI-assisted. <sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub> |
||
|
|
9c8abab7a7 |
perf(diagnostics): batch graphical reports (#25710)
Batch graphical diagnostics so reports sharing a source reuse line indexing, and route oxlint diagnostic batches through the new API. AI assistance: Codex was used. The contributor remains responsible for this change. <sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a></sub> |
||
|
|
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. |
||
|
|
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 |
||
|
|
4004c101ca |
fix(linter/eslint/no-irregular-whitespace): check comments by default (#25660)
## Summary - align the skipComments default with ESLint - report irregular whitespace in line and block comments by default - preserve the skipComments: true opt-out - verify suppressed comment diagnostics count disable directives as used - regenerate the published configuration schema Fixes #25616. |
||
|
|
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 |
||
|
|
a38f7b3d57 |
fix(oxlint,oxfmt): apply .gitignore only to walk targets, not explicitly named files (#25531)
Possibly fixes #25259, and partial revert of #25133. --- - `.gitignore` applies only to discovery (walking directory targets, cwd, globs) - An explicitly named file target is linted / formatted even when gitignored - = Restoring the pre-[#25133]() behavior for files, while fully keeping the [#25107]() fix for walk roots | Target | Current | This PR | | --- | --- | --- | | Explicit file (`oxlint dist/a.js`) | skipped | linted | | Explicit directory (`oxlint dist`) | skipped | skipped | | cwd inside ignored tree | skipped | skipped | The underlying principle: > `.gitignore` is a message addressed to git, not to tools. > Borrowing it to scope discovery is a useful heuristic, and a heuristic may narrow what the walk finds, but never refuse what the user names. > Only tool's own ignore config can refuse. (which remain hard for the husky staged-file case). This also re-aligns the CLI with stdin and LSP, which deliberately do not consult `.gitignore` (#19206). 👉🏻 This is the main motivation. ### Why not full revert A directory target names where to search, not what to process. The files under it are still discovered by the walk, so discovery rules apply. Reverting that would bring back [#25107](), whose old behavior was not even a statable spec: whether running inside an ignored tree processed anything depended on the ignore pattern's form (bare `generated` did, `generated/**` didn't), an artifact of walker pruning, not a design. ### Regarding to `--no-ignore` This flag remains orthogonal as a walk-level opt-out (`--no-ignore=vcs dist`) and for filling gap between existing tools. However, with explicit files working again, I'm inclined to close those PRs and revisit if demand shows up. For [#25259]()'s use case: name the files, e.g. `oxlint dist/foo.js` (or shell-expanded glob). |
||
|
|
0c68b7ff8b |
fix(estree): emit decorators on FormalParameterRest (#25582)
This PR adds support for emitting `decorators` when serializing an ast to ESTree (both with/without raw transfer).
Given the following code:
```
class C { method(@dec ...args) {} }
```
Before we emitted the following ESTree shape:
```json
"params": [
{
"type": "RestElement",
"decorators": [],
"argument": {
"type": "Identifier",
"decorators": [],
"name": "args",
"optional": false,
"typeAnnotation": null,
},
"optional": false,
"typeAnnotation": null,
"value": null,
}
],
```
Now we emit:
```json
"params": [
{
"type": "RestElement",
"decorators": [
{
"type": "Decorator",
"expression": { "type": "Identifier", "name": "dec" }
}
],
"argument": {
"type": "Identifier",
"decorators": [],
"name": "args",
"optional": false,
"typeAnnotation": null,
},
"optional": false,
"typeAnnotation": null,
"value": null,
},
],
```
fixes https://github.com/oxc-project/oxc/issues/18981
closes https://github.com/oxc-project/oxc/pull/24736
|
||
|
|
1d22912cb4 |
fix(linter/plugins): parse rule-less directive justifications (#25559)
## Summary - extract directive justifications before parsing directive labels, matching ESLint - return an empty rule value for rule-less directives while preserving their justification - cover block, enable, line, and next-line directives with both eslint and oxlint prefixes Closes #25556 |
||
|
|
9771ee151c |
test(linter): give the prune test its own suppression fixture directory (#25445)
`test_suppressing_errors_update_the_file_when_errors_are_decreased` and `test_prunning_errors_update_the_file_when_errors_are_decreased` both point at `fixtures/suppression/with_arg_and_decreased_errors`. Every other `SuppressionTester` fixture has a single owner. Both of these run oxlint in that directory, which rewrites `oxlint-suppressions.json`, and both then delete it and restore it from the backup in `Drop`. It showed up as an intermittent red in `just ready` while I was working on something unrelated, and it cost enough re-runs that I went looking. I flagged it at the end of #25412. This is that fix. Measured with `cargo test -p oxlint suppress`, ten runs per setting, on an 18 core machine: ``` --test-threads failures 1 0/10 12 0/10 16 0/10 17 0/10 18 3/10 20 0/10 24 0/10 ``` 18 is `hw.ncpu` there, and it is what `cargo test` picks by default. 20 and 24 are more parallel and never failed, so this is not load and it is not machine speed. The two tests have to land in the same dispatch wave, which depends on the divisor. The `Test Linux` job runs `cargo test --all-features` and stays green, which I read as a different core count rather than anything about the runner. Three distinct failure modes came out of the one shared directory: ``` tester.rs:249 one test's opening assert runs while the other sits between remove_file and fs::copy tester.rs:295 both Drop calls delete the same path, and the second gets ENOENT tester.rs:274 one test reads the file while the other is inside a truncating write ``` Before settling on the fixture split I checked whether repairing `Drop` would be enough, since deleting before copying is what opens the widest window. It is not enough. Guarding the delete with `&& !self.have_backup_file`, so the file is never absent, left the rate where it was and only changed the message: ``` Drop shape directory failures delete then copy, as today shared 3/20 copy only shared 4/40 unchanged separate 0/40 ``` To find out what the reader was actually getting in that third mode, I patched the panic at `tester.rs:274` to print the observed content. That patch was throwaway and is not in this diff: ``` PROBE observed len=0 serde=EOF while parsing a value at line 1 column 0 first80="" ``` Length zero, not a torn file. `SuppressionFile::save` uses `fs::write`, which is `File::create` plus `write_all`, and `File::create` opens with `O_TRUNC`. The truncate commits at open time and the bytes arrive on the next syscall, so the file is briefly empty. A separate directory is the only change that closes both that window and the `Drop` one. Calling out one thing up front: the new directory is a byte for byte copy of the old one. `--suppress-all` and `--prune-suppressions` converge in the decreased case, so the expected content is the same for both tests. The directory exists for isolation, not for content. `with_arg_and_increased_errors` and `with_arg_and_increased_errors_prune` are the same split for the case where the two commands diverge, so five of six files match there and six of six match here. This is the same shape as #20717, where `--init` writes leaked across parallel tests. With the change in, the suppression module is 0/20 at 18 threads and 0/10 at the default. The rest of `just ready` is green as well: `typos`, `cargo lintgen`, `just fmt`, `just check`, `just test`, `just lint`, `just doc` and `just ast`, with 4446 tests passing under `--test-threads=1`. Three other suppression fixtures have more than one owner, and I left all three alone. `fixed_violations_are_reported` has two readers. `type_check_only_with_regular_rule` also has two, and although the second passes `--suppress-all` and `--prune-suppressions`, `lint.rs:426` rejects that combination before any lint runs, so nothing writes. `diagnostics_filtered_if_count_is_the_same` is the only other one where a write really happens, so it carries the truncating write window in principle, but that window is a single `fs::write` over a few hundred bytes, where the one this PR fixes spanned a whole `Drop` delete-then-copy plus the other test's entire run. Forty runs with those two tests forced to overlap found nothing. I did not want to change something I cannot show is broken. Happy to fold it in if the whole class should close in one go. Disclosure, per CONTRIBUTING.md: I used Claude for the investigation and for the patch. I have reviewed and tested all of it myself. |
||
|
|
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. |
||
|
|
82c924496c |
refactor(diagnostics): clean up vendored renderer (#25501)
Clean up the diagnostics renderer vendored after removing `oxc-miette`: simplify source attachment and multiline labels, tighten visibility, and correct JSON escaping and debug formatting. Validated with `just ready`. AI-assisted; contributor review is required before merge. |
||
|
|
00e1b762e0 |
refactor(diagnostics): vendor oxc-miette (#25499)
We no longer need to maintain the `oxc-miette` repo as most of the code is now removed, the remaining code is minimal and can be vendored. |
||
|
|
2d7a75d46b |
chore(deps): update oxc to ^0.144.0 (#25483)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [@oxc-project/types](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxc-types)) | [`^0.143.0` → `^0.144.0`](https://renovatebot.com/diffs/npm/@oxc-project%2ftypes/0.143.0/0.144.0) |  |  |  |  | | [oxc-parser](https://oxc.rs/docs/guide/usage/parser) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/napi/parser)) | [`^0.143.0` → `^0.144.0`](https://renovatebot.com/diffs/npm/oxc-parser/0.143.0/0.144.0) |  |  |  |  | --- ### Release Notes <details> <summary>oxc-project/oxc (@​oxc-project/types)</summary> ### [`v0.144.0`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/npm/oxc-types/CHANGELOG.md#01440---2026-08-10) ##### 💥 BREAKING CHANGES - [`44fd320`](https://redirect.github.com/oxc-project/oxc/commit/44fd320) ast: \[**BREAKING**] Split TS external modules & Namespace Declarations ([#​25284](https://redirect.github.com/oxc-project/oxc/issues/25284)) (camc314) </details> <details> <summary>oxc-project/oxc (oxc-parser)</summary> ### [`v0.144.0`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/napi/parser/CHANGELOG.md#01440---2026-08-10) ##### 💥 BREAKING CHANGES - [`a33788e`](https://redirect.github.com/oxc-project/oxc/commit/a33788e) ast: \[**BREAKING**] Group class heritage into `ClassHeritage` ([#​25360](https://redirect.github.com/oxc-project/oxc/issues/25360)) (camc314) - [`5c5cdcd`](https://redirect.github.com/oxc-project/oxc/commit/5c5cdcd) ast: \[**BREAKING**] Narrow `TSInterfaceHeritage::expression` to TSTypeName ([#​24360](https://redirect.github.com/oxc-project/oxc/issues/24360)) (camc314) - [`6be314f`](https://redirect.github.com/oxc-project/oxc/commit/6be314f) ast: \[**BREAKING**] Remove duplicated `VariableDeclarator::kind` ([#​25319](https://redirect.github.com/oxc-project/oxc/issues/25319)) (camc314) - [`44fd320`](https://redirect.github.com/oxc-project/oxc/commit/44fd320) ast: \[**BREAKING**] Split TS external modules & Namespace Declarations ([#​25284](https://redirect.github.com/oxc-project/oxc/issues/25284)) (camc314) ##### 🐛 Bug Fixes - [`2a1058a`](https://redirect.github.com/oxc-project/oxc/commit/2a1058a) napi: Omit parser header from WASI declarations ([#​25254](https://redirect.github.com/oxc-project/oxc/issues/25254)) (camc314) </details> --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
c42d6397ea |
release(apps): oxlint v1.78.0 && oxfmt v0.63.0 (#25473)
# Oxlint ### 💥 BREAKING CHANGES - |
||
|
|
030857b509 |
refactor(diagnostics): update oxc-miette to v4 (#25395)
Remove the miette `Report` wrapper and update oxc-miette to v4's narrowed diagnostic and source protocol. AI-assisted by OpenAI Codex. |
||
|
|
a92c5410a1 |
fix(linter): preserve source text for JS plugin ignore fixes (#25280)
Closes #25278 ## Overview This PR resolves an oxlint language server crash that could occur when requesting code actions for diagnostics reported by JS plugins, particularly when the diagnostic appears after the beginning of a file. JS plugin diagnostics can now safely provide regular fixes as well as line-level and file-level disable actions. ## Root cause 1. In `run_external_rules()`, the `semantic` is being taken to run the external JS plugin rules, leaving the former `semantic` inside the context host empty: https://github.com/oxc-project/oxc/blob/e23dccf338d568ac0c2be3b1223f213c797923f7/crates/oxc_linter/src/lib.rs#L539 2. The language server enables `with_ignore_fixes` to generate ignore fixes, but inside the `add_ignore_fix()`, it doesn't check the `section_source_text`. 3. The context host with the empty `semantic` passes the empty source text to the `add_ignore_fix()` as `section_source_text`, and the empty string just causes the crash. https://github.com/oxc-project/oxc/blob/e23dccf338d568ac0c2be3b1223f213c797923f7/crates/oxc_linter/src/context/host.rs#L329-L334 ## What changed A new property `source_text` is added to the context sub host, which stores a reference to the real source text string. Even if the `semantic` is taken and becomes empty, the reference can still get the real string and make things work. ```diff pub struct ContextSubHost<'a> { /// Semantic information about the file being linted, which includes scopes, symbols and AST nodes. /// See [`Semantic`]. pub(super) semantic: Semantic<'a>, // ... + /// Stable source text for this script section + /// which remains available even after `semantic` is taken while running JS plugins. + pub(super) source_text: &'a str, /// The source text offset of the sub host pub(super) source_text_offset: u32, } ``` And I added a new utility method to get the `source_text` from the context sub host. ```rs #[inline] pub fn source_text(&self) -> &'a str { self.current_sub_host().source_text() } ``` When passing source text to `add_ignore_fix()`, just use the new `source_text()` method. ```diff if self.with_ignore_fixes { - let source_text = self.semantic().source_text(); + let source_text = self.source_text(); for diagnostic in &mut diagnostics { diagnostic.add_ignore_fix(self.current_sub_host().source_text_offset, source_text); } } // (the same as other occurs ``` Also, I added the necessary check for the `section_source_text` in `add_ignore_fix()`. ## Notes This is my first contribution to oxc project. Thanks for reviewing! |
||
|
|
c7583238a0 |
refactor(lsp): add ToolBuildResult struct for optional client message (#25386)
Added a new `ToolBuildResult` struct, so an optional `ClientMessage` can be passed to `Backend` (in a later PR). This allows us later to send the custom message to the clients interface when some config errors happened on the (re)creation. There is no message sent yet, this will be integrated in another PR too. This PR is just the base for the `ToolInterface`. |
||
|
|
a33788e13e |
feat(ast)!: group class heritage into ClassHeritage (#25360)
## Summary
- Groups `Class::super_class` and `Class::super_type_arguments` into `Class::heritage`.
- Introduces `ClassHeritage` containing the superclass expression and its optional TypeScript type arguments.
- Makes superclass type arguments without a superclass expression unrepresentable.
## Breaking Change
The Rust AST changes from:
```rust
pub struct Class<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub r#type: ClassType,
pub decorators: Vec<'a, Decorator<'a>>,
pub id: Option<BindingIdentifier<'a>>,
#[ts]
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub super_class: Option<Expression<'a>>,
#[ts]
pub super_type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
#[ts]
pub implements: Vec<'a, TSClassImplements<'a>>,
pub body: Box<'a, ClassBody<'a>>,
#[ts]
pub r#abstract: bool,
#[ts]
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}
```
to:
```rust
pub struct Class<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub r#type: ClassType,
pub decorators: Vec<'a, Decorator<'a>>,
pub id: Option<BindingIdentifier<'a>>,
#[ts]
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub heritage: Option<ClassHeritage<'a>>,
#[ts]
pub implements: Vec<'a, TSClassImplements<'a>>,
pub body: Box<'a, ClassBody<'a>>,
#[ts]
pub r#abstract: bool,
#[ts]
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}
pub struct ClassHeritage<'a> {
pub expression: Expression<'a>,
#[ts]
pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
}
```
## Why?
ECMAScript defines the complete `extends` clause as `ClassHeritage`:
```text
ClassHeritage : extends LeftHandSideExpression
```
TypeScript additionally permits type arguments on the heritage expression:
```ts
class Derived extends Base<T> {}
```
Previously, the AST stored the expression and type arguments independently:
```text
Class {
super_class: Some(Base),
super_type_arguments: Some(<T>),
...
}
```
This allowed an invalid state to be constructed:
```text
Class {
super_class: None,
super_type_arguments: Some(<T>),
...
}
```
Superclass type arguments cannot exist without an `extends` expression.
The parser already treated these fields as a pair. It parsed a class heritage entry and then split its expression and type arguments into two independent fields. Builders and transforms therefore had to preserve their relationship manually.
Grouping them into `ClassHeritage` makes the syntactic dependency explicit and prevents consumers from observing or constructing contradictory class heritage.
## Class heritage forms
A class without an `extends` clause has no heritage:
```js
class Base {}
```
```text
Class {
heritage: None,
...
}
```
A class extending an expression has heritage without type arguments:
```js
class Derived extends Base {}
```
```text
Class {
heritage: Some(ClassHeritage {
expression: Base,
type_arguments: None,
}),
...
}
```
TypeScript type arguments belong to the same heritage structure:
```ts
class Derived extends Base<T> {}
```
```text
Class {
heritage: Some(ClassHeritage {
expression: Base,
type_arguments: Some(<T>),
}),
...
}
```
The heritage expression may be any valid class heritage expression:
```js
class Derived extends mixin(Base) {}
class NullDerived extends null {}
```
## How to migrate
Code that previously accessed the superclass expression directly:
```rust
if let Some(super_class) = &class.super_class {
// ...
}
```
can use the compatibility accessor:
```rust
if let Some(super_class) = class.super_class() {
// ...
}
```
Code that needs both parts should access the grouped heritage:
```rust
if let Some(heritage) = &class.heritage {
let expression = &heritage.expression;
let type_arguments = heritage.type_arguments.as_deref();
}
```
Mutating consumers should update the nested fields:
```rust
if let Some(heritage) = &mut class.heritage {
heritage.type_arguments = None;
}
```
Common migrations:
| Previous representation | New representation |
| --- | --- |
| `class.super_class` | `class.heritage.as_ref().map(\|h\| &h.expression)` or `class.super_class()` |
| `class.super_type_arguments` | `class.heritage.as_ref()?.type_arguments` or `class.super_type_arguments()` |
| `class.super_class.is_some()` | `class.heritage.is_some()` |
| Mutate `class.super_class` | Mutate `class.heritage.expression` |
| Clear `class.super_type_arguments` | Clear `class.heritage.type_arguments` |
| Pass superclass and type arguments separately to a `Class` builder | Construct and pass `ClassHeritage` |
| Clone both fields independently | Clone `class.heritage` |
```ts
superClass: Expression | null;
superTypeArguments?: TSTypeParameterInstantiation | null;
```
No `heritage` property or `ClassHeritage` node is added to the ESTree output.
fixes https://github.com/oxc-project/backlog/issues/216
|
||
|
|
4ec9189b26 |
perf(oxlint/lsp): avoid second lock for getting/removing unused directives (#25350)
Avoids a second lock for `.map` inside `DirectivesStore` when consuming the directives on `--lsp` side. |
||
|
|
6c0d01b8de |
perf(oxlint/lsp): preallocate fix-content vec (#25351)
After https://github.com/oxc-project/oxc/pull/24958 we know the size of `Vec<FixedContent>` , because we are only consuming now `Messages.fixes` which are directly mapped into `FixedContent` |
||
|
|
5c5cdcd522 |
feat(ast)!: narrow TSInterfaceHeritage::expression to TSTypeName (#24360)
## Summary
Narrow `TSInterfaceHeritage` from a general JavaScript `Expression` to `TSTypeName`.
```rust
pub struct TSInterfaceHeritage<'a> {
pub type_name: TSTypeName<'a>,
pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
}
```
## Breaking Change
The Rust AST field changes from:
```rust
expression: Expression<'a>
```
to:
```rust
type_name: TSTypeName<'a>
```
## Why?
The current AST can represent shapes such as:
```ts
interface A extends foo() {}
interface A extends A + B {}
interface A extends new Foo() {}
interface A extends true {}
```
Which is an overly wide type since all of the above variants are invalid.
This PR tightens up the AST, making these invalid variants irrepresentable.
## How to migrate?
This should be a trivial migration:
1. instead of accessing `expression` on `TSInterfaceHeritage`, now access `type_name`
2. change any pattern matching on the `type_name` field to use `TypeName` (this is a smaller subset so should allow deleting code!)
closes https://github.com/oxc-project/backlog/issues/215
|
||
|
|
6b1c4795b2 |
fix(oxlint): normalize customized rule names (#25316)
## Summary - normalize LSP `rulesCustomization` keys using the linter config rule-name parser - support `eslint/` prefixes and existing plugin aliases such as `@typescript-eslint` - cover prefixed severity and autofix customization paths Closes #25311 |
||
|
|
ccb8fe89db |
feat(linter/jsdoc): implement no-blank-blocks rule (#25207)
this PR implements `jsdoc/no-blank-blocks` rule, issue #1170 |
||
|
|
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` |
||
|
|
6be314f226 |
feat(ast)!: remove duplicated VariableDeclarator::kind (#25319)
## Summary
- Removes `VariableDeclarator::kind`.
- Makes `VariableDeclaration::kind` the single source of truth for every declarator in its declaration list.
- Makes contradictory parent and child declaration kinds unrepresentable.
## Breaking Change
The Rust AST changes from:
```rust
pub struct VariableDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub kind: VariableDeclarationKind,
pub declarations: Vec<'a, VariableDeclarator<'a>>,
#[ts]
pub declare: bool,
}
pub struct VariableDeclarator<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
#[estree(skip)]
pub kind: VariableDeclarationKind,
#[estree(via = VariableDeclaratorId)]
pub id: BindingPattern<'a>,
#[ts]
#[estree(skip)]
pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub init: Option<Expression<'a>>,
#[ts]
pub definite: bool,
}
```
to:
```rust
pub struct VariableDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub kind: VariableDeclarationKind,
pub declarations: Vec<'a, VariableDeclarator<'a>>,
#[ts]
pub declare: bool,
}
pub struct VariableDeclarator<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
#[estree(via = VariableDeclaratorId)]
pub id: BindingPattern<'a>,
#[ts]
#[estree(skip)]
pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub init: Option<Expression<'a>>,
#[ts]
pub definite: bool,
}
```
## Why?
A variable declaration has one declaration kind shared by every declarator in its declaration list:
```js
const first = 1, second = 2;
```
Previously, the AST stored that kind on both the parent declaration and every child declarator:
```text
VariableDeclaration {
kind: Const,
declarations: [
VariableDeclarator { kind: Const, ... },
VariableDeclarator { kind: Const, ... },
],
}
```
This allowed contradictory ASTs to be constructed:
```text
VariableDeclaration {
kind: Const,
declarations: [
VariableDeclarator { kind: Var, ... },
],
}
```
Different consumers read different copies:
- Code generation used `VariableDeclaration::kind`.
- Semantic binding used `VariableDeclarator::kind`.
- Lint rules, transforms, and minifier passes used a mixture of both.
As a result, one AST could be emitted as `const` while its binding was treated as function-scoped `var`.
Transforms also had to keep the copies synchronized manually. For example, const-to-let normalization updated the parent and then looped through every declarator to update each child. Explicit resource management performed similar paired mutations for `using` declarations.
Keeping the kind only on `VariableDeclaration` removes this synchronization requirement and prevents consumers from observing conflicting declaration semantics.
## Declaration forms
The declaration kind now belongs exclusively to the node that owns the declaration list:
```js
let value;
```
```text
VariableDeclaration {
kind: Let,
declarations: [
VariableDeclarator { id: value, ... },
],
}
```
Multiple declarators share the same parent kind:
```js
const first = 1, second = 2;
```
```text
VariableDeclaration {
kind: Const,
declarations: [
VariableDeclarator { id: first, ... },
VariableDeclarator { id: second, ... },
],
}
```
## How to migrate
Code that previously read the kind from a declarator:
```rust
if declarator.kind.is_const() {
// ...
}
```
should now read it from the containing declaration:
```rust
if declaration.kind.is_const() {
// ...
}
```
Consumers operating through an AST node store should retrieve the parent `VariableDeclaration`:
```rust
let AstKind::VariableDeclaration(declaration) =
nodes.parent_kind(declarator.node_id())
else {
unreachable!();
};
let kind = declaration.kind;
```
Common migrations:
| Previous representation | New representation |
| --- | --- |
| `declarator.kind` | Containing `declaration.kind` |
| Match `VariableDeclarator::kind` during semantic binding | Read the parent `VariableDeclaration` from ancestry |
| Pass `kind` to `VariableDeclarator::new` | Remove the `kind` argument |
| Update parent and every child kind | Update only `VariableDeclaration::kind` |
| Recover kind after detaching a declarator | Capture or pass the parent kind before detaching it |
| Inspect a symbol’s declarator kind in lint rules | Resolve its parent declaration through the node store |
When constructing declarators, use the generated kindless `VariableDeclarator` builders and place them inside a `VariableDeclaration` carrying the required kind.
fixes https://github.com/oxc-project/backlog/issues/237
|
||
|
|
4abff11c80 |
perf(linter): avoid redundant message work in the agent reporter (#25315)
Generated with Claude Code, Opus 5. Reviewed and tested by me. Mainly just avoiding extra, unneeded allocations per-diagnostic. This shouldn't matter much at normal scales, but given that many people are using Claude Code, Codex, etc for setting up their linter config or to mass-resolve lint violations, I think the tradeoff in extra code here is probably worth it because there are definite cases where this will be getting triggered with large diagnostic counts. I will admit the `is_already_compact` method here is jank, though. --- Two small changes to `format_agent`, both removing work that was already done. **1. Borrow already-compact messages.** `compact_message` rebuilt every message into a fresh `String` by splitting on whitespace and rejoining, even though nearly every rule message is already compact and comes out byte-for-byte identical. It now checks first and borrows when there is nothing to collapse, falling back to the rebuild otherwise. **2. Reuse the message `Info` already rendered.** `Info::new` calls `diagnostic.to_string()` internally; `format_agent` discarded that and rendered it a second time. It now takes the message from `Info`. `Info` only fills the message in when the diagnostic has a resolvable label, so the direct render is kept for the label-less case — which the existing `reporter_error_without_label` test covers. ## Allocations Measured with a counting global allocator, `--threads=1` for deterministic counts, on a corpus of 20k small files producing exactly 2,400,000 diagnostics. `unix` is a control (untouched by this PR) and `--silent` is the no-formatter baseline. | format | main allocs | branch allocs | diff | change | | --- | ---: | ---: | ---: | ---: | | silent (baseline) | 55,672,894 | 55,672,894 | 0 | 0.00% | | unix (control) | 91,353,791 | 91,353,791 | 0 | 0.00% | | agent | 124,894,389 | 104,194,389 | -20,700,000 | -16.57% | Subtracting the baseline to isolate the formatter itself: | | main | branch | change | | --- | ---: | ---: | ---: | | agent formatter allocations | 69,221,495 | 48,521,495 | **-29.9%** | | per diagnostic | 28.84 | 20.22 | -8.62 | | bytes requested | 8.39 GB | 7.66 GB | -729.7 MB | Worth noting that the saving is much larger than the two `String`s the diff visibly removes. `diagnostic.to_string()` is not one allocation — rendering an `Error` goes through miette formatting, which allocates repeatedly — so removing the duplicate render is worth around 8 allocations per diagnostic, not one (we should maybe consider figuring out if we can fix that separately to reduce the allocations per diagnostic, but usually there aren't too many diagnostics so it's a minor improvement). ## Timing Paired-difference measurement: samples interleaved one-for-one between the two binaries and differenced pairwise, so drift cancels. `unix` again as control. | corpus | format | main | branch | diff | 95% CI | change | | --- | --- | ---: | ---: | ---: | :---: | ---: | | 20k small files (2.4M diagnostics) | agent | 3837ms | 3272ms | -564.4ms | [-590.7, -538.2]ms | -14.7% | | 20k small files (2.4M diagnostics) | unix (control) | 2846ms | 2832ms | -14.2ms | [-39.4, +10.9]ms | -0.5% | | vscode `-D all` (1.37M diagnostics) | agent | 13721ms | 13381ms | -339.8ms | [-511.6, -168.0]ms | -2.5% | | vscode `-D all` (1.37M diagnostics) | unix (control) | 12794ms | 12781ms | -12.9ms | [-70.1, +44.4]ms | -0.1% | ## Equivalence Confirmed byte-identical output from the formatter on main vs this branch over VS Code. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
6bb5421c4a |
perf(linter): hoist current_dir out of the stylish reporter loop (#25313)
AI Disclosure: Generated with Claude Code, reviewed and tested by me. Just a micro-optimization. The stylish reporter calls `std::env::current_dir()` once per file group, in order to canonicalize each filename for display. That is a syscall, and the result is identical for every group, so this reads it once before the loop and borrows it. Output is unchanged — `current_dir()` is not expected to vary mid-run, and the value is used the same way. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
44fd320324 |
feat(ast)!: split TS external modules & Namespace Declarations (#25284)
## Summary
- Splits `TSModuleDeclaration` into two dedicated declaration nodes:
- `TSExternalModuleDeclaration` for string-literal modules and module augmentations.
- `TSNamespaceDeclaration` for identifier-based `module` and `namespace` declarations.
- Removes `TSModuleDeclaration`, `TSModuleDeclarationName`, `TSModuleDeclarationBody`, and `TSModuleDeclarationKind`.
- Makes invalid combinations of names, bodies, and declaration kinds unrepresentable.
- Ensures only namespace declarations introduce a normal binding.
- Updates all AST consumers, generators, traversal, formatting, code generation, semantic analysis, lint rules, transforms, and serialization.
- Keeps normal and eager-raw ESTree output compatible: both declarations remain `TSModuleDeclaration` nodes.
- Allows experimental lazy raw deserialization to expose the two new node types directly.
## Breaking Change
The Rust AST changes from:
```rust
pub enum Declaration<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
FunctionDeclaration(Box<'a, Function<'a>>) = 33,
ClassDeclaration(Box<'a, Class<'a>>) = 34,
TSTypeAliasDeclaration(Box<'a, TSTypeAliasDeclaration<'a>>) = 35,
TSInterfaceDeclaration(Box<'a, TSInterfaceDeclaration<'a>>) = 36,
TSEnumDeclaration(Box<'a, TSEnumDeclaration<'a>>) = 37,
TSModuleDeclaration(Box<'a, TSModuleDeclaration<'a>>) = 38,
TSGlobalDeclaration(Box<'a, TSGlobalDeclaration<'a>>) = 39,
TSImportEqualsDeclaration(Box<'a, TSImportEqualsDeclaration<'a>>) = 40,
}
pub struct TSModuleDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub id: TSModuleDeclarationName<'a>,
pub body: Option<TSModuleDeclarationBody<'a>>,
pub kind: TSModuleDeclarationKind,
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}
```
to:
```rust
pub enum Declaration<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
FunctionDeclaration(Box<'a, Function<'a>>) = 33,
ClassDeclaration(Box<'a, Class<'a>>) = 34,
TSTypeAliasDeclaration(Box<'a, TSTypeAliasDeclaration<'a>>) = 35,
TSInterfaceDeclaration(Box<'a, TSInterfaceDeclaration<'a>>) = 36,
TSEnumDeclaration(Box<'a, TSEnumDeclaration<'a>>) = 37,
TSExternalModuleDeclaration(Box<'a, TSExternalModuleDeclaration<'a>>) = 38,
TSNamespaceDeclaration(Box<'a, TSNamespaceDeclaration<'a>>) = 39,
TSGlobalDeclaration(Box<'a, TSGlobalDeclaration<'a>>) = 40,
TSImportEqualsDeclaration(Box<'a, TSImportEqualsDeclaration<'a>>) = 41,
}
pub struct TSExternalModuleDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub id: StringLiteral<'a>,
pub body: Option<Box<'a, TSModuleBlock<'a>>>,
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}
pub struct TSNamespaceDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub id: BindingIdentifier<'a>,
pub body: TSNamespaceDeclarationBody<'a>,
pub kind: TSNamespaceDeclarationKind,
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}
pub enum TSNamespaceDeclarationBody<'a> {
TSNamespaceDeclaration(Box<'a, TSNamespaceDeclaration<'a>>) = 0,
TSModuleBlock(Box<'a, TSModuleBlock<'a>>) = 1,
}
pub enum TSNamespaceDeclarationKind {
Module = 0,
Namespace = 1,
}
```
The corresponding inherited `Statement` variants, `AstKind` variants, builders, and visitor methods have also changed.
## Why?
`TSModuleDeclaration` previously represented two declaration families with different syntax and semantics:
```ts
declare module "foo" {}
declare module "*.css";
module Foo {}
namespace Foo {}
namespace Foo.Bar {}
```
The shared representation allowed invalid states such as:
- A namespace with a string-literal name.
- An external module with an identifier name.
- An identifier namespace without a body.
- A dotted external module.
- An external module containing another module declaration as its body.
- A declaration whose `kind` disagreed with its name.
Consumers also had to inspect `id` before determining whether the node introduced a binding or represented an external module.
The two declaration families have stronger independent invariants:
### External modules
- Always have a string-literal name.
- Never introduce a normal binding identifier.
- May omit their body.
- Cannot use dotted names.
- Use module-body import and export rules.
### Namespace declarations
- Always have a binding identifier.
- Always have a body.
- May contain nested namespace declarations for dotted names.
- Explicitly preserve the `module` or `namespace` spelling.
- Introduce a namespace/module symbol.
- Use namespace-body restrictions.
Dedicated nodes encode these differences directly.
## Declaration forms
External modules use `TSExternalModuleDeclaration`:
```ts
declare module "foo" {}
declare module "*.css";
module "foo" {}
```
Identifier-based declarations use `TSNamespaceDeclaration`:
```ts
module Foo {}
namespace Foo {}
```
Dotted namespaces are represented as nested namespace declarations:
```ts
namespace Foo.Bar {}
```
```rust
TSNamespaceDeclaration {
id: Foo,
body: TSNamespaceDeclarationBody::TSNamespaceDeclaration(
TSNamespaceDeclaration {
id: Bar,
body: TSNamespaceDeclarationBody::TSModuleBlock(...),
// ...
}
),
// ...
}
```
Only `TSExternalModuleDeclaration::body` is optional.
## ESTree compatibility
Normal serialization and eager raw deserialization continue to emit the existing ESTree shape:
```ts
interface TSModuleDeclaration {
type: "TSModuleDeclaration";
id: BindingIdentifier | StringLiteral | TSQualifiedName;
body: TSModuleBlock | null;
kind: "module" | "namespace";
declare: boolean;
global: false;
}
```
Dotted namespaces continue to serialize as a single `TSModuleDeclaration` with a `TSQualifiedName`.
Experimental lazy raw deserialization is not compatibility-preserving. It now exposes `TSExternalModuleDeclaration` and `TSNamespaceDeclaration` directly, with separate constructors, layouts, and visitor type IDs.
## How to migrate
Code that previously matched all forms through one variant:
```rust
if let Declaration::TSModuleDeclaration(declaration) = declaration {
// ...
}
```
should now match the required declaration family:
```rust
match declaration {
Declaration::TSExternalModuleDeclaration(declaration) => {
// String-literal external module
}
Declaration::TSNamespaceDeclaration(declaration) => {
// Identifier-based module or namespace
}
_ => {}
}
```
The same applies to `Statement` and `AstKind`:
```rust
Statement::TSExternalModuleDeclaration(declaration)
Statement::TSNamespaceDeclaration(declaration)
AstKind::TSExternalModuleDeclaration(declaration)
AstKind::TSNamespaceDeclaration(declaration)
```
Common field migrations:
| Previous representation | New representation |
| --- | --- |
| `TSModuleDeclarationName::StringLiteral(id)` | `TSExternalModuleDeclaration::id` |
| `TSModuleDeclarationName::Identifier(id)` | `TSNamespaceDeclaration::id` |
| `body: None` | Only valid on `TSExternalModuleDeclaration` |
| `TSModuleDeclarationBody::TSModuleBlock` | External `body` or `TSNamespaceDeclarationBody::TSModuleBlock` |
| `TSModuleDeclarationBody::TSModuleDeclaration` | `TSNamespaceDeclarationBody::TSNamespaceDeclaration` |
| `TSModuleDeclarationKind::Module` | External module, or `TSNamespaceDeclarationKind::Module` |
| `TSModuleDeclarationKind::Namespace` | `TSNamespaceDeclarationKind::Namespace` |
| Inspect `id` to determine binding behavior | Match `TSNamespaceDeclaration` |
| `declaration.id()` for string modules | Now returns `None` |
| `visit_ts_module_declaration` | `visit_ts_external_module_declaration` or `visit_ts_namespace_declaration` |
When constructing nodes, use the generated `TSExternalModuleDeclaration` or `TSNamespaceDeclaration` builders rather than recreating the previous shared representation.
fixes https://github.com/oxc-project/backlog/issues/218
|
||
|
|
9a7c323500 |
perf(linter): compute diagnostic Info once per diagnostic in junit reporter (#25312)
AI Disclosure: Generated with Claude Code, Opus 5. Tested and reviewed by me for correctness. --- `format_junit` built an `Info` for every diagnostic twice: once to group diagnostics by filename, then again inside the render loop. `Info::new` reads the span out of the source, so this doubled the most expensive part of the reporter. Build it once and group by index instead. Also drop two other duplicated pieces of work in the same loop: the message was `xml_escape`d twice (once for the attribute, once for the description), and the rule name was re-derived via `code().to_string()` even though `Info` already carries it as `rule_id`. And the nested `Vec<String>` + `join` is now a single output buffer. Benchmarked with 3 runs x 2 format options (checkstyle as the control) x 3 repos, shows small reductions on junit in RSS thanks to this change, and 40-47% drops in runtime (`oxlint -D all --format=NAME`): | repo | diagnostics | format | main | branch | delta | change | RSS main | RSS branch | | --- | ---: | --- | ---: | ---: | ---: | ---: | ---: | ---: | | vscode | 1,366,572 | checkstyle | 11832ms | 11645ms | -187ms | -1.6% | 3272 MB | 3273 MB | | vscode | 1,366,572 | **junit** | 22022ms | 11611ms | -10410ms | **-47.3%** | 3325 MB | 3287 MB | | gitlab | 363,895 | checkstyle | 1749ms | 1723ms | -26ms | -1.5% | 966 MB | 971 MB | | gitlab | 363,895 | **junit** | 2895ms | 1718ms | -1177ms | **-40.7%** | 989 MB | 948 MB | | canvas-lms | 350,637 | checkstyle | 2207ms | 2155ms | -52ms | -2.3% | 917 MB | 915 MB | | canvas-lms | 350,637 | **junit** | 3944ms | 2139ms | -1805ms | **-45.8%** | 921 MB | 886 MB | On a more reasonable number of diagnostics (running on canvas-lms with the default ruleset) the numbers are less pronounced but still show a 17% drop: | repo | ruleset | diagnostics | format | main | branch | delta | change | | --- | --- | ---: | --- | ---: | ---: | ---: | ---: | | canvas-lms | default | 3,149 | checkstyle | 218ms | 219ms | +1ms | +0.5% | | canvas-lms | default | 3,149 | junit | 265ms | 219ms | -46ms | -17.3% | On a repo with 0 violations, the runtime difference for junit on main vs. this branch is entirely noise. Realistically this won't have much of an impact in a user's actual run, as most of the time a lint run results in one of: - 0 diagnostics - a single digit number of diagnostics in a junit run due to new violations introduced by code changes - or there are only a few hundred to a few thousand max (due to, for example, warnings which are considered safe and are only used for a "transition" period where a rule is soft-enabled until all existing violations of it are fixed). But I think it's worthwhile regardless to help on smaller #s of diagnostics. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
1cf7ddea46 |
perf(oxlint): render JSON report into a single buffer (#25295)
AI Disclosure: Generated with Claude Code, Opus 5. Reviewed and tested by me. ## What `format_json` rendered each diagnostic into its own `String`, collected them into a `Vec<String>`, then `join`ed them. That allocates once per diagnostic and copies the entire report a second time to build the joined result. This renders straight into one output buffer instead. ## Why On the vscode corpus with `-D all` — 1.37M diagnostics, ~500 MB of JSON output: | | before | after | | --- | --- | --- | | `--format=json` wall clock | 13.3 s | 12.6 s | | peak RSS | 4668 MB | 3576 MB | Measured as best-of-3 with the two binaries interleaved, output redirected to `/dev/null`. ## Correctness Output is byte-identical before and after. Verified on `apps/oxlint/fixtures/cli/output_formatter_diagnostic` and on a 365k-diagnostic subset of vscode (170 MB of JSON compared byte-for-byte). Note that oxlint's diagnostic ordering is nondeterministic run-to-run under parallelism, so the comparison was run with `--threads=1`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
72bbbe240a | chore(deps): update dependency oxc-parser to ^0.143.0 (#25260) | ||
|
|
cc01bd7f0f |
chore(deps): update dependency @oxc-project/types to ^0.143.0 (#25255)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [@oxc-project/types](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxc-types)) | [`^0.142.0` → `^0.143.0`](https://renovatebot.com/diffs/npm/@oxc-project%2ftypes/0.142.0/0.143.0) |  |  |  |  | --- ### Configuration 📅 **Schedule**: (in timezone Asia/Shanghai) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
9a423f2f48 |
release(apps): oxlint v1.77.0 && oxfmt v0.62.0 (#25251)
# Oxlint ### 💥 BREAKING CHANGES - |