Commit Graph

12 Commits

Author SHA1 Message Date
overlookmotel 9de9385fd1 refactor(linter/plugins): rename oxlint/plugin to oxlint/plugins (#18792)
Part of #18610.

Our intent is to move `definePlugin`, `defineRule`, and `eslintCompatPlugin` to a separate package `@oxlint/plugins` (plural to avoid confusion with naming convention for plugins `oxlint-plugin-xxx`).

So rename the current entry point which exports these functions from `oxlint/plugin` to `oxlint/plugins` (plural).
2026-02-01 13:23:14 +00:00
overlookmotel 88f30e0b4a feat(linter/plugins): move eslint compatible plugin conversion to eslintCompatPlugin function (#18791)
Closes #18611.

Previously `definePlugin` and `defineRule` were doing double duty:

1. Providing type safety (standard `defineConfig` pattern).
2. Converting a plugin/rule to be ESLint compatible

Combining the two duties is probably confusing to users. Users are familiar with the `defineConfig` pattern and these functions generally don't do anything at runtime - just require a specific type as param and return the input untouched.

This PR adds a separate function `eslintCompatPlugin` which does the conversion to an ESLint-compatible plugin.

`definePlugin` and `defineRule` are now no-ops at runtime - they just pass through the plugin/rule unchanged.
2026-02-01 12:37:48 +00:00
camc314 81eb6fa9db refactor(linter): split entry points for custom plugins/config/types (#18601)
This is technically breaking (only for types), but custom plugins are experimental.

The ruletester/defineRule/definePlugin are re-exported but with a `@deprecated` tag which I think is a good enough trade off

I want to avoid users bringing in a ton of custom plugin code when doing `import { defineConfig } from 'oxlint'`
2026-01-27 00:58:08 +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 690abec235 test(linter/plugins): use subpath imports (#15920)
Shorten imports in test fixtures using [subpath imports](https://nodejs.org/docs/latest-v24.x/api/packages.html#subpath-imports).

Before:

```ts
import type { Plugin } from '../../../dist/index.js';
```

After:

```ts
import type { Plugin } from '#oxlint';
```
2025-11-21 11:44:25 +00:00
overlookmotel def251dee0 test(linter/plugins): remove unused imports from fixtures (#15655)
Pure refactor to tests. These imports are no longer used. Remove them.
2025-11-12 23:49:48 +00:00
overlookmotel 075079cc9c test(linter/plugins): improve reliability of replacing paths in output (#15424)
When replacing absolute paths in fixture snapshots, replace paths anywhere in the output, rather than only in certain specified patterns.

Additionally, introduce `<fixtures>` and `<fixture>` replacements to shorten paths in snapshots.

```diff
- File path: <root>/apps/oxlint/test/fixtures/fixture_name/files/1.js
+ File path: <fixture>/files/1.js
- File path: <root>/apps/oxlint/test/fixtures
+ File path: <fixtures>
```

This allows removing the `relativePath` helper function from some test plugins, outputting paths (e.g. `cwd`) anywhere, and generally will avoid problems with snapshots being system-dependent, and dependent on directory layout of fixtures.

Also, amend ESLint `stdout` output in snapshots to align all rule names, to reduce churn in snapshots, and avoid mismatches between local and CI (presumably due to differences in terminal width).

```diff
- filename: <fixture>/files/1.js                              define-plugin-plugin/create-once
- filename: <fixture>/files/long_filename.js                              define-plugin-plugin/create-once
- filename: <fixture>/files/very_long_filename.js                              define-plugin-plugin/create-once
+ filename: <fixture>/files/1.js                                 define-plugin-plugin/create-once
+ filename: <fixture>/files/long_filename.js                     define-plugin-plugin/create-once
+ filename: <fixture>/files/very_long_filename.js                define-plugin-plugin/create-once
```
2025-11-07 12:28:48 +00:00
overlookmotel 96663fbaab fix(linter/plugins): do not call before hook if empty visitor (#14401)
If rule is defined using `createOnce`, and it returns an empty visitor (`before` / `after` hooks only), then don't run the hooks - the rule is a no-op.

Reason this is important is forward-compatibility with an optimization we could make where we calculate on Rust side whether AST contains any nodes that rules act on, and if it doesn't, skip calling into JS entirely. In that case, the `before` hook wouldn't run on those files.

We can't emulate that behavior entirely, but we can at least avoid users creating rules which *only* contain a `before` hook, and then finding that when we apply that optimization later on, it stops behaving as expected.

i.e. we make the `before` hook never be called for a rule defined like this:

```js
export default {
  createOnce(context) {
    return {
      before() {
        if (content.filename.endsWith('.tsx') {
          context.report({ message: 'No TSX!', node: context.sourceCode.ast });
        }
      },
    };
  },
};
```
2025-10-07 09:43:21 +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 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 1387aaa495 test(linter/plugins): test createOnce returning no visitor functions (#14279)
Add a test to make sure `createOnce` can return an object with only `before` and `after` hooks (no visitor functions) and that both hooks are called for each file in this case.
2025-10-01 14:38:31 +00:00
overlookmotel acd1266d60 feat(linter/plugins): oxlint export types (#14163)
`oxlint` package export TS types. `defineRule` and `definePlugin` now give you type-safety and intellisense.

Writing plugins in TS is only supported on versions of NodeJS which support type-stripping. Have not added a library (e.g. Jiti) to support older NodeJS versions.

Probably some of the types are wrong. But I think this is a decent start.

"Are the types wrong" (added in #14177) is reporting an error in `index.d.ts`:

```ts
import { VisitorObject as Visitor } from "../dist/generated/visit/visitor.js";
//                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

because the file in `dist/generated/visit` is actually called `visitor.d.ts` (`.d.ts`, not `.js`).

I'm not sure if that's a mistake in Rolldown's bundling, "Are the types wrong" being too strict, or a genuine problem.

But regardless, TS seems to pick up the types from `visitor.d.ts`, so I think we can probably merge this and look into / fix it later.
2025-09-28 14:59:48 +00:00