Commit Graph

40 Commits

Author SHA1 Message Date
Sysix 8af5703b56 chore(oxlint/generate-config-types): remove unneeded DummyRule tsType mapping (#26206)
With the major update in https://github.com/oxc-project/oxc/pull/26193, this code does not do anything.
Removing it.
2026-08-31 19:28:43 +00:00
Boshen 1193c9dbaf chore(oxfmt): dogfood operator position at line start (#25937)
dogfood
2026-08-20 14:36:47 +00:00
Sysix b1b83d5b9f refactor(linter): remove second | undefined from DummyRuleMap ts generation (#23684) 2026-06-21 13:54:06 +00:00
Sysix 0338b49476 refactor(linter): use strictIndexSignatures when generating TS config (#23521)
This PR enables `strictIndexSignatures` option when generating `oxlint` config type declarations, allowing us to implement rule config schemas where the generation would produce a TS error.
See https://github.com/oxc-project/oxc/issues/23299 for the problem.

The generated code now appends `undefined` for some rule config options.

The docs of the option:

```
    /**
     * Append all index signatures with `| undefined` so that they are strictly typed.
     *
     * This is required to be compatible with `strictNullChecks`.
     */
    strictIndexSignatures: boolean;
```
2026-06-17 10:02:46 +00:00
Sysix 008fa41609 feat(linter): add schema for eslint/no-constant-condition (#22991)
The generator changes was written by AI and reviewed on my side.
2026-06-07 15:28:26 +00:00
Sysix 545493f25d feat(linter): add schema for eslint/complexity (#22960)
The `apps/oxlint/scripts/generate-config-types.ts` was generated by AI 🤖
2026-06-07 14:40:26 +00:00
camc314 d0211b0fd2 fix(linter): allow undefined in DummyRuleMap index (#22626)
fixes #22624
2026-05-20 15:49:58 +00:00
camc314 f26e6abde0 fix(linter): make generate-plugin-eslint script work on windows (#20246) 2026-03-12 09:11:06 +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
connorshea 6ea49a04fb docs(linter): Fix some identation issues for the generated types used in oxlint.config.ts. (#19942)
I think we may want to consider alternatively calling oxfmt in order to do this, rather than a bespoke solution here? That would also fix the formatting of typescript code blocks.

Right now, this also doesn't handle `jsonc` code blocks.

But for now, good enough.

Without this fix, the editor suggestions have docs like this:

<img width="976" height="441" alt="Screenshot 2026-03-02 at 8 46 34 PM" src="https://github.com/user-attachments/assets/243af8fb-a7d4-4954-a272-51dadfb9e488" />

AI Disclosure: Changeset generated by Claude Code.
2026-03-03 12:57:59 +00:00
overlookmotel 018277937e build(oxlint): generate npm/oxlint-plugins in release CI workflow (#18903)
#18824 added `@oxlint/plugins` package. The files in `npm/oxlint-plugins` were generated by the build script `apps/oxlint/scripts/build.ts`.

Instead, populate `npm/oxlint-plugins` in the release CI workflow, just before the package is published.
2026-02-04 12:40:27 +00:00
overlookmotel e52005e6fc build(oxlint): simplify building @oxlint/plugins (#18902)
Follow-on after #18824. Refactor only.

Simplify building `@oxlint/plugins` package. Generate both the ESM and CommonJS builds in the same directory.
2026-02-04 09:24:46 +00: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
Boshen 9788a96639 feat(oxlint,oxfmt): add more native builds (#18853)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 00:18:54 +08:00
camc314 da32203a60 feat(linter): auto generate oxlint.config.ts types (#18597) 2026-02-01 23:50:25 +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 5877752586 ci(lint): enable no-console rule (#16053)
Enable `no-console` rule in our linting setup. Add `oxlint-disable` comments where we do want to log (in scripts).
2025-11-24 12:06:00 +00:00
overlookmotel 80fe39d696 build(linter/plugins): build either release or debug version, not both (#15949)
#15921 added a debug build for Oxlint, and various PRs since have tweaked it. However, I now realize there's little point in generating *both* a release build and debug build.

Just create one build, and use env var `DEBUG` to control whether it has debug assertions included in it or not.

`pnpm run build` produces release build with no debug assertions, `pnpm run build-test` includes the asserts. I've verified that both do what they're meant to.
2025-11-23 12:11:29 +00:00
overlookmotel 8b3fd1ca9a build(linter/plugins): simplify TSDown config (#15948)
#15946 means we can now simplify the TSDown build config.

Previously we had to have 2 separate builds for `index.ts` and `cli.ts`, to avoid `assert*` functions ending up in a shared chunk, and not getting removed by minifier. Now that problem is solved, so we can switch to a single build with 2 entry points.

TSDown does create a small extra chunk for its `__toESM` and `__commonJSMin` functions, but I think that's fine.

Annoyingly it doesn't seem to be possible to tell TSDown to generate `.d.ts` files only for the `index.js` chunk, so have to delete this pointless files in build script.

The point of all this is that `RuleTester` needs to use a ton of code from `plugins.ts`, and we wouldn't want all that code duplicated in both `index` and `plugins` chunks (especially once we're bundling TS-ESlint's parser #15861). Now that code will be shared between the two entry points in a shared chunk, not duplicated.
2025-11-21 16:18:19 +00:00
overlookmotel 22e132d255 refactor(linter/plugins): shorten build script (#15943)
Pure refactor. Just tidy up the build script a little.
2025-11-21 14:05:32 +00:00
overlookmotel 325af3273b test(linter/plugins): debug build for tests (#15921)
Generate a debug build, in addition to the normal release build.

In the debug build, `DEBUG` global is defined as `true` and `assertIsNonNull` does a runtime assertion. In release build, `DEBUG === false` and minifier removes debug-only code.

Run the tests in debug mode.

Debug build is generated in a separate directory from `dist`, so is *not* included in NPM package.
2025-11-21 13:40:31 +00:00
overlookmotel a409c16374 refactor(linter/plugins): shorten build script (#15874)
Pure refactor. Just shorten the code in build script.
2025-11-19 13:35:29 +00:00
overlookmotel fa1780a25c refactor(linter/plugins): bundle deserializer (#15873)
Bundle the deserializer. Originally it wasn't bundled at my request, so that source maps wouldn't be required for debugging. But it's turning out that we have no problems in the deserializer - our problems are elsewhere!
2025-11-19 13:35:28 +00:00
camc314 4719a616e9 refactor(oxlint): move build script to typescript (#15648) 2025-11-12 21:53:14 +00:00
overlookmotel f279f0b4a6 refactor(linter/plugins): do not lazy-load visitor keys (#14431)
Previously we lazy-loaded visitor keys file, because it would be rarely used. But it's required for selectors DSL, so statically import it, and include it in bundle.

Also, import it as a TS file, since it's valid TS, even without type annotations.
2025-10-07 23:35:31 +00:00
overlookmotel 52f35c6dcd refactor(napi/parser, linter/plugins): rename types.js to type_ids.js (#14384)
Pure refactor. Just rename generated `types.js` files to `type_ids.js`. This name better describes what the files contain, and it avoids naming clash with `types.d.ts` in `apps/oxlint/src-js/generated`.
2025-10-06 18:55:15 +00:00
overlookmotel c8eeeb5d78 refactor(linter/plugins): remove build-time dependency on napi/parser (#14374)
Refactor. Previously build script for `oxlint` package copied files from `napi/parser`. Remove this dependency, by instead making `oxc_ast_tools` generate the files in `apps/oxlint/src-js/generated`, and then copy the files from there to `dist/generated` in the build script.

This ends up with the same result, but divorces `oxlint` package from `oxc-parser`, which is cleaner.
2025-10-06 12:08:07 +00:00
overlookmotel fb1a067637 refactor(linter/plugins): bundle walker and AST types map (#14373)
Refactor. Include generated files `types.js` and `walk.js` in bundle, instead of externalizing them. It's only the deserializer code that we want to keep unbundled to make it easier to debug without source maps. `types.js` and `walk.js` aren't too complicated.
2025-10-06 12:08:06 +00:00
overlookmotel a2914fe8d8 feat(linter/plugins): add loc field getter to all AST nodes (#14355)
Add `loc` to all AST nodes.

`loc` is computed lazily, as it's quite an expensive operation - because it requires searching the source text for line breaks and building a translation table.

We can consider making `loc` a "real" property once we have a faster translation table built on Rust side.
2025-10-05 14:02:12 +00:00
overlookmotel 93d81641b2 refactor(linter/plugins): export AST types direct from oxlint package (#14353)
Export AST types directly from `oxlint` package, instead of depending on `@oxc-project/types`. This enables altering the types to reflect that `range` field is always present on AST node in Oxlint's AST (#14354).
2025-10-05 13:47:32 +00:00
overlookmotel c8de6fe9cf feat(linter/plugins): add parent field to AST nodes (#14345)
Use the new raw transfer deserializer added in #14344 to add `parent` field to all AST node in Oxlint JS plugins.
2025-10-05 00:32:09 +00:00
overlookmotel e75d42d509 perf(napi/parser, linter/plugins): remove runtime preserveParens option from raw transfer deserializers (#14338)
We had a runtime `preserveParens` option in deserializers to cater for linter, but it was not used in parser. Convert it to a compile-time option instead.
2025-10-04 17:03:33 +00:00
overlookmotel 5505a86121 feat(linter/plugins): include range field in AST (#14321)
Add `range` field to AST nodes, using the support for `range` in raw transfer added in #14319.

Use `range` field rather than `start` + `end` in nodes passed to `context.report` and fixer methods - for closer alignment with ESLint.
2025-10-04 15:47:47 +00:00
overlookmotel 2f8c985393 feat(linter/plugins): implement SourceCode#visitorKeys property (#14289)
Add support for obtaining visitor keys for AST via `context.sourceCode.visitorKeys`.
2025-10-02 08:32:04 +00:00
overlookmotel bb040bc2d5 refactor(parser, linter): replace .mjs files with .js (#14045)
Now that `apps/oxlint` and `napi/parser` are both ESM packages (#13723 and #14042), we can use `.js` file extensions for all ESM files, rather than the mix of `.js` and `.mjs` file we had previously.

It's less confusing having to remember what's `.js` and what's `.mjs`, and avoids ugly workarounds like #14038 (`.d.mts`??).
2025-09-23 14:47:40 +00:00
Daniel Roe 1f4be382a8 fix(napi/parser): generate .d.mts extension for types (#14038)
the latest version of `oxc-parser` (on npm) does not have resolvable
types because the entry is `.mjs` and the types are `.d.ts` (these need
to match - `.d.mts`). you can see this in the failing CI for [this
renovate
PR](https://github.com/nuxt/nuxt/actions/runs/17940186619/job/51014702361?pr=33290)
but I'm happy to provide a more minimal reproduction if it helps

I also spotted that `napi/parser/test/visit.test.ts` was importing
`visitorKeys` which was not exported from the corresponding declaration,
so took the liberty to add that export as well.

let me know if this needs any changes 🙏 

I hope it helps

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2025-09-23 11:53:20 +01:00
overlookmotel bef875343e feat(linter/plugins): ESTree-compatible AST for JS plugins (#13942)
Use eager deserialization instead of lazy deserialization in linter plugins, so AST custom rules receive is ESTree-compatible.

Unfortunately this reduces performance significantly, but we'll bring back lazy deserialization later on once we have it producing an ESTree-compatible AST.
2025-09-22 11:16:33 +00:00
Boshen a14aa79850 feat(npm/oxlint): convert to ES modules (#13876)
## Summary
- Convert npm/oxlint package to ES modules by setting `"type": "module"` in package.json

## Test plan
- [ ] Verify CLI binaries continue to work correctly
- [ ] Test package installation and execution
- [ ] Run existing test suites
- [ ] Confirm language server binary still functions

🤖 Generated with [Claude Code](https://claude.ai/code)
2025-09-20 08:43:24 +00:00
overlookmotel ac3e9e966a refactor(napi/parser): move JS code into src-js directory (#13899)
Pure refactor. Root of `napi/parser` was getting really crowded with tons of files, and I'm about to add a load more for the ESTree walker.

Move JS source files into a `src-js` directory, like in `apps/oxlint`, so that the root of the package is just config files and scripts.
2025-09-19 08:46:42 +00:00
overlookmotel 53d04dd1dc feat(linter): convert oxlint to NAPI app (#13723)
Convert `oxlint` to a NAPI package.

This PR:

1. Moves files from `napi/oxlint` into `apps/oxlint`.
2. Converts `oxlint` into a NAPI package.
3. Alters the [release workflow](https://github.com/oxc-project/oxc/pull/13723/files#diff-80cb497c859bbaf7756da6ced2bca3d31933affc96102983eee1ad7d4bcc60fd) and [script](https://github.com/oxc-project/oxc/pull/13723/files#diff-4c4b7045c68805aeeae7c0af94cf7cf7487cb0403496da974a6a23accdc457d0) for building `oxlint` packages.

Most of necessary code modifications and refactoring was done in previous PRs (#13701, #13712, #13722, #13745), so this PR only includes changes necessary for packaging as NAPI.

I've done my best to update release workflow, but am mostly "flying blind" without ability to test it, so very likely there are mistakes.

A few notes and oddities:

* I've kept the `oxlint` NPM package as CommonJS. We could probably switch to ESM, but I thought it better to minimize the changes in this PR.
* NAPI-RS creates `.node` files named with a `-msvc` postfix for Windows. The scripts here remove that postfix so that filename of `.node` files and NPM package names match for all platforms, for simplicity.
* `tasks/website` has a dependency on `oxlint` as a normal library. This resulted in linker errors, so have had to put all the NAPI stuff behind `napi` cargo feature. Tests for `tasks/website` are run separately in CI, to avoid feature unification turning on the `napi` feature for `website`.

I've made a few comments below for the parts which aren't fairly self-explanatory.
2025-09-17 09:20:21 +00:00