Commit Graph

23 Commits

Author SHA1 Message Date
leaysgur 181953b92d docs(oxfmt,formatter_core,formatter,formatter_yaml,formatter_css,formatter_graphql): extract DIVERGENCES.md out from AGENTS.md (#26121)
- Extract "known divergences" section from `AGENTS.md` to explicit `DIVERGENCES.md` with code example
- Update all anchors
- Add missing pinned fixtures
2026-08-27 05:33:58 +00:00
Boshen 1193c9dbaf chore(oxfmt): dogfood operator position at line start (#25937)
dogfood
2026-08-20 14:36:47 +00:00
Boshen 1c4f519e36 feat(napi): add Relay transform plugin (#25503)
## What

Ports the Relay `graphql` tagged template transform (babel-plugin-relay / swc_relay) as an individual napi transform, per #24914:

- **`crates/oxc_relay`** — the core transform as its own crate (modeled on `oxc_react_compiler`): replaces `graphql` tagged templates with references to relay-compiler artifacts. Definition names are extracted textually like `swc_relay` (equivalent to `\b(fragment|mutation|query|subscription)\s+(\w+)` with `#` comments stripped; hand-rolled scanner, no regex dependency).
- **`napi/transform-relay`** (`oxc-transform-relay`) — standalone napi package copied from the `napi/transform-react` template: parse → semantic → relay traverse → codegen. Only `graphql` tags are rewritten; TypeScript/JSX syntax is preserved untouched, so the output composes with any downstream toolchain.

## Options

| option | default | behavior |
|---|---|---|
| `artifactDirectory` | unset | when set, the import path is computed lexically relative to the transformed file (babel-plugin-relay `getRelativeImportPath` semantics — swc emits absolute paths instead); unset → `./__generated__/` next to the file |
| `language` | `javascript` | `typescript` imports `Name.graphql.ts`, otherwise `Name.graphql.js` |
| `eagerEsModules` | `true` | hoisted default imports (babel-plugin-relay ≥ v17 parity); `false` emits inline `require()` (`@swc/plugin-relay` / Next.js behavior) |

A `graphql` tag with no extractable definition name produces an error diagnostic (babel throws; swc silently skips).

Not supported, documented in both READMEs: dev-mode artifact hash validation, `jsModuleFormat: "haste"`, `isDevVariableName`, swc's Next.js-specific `projects`/`pagesDir`, and GraphQL document validation.

closes #24914

---

Implemented with Claude Code.
2026-08-13 13:56:01 +00:00
overlookmotel a4478e960a feat(codegen): add oxc-codegen package (#25488)
Add `oxc-codegen` package - a printer written in TS.

### Features

- Prints JS, JSX, TS, TSX.
- Matches `oxc_codegen` exactly on all Test262, TypeScript, Acorn-JSX fixtures.
- Very fast.

### Deficiencies

- Pretty-printing only (no compact/minified output).
- No support for printing comments.
- Source map support is semi-there, but largely untested, and poor API (design doc has some ideas on how to improve it).

### This PR adds

- The printer code.
- Conformance testing infra.
- Further tests for edge cases.
- README.
- Design doc - how it differs from `oxc_codegen` and why, what produces the perf.

### This PR doesn't add

- Not integrated into CI or release pipeline.

### Notes

This started as a slop port of `oxc_codegen`. I've iterated on that base, cleaned it up a lot, and at least skimmed through all of it. I think it's in fairly decent shape.

The design doc is I think worth a read. It explains the rationale for the choices, in particular the "1 codebase, 4 builds" approach.

I've put it in a new top-level directory called `packages`. It's not an app, so didn't seem to me to fit alongside `apps/oxlint` and `apps/oxfmt`. It's pure JS, so not like e.g. `napi/parser`. And it felt too heavyweight to put into `npm` dir. But maybe there's a better place for it.

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-12 13:41:31 +00:00
renovate[bot] b937e3e2f1 chore(deps): update napi (#25019)
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/) | Type |
Update |
|---|---|---|---|---|---|---|---|
| [@napi-rs/cli](https://napi.rs/)
([source](https://redirect.github.com/napi-rs/napi-rs)) | [`3.7.4` →
`3.8.2`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/3.7.4/3.8.2) |
![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/3.8.2?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/3.8.2?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/3.7.4/3.8.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/3.7.4/3.8.2?slim=true)
| pnpm.catalog.default | minor |
| [napi](https://redirect.github.com/napi-rs/napi-rs) | `3.11.0` →
`3.12.0` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi/3.12.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi/3.12.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi/3.11.0/3.12.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi/3.11.0/3.12.0?slim=true)
| workspace.dependencies | minor |
| [napi-build](https://redirect.github.com/napi-rs/napi-rs) | `2.3.2` →
`2.4.0` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi-build/2.4.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-build/2.4.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-build/2.3.2/2.4.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-build/2.3.2/2.4.0?slim=true)
| workspace.dependencies | minor |
| [napi-derive](https://redirect.github.com/napi-rs/napi-rs) | `3.6.0` →
`3.6.2` |
![age](https://developer.mend.io/api/mc/badges/age/crate/napi-derive/3.6.2?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/crate/napi-derive/3.6.2?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/crate/napi-derive/3.6.0/3.6.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/crate/napi-derive/3.6.0/3.6.2?slim=true)
| workspace.dependencies | patch |

---

### Release Notes

<details>
<summary>napi-rs/napi-rs (@&#8203;napi-rs/cli)</summary>

###
[`v3.8.2`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.1...@napi-rs/cli@3.8.2)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.1...@napi-rs/cli@3.8.2)

###
[`v3.8.1`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.0...@napi-rs/cli@3.8.1)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.8.0...@napi-rs/cli@3.8.1)

###
[`v3.8.0`](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.7.4...@napi-rs/cli@3.8.0)

[Compare
Source](https://redirect.github.com/napi-rs/napi-rs/compare/@napi-rs/cli@3.7.4...@napi-rs/cli@3.8.0)

</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.

👻 **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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-08-03 11:21:03 +01:00
Boshen 85d0f4dd1f feat(napi): add React Compiler transform binding (#24934)
Adds the `oxc-transform-react` N-API binding and its public CI and publish workflows.

AI-assisted.
2026-07-29 09:08:58 +00:00
leaysgur 862e0a4959 chore(oxfmt): Ignore generated files (#20723) 2026-03-25 05:46:02 +00:00
leaysgur ab446efc72 test(oxfmt): Update conformance to save each diff (#20170)
It's more efficient for both humans and AI to be able to see individual diffs.
2026-03-10 03:44:12 +00:00
overlookmotel fe3b32ee71 feat(linter/plugins): add oxlint-plugin-eslint package (#20009)
Closes #19746.

Add `oxlint-plugin-eslint` plugin which exports all ESLint's built-in rules as a JS plugin which can be used with Oxlint.

The code for rules is lazy-loaded on first use, so just using the plugin doesn't load the code for all the rules, only the ones which the user actually uses. However, the `meta` property of each rule is provided eagerly, so that `registerPlugin` in Oxlint can load the plugin without triggering the getters which lazy-load rule code.

All ESLint's rule code is bundled into this plugin package, so the package has no dependencies. This has a few advantages:

1. We control the version of ESLint which the rules are taken from.
2. Avoids "works on my machine" unreproducible bug reports due to differing ESLint versions.
3. Avoids relying on ESLint's `eslint/use-at-your-own-risk` export, which could change without warning.

At present, the plugin contains *all* ESLint's rules, including ones which are natively implemented in Oxlint.

We might choose to scale it back to include only the rules which Oxlint doesn't natively implement. But then we need to consider what happens when we implement more rules in future: Do they disappear from this package without warning? Would that be considered a breaking change? If it would, how long do we keep them in this package?

I propose that in the interests of getting this useful feature released without having to decide all these issues, we just go with it as is for now. JS plugins are not yet stable, so at present we can still make changes later on if we need to, without breaking any promises.
2026-03-09 17:22:40 +00:00
overlookmotel 03bce9f2fa refactor(estree/tokens): replace stored token when re-lexing (#19698)
Previously the ESTree tokens serializer had a special case to skip a `<<` token which has same start as preceding `<` token. Instead, solve this problem at source - prevent this duplicate token from being in the `Vec<Token>` in the first place, by modifying the parser.

This is important because we want to move to sending tokens to JS via raw transfer, and we need the `Vec<Token>` to have the right number of tokens in it to start with, so we can do lazy deserialization and just get a token at a specific index. This breaks down if there are extra tokens that need to be skipped.

The logic around this in parser is quite labyrinthine, so add lengthy comments explaining it.

This change also simplifies the main loop in ESTree serializer, so has side effect of +1% on `estree_tokens` benchmark. Conversely, it doesn't affect the `parser_tokens` benchmark perf, because the path in parser which got more complex is not commonly taken.
2026-02-25 19:18:38 +00:00
renovate[bot] a1b5d646ed chore(deps): update dependency oxfmt to ^0.32.0 (#19318)
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/) |
|---|---|---|---|---|---|
| [oxfmt](https://oxc.rs/docs/guide/usage/formatter)
([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxfmt))
| [`^0.31.0` →
`^0.32.0`](https://renovatebot.com/diffs/npm/oxfmt/0.31.0/0.32.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/oxfmt/0.32.0?slim=true)
|
![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxfmt/0.32.0?slim=true)
|
![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxfmt/0.31.0/0.32.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxfmt/0.31.0/0.32.0?slim=true)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
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:eyJjcmVhdGVkSW5WZXIiOiI0My44LjUiLCJ1cGRhdGVkSW5WZXIiOiI0My44LjUiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2026-02-16 10:35:25 +00:00
overlookmotel ce8bf1db80 refactor(tools): remove unnecessary ignore patterns from oxfmt config (#19070)
These ignores are no longer required since #18903.
2026-02-06 14:49:51 +00:00
overlookmotel d8055feb01 test(linter/plugins): test fixes and suggestions at very end of file (#19054)
Alter test fixtures for fixes and suggestions.

Remove trailing newline from end of fixture files, so that the last fix the plugin makes is at very end of file - makes sure fixes in this position still work.

Add checks to these tests and also the BOM test to catch if these fixture files accidentally get formatted, which would add a trailing newline and prevent the tests testing what they should do.
2026-02-06 12:57:05 +00:00
Boshen 4179e4f85a chore(editors): remove VS Code extension (moved to oxc-vscode repo) (#18982)
## Summary

- Removes `editors/vscode` directory - code has been moved to
https://github.com/nicholasrice/oxc-vscode
- Removes `tasks/vscode_docs` crate (no longer needed)
- Removes CI and release workflows for VS Code extension
- Updates `editors/README.md` to point to the new repository
- Cleans up references in `.gitignore`, `justfile`, `oxc_release.toml`,
`oxfmtrc.jsonc`, `oxlintrc.json`, and `pnpm-workspace.yaml`

closes #17484

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 21:14:03 +08:00
overlookmotel 9fd3bd6605 feat(linter/plugins): add @oxlint/plugins NPM package (#18824)
Alternative to #18796. Part of #18610.

## Overview

Add `@oxlint/plugins` package.

`@oxlint/plugins` package has no dependency on `oxlint`, which solves the problem raised in https://github.com/oxc-project/oxc/pull/18796#discussion_r2751286894, and is also what we wanted in the end anyway. We don't actually want plugins packages to have to depend on `oxlint`.

## Differences from other Oxc packages

This package is different from all our other packages, in that it's intended to work not only with Oxlint's ecosystem, but also with ESLint's ecosystem.

`@oxlint/plugins` will be a *runtime* dependency of plugin packages that the community create, and they may want their plugin to be compatible with both Oxlint and ESLint - this package provides the `eslintCompatPlugin` function for exactly this purpose.

Our aim is to allow plugin authors to migrate from ESLint's `create` API to Oxlint's `createOnce` API with minimum friction, and without breaking changes for their users:

1. Their plugin should remain compatible with ESLint.
2. They do not need to alter the versions of NodeJS they support (no change to `engines` field in `package.json`).
3. They can continue to publish their plugin as a CommonJS package, if that's the format they currently use.

## Package composition

Due to these requirements, the make-up of `@oxlint/plugins` is different from our other packages:

### Dual Format

This package is in "dual package" format, with both ESM and CommonJS entry points.

### Older NodeJS versions support

This package supports NodeJS versions back to v12.22.0.

https://github.com/oxc-project/oxc/blob/9938dc476f8533b7011af03cdbac328b0d00d344/npm/oxlint-plugins/package.json#L40-L42

This matches `engines` field in all ESLint 8.x.x releases:

* 8.0.0: https://www.npmjs.com/package/eslint/v/8.0.0?activeTab=code
* 8.57.1: https://www.npmjs.com/package/eslint/v/8.57.1?activeTab=code

Therefore, `@oxlint/plugins` can be used by any plugin which supports ESLint 8 or later.

Note: Download counts for ESLint 8 are still roughly equal to ESLint 9, even though v9 was released 2 years ago.

#### Notes

* Changing `target` in TSDown to `"node12"` does not result in any changes to built files. See 3rd commit in this PR.
* `exports` field in `package.json` is supported (without experimental flag) from NodeJS v12.17.0 + v14.0.0.
* `.cjs` file extension supported from NodeJS v12.0.0.

## Building the package

This PR adds 2 extra builds to TSDown config, which generate the files for the package. `build.ts` script moves the files into `npm/oxlint-plugins` directory.

Later on, we'll move the logic for moving the files into the CI release workflow, so we don't need to check the generated build files into Git.

## `@oxlint/plugins-dev`

In #18610 we decided to also add an `@oxlint/plugins-dev` to contain `RuleTester`, so we can move that out of `oxlint` package. This PR *does not* add that package. I've skipped that for now as (a) it's trickier and (b) it's much less important.
2026-02-03 15:46:17 +00:00
overlookmotel 9d37b63813 test(linter/plugins): prepare conformance test runner for testing multiple repos (#18461)
Restructure the conformance test runner to run the tests from multiple repos, rather than just ESLint.

Key changes:

* Details of each repo are stored in `test-groups.ts`, rather than logic spread across multiple files.
* Runner offers various hooks for mocking modules, mocking `RuleTester` instances, and registering custom parsers.
* Use `tsx` to run conformance tests, to support running tests in TypeScript files which NodeJS cannot run natively.
* Support older versions of ESLint's `RuleTester` where custom parsers were specified in config with file path instead of a parser object.
2026-01-23 18:58:57 +00:00
overlookmotel 8db0e78ae6 feat(linter/plugins): handle BOMs (#18376)
Closes #12526.

Handle BOM on start of files in the same way that ESLint does - do not include it in the source text on JS side, but `context.sourceCode.hasBOM` evaluates to `true`.

Method:

* Alter `program.source_text` to trim off the BOM before passing AST to JS side.
* Add a `has_bom` flag to `RawTransferMetadata`.
* Add ability to add an offset in the conversion from UTF-8 to UTF-16 spans.

The result is that the file as it's seen on JS side is as if the BOM didn't exist (except for the `hasBOM` flag). Spans are converted accordingly in JS-side AST, and converted back when passing diagnostics back to Rust.
2026-01-22 02:16:54 +00:00
Sysix 658c2f1f20 chore(vscode): format for vscode tests files (#17971) 2026-01-18 15:44:10 +00:00
Boshen 6fca2f7f60 chore(infra): use oxfmt for all files, remove dprint (#16599)
Toml formatting is missing but there's only a few toml files, can wait
for oxfmt plugins.

- [x] Something is slow, can't figure out why, need #16607
2025-12-15 12:06:24 +00:00
overlookmotel cb74fad70d test(linter/plugins): add conformance tests (#16650)
Add conformance tester for JS plugins.

The tester runs all of ESLint's test cases for all its built-in rules, but using Oxlint's `RuleTester` in place of ESLint's. i.e. the ESLint rules are run as Oxlint JS plugins.

It outputs the results in `snapshot.md` file.

Majority of the failing test cases are false positives. Later PRs will improve the conformance tester and `RuleTester` so it correctly handles `sourceType`, `jsx`, and TypeScript sources.

These tests do not run in CI. For now it's just useful for me to commit this, while I work on improving the tester.

I'm not sure if inside `apps/oxlint` is the right place for this ultimately, but for now I think it's passable.
2025-12-09 15:13:37 +00:00
Boshen 523a30a016 style(all): apply oxfmt default options (#16091)
Embrace the defaults!

---------

Co-authored-by: Yuji Sugiura <y.sugiura.0316@gmail.com>
2025-11-25 15:56:24 +09:00
overlookmotel 6ce62c51a8 style(linter/plugins): update oxfmt config to format oxlint fixtures (#15601)
Update `oxfmt` config so it formats `apps/oxlint/test/fixtures`.

Actual formatting changes were in PRs #15600 and #15674. This PR alters the config so all these files will continue to be formatted in future.
2025-11-13 15:11:57 +00:00
leaysgur a8e5181ab7 chore(infra): dogfooding oxfmt (#14979)
Fixes #14803

- Added `oxfmt` and `oxfmtrc.jsonc`
- Remove `dprint` plugin and useless ignore paths
- Apply `dprint` again
- Apply `oxfmt`
2025-10-28 01:16:46 +00:00