Skip to content

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented Sep 20, 2025

Add createOnce method for rules. This is the "alternative API" mentioned in #9905 (comment).

export default {
  meta: { /* ... */ },
  // `createOnce`, not `create`. Called only once, NOT once per file.
  createOnce(context) {
    let classCount;
    return {
      before() {
        classCount = 0;
      },
      ClassDeclaration(klass) {
        classCount++;
      },
      after() {
        if (classCount > 5) {
          context.report({
            message: 'files should not contain more than 5 class declarations, '
              + `found ${classCount}`,
            node: { start: 0, end: 0 },
          });
        }
      },
    };
  }
};

If before method returns false, the rule is skipped for the current file. This is equivalent to the following pattern in ESLint:

export default {
  meta: { /* ... */ },
  create(context) {
    if (shouldSkip(context)) return {}; // Skip
    return { /* visitor */ };
  }
};

Currently we don't capitalize on the potential perf benefits of this alternative API, but plugin authors can use it now, and once we do implement the perf optimizations this API enables, they'll get a speed boost just by upgrading Oxlint, without needing to change their plugin code.

@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI C-enhancement Category - New feature or request labels Sep 20, 2025
Copy link
Member Author

overlookmotel commented Sep 20, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@overlookmotel overlookmotel marked this pull request as ready for review September 20, 2025 11:13
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_estree-compatible_ast_for_js_plugins branch from 55771c4 to dc47cc3 Compare September 21, 2025 10:03
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch 2 times, most recently from 988eab7 to 710d205 Compare September 21, 2025 10:06
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_estree-compatible_ast_for_js_plugins branch 2 times, most recently from 234a600 to a089a79 Compare September 21, 2025 10:31
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch 2 times, most recently from a0a8490 to d903879 Compare September 21, 2025 15:00
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_estree-compatible_ast_for_js_plugins branch from a089a79 to 16f54cc Compare September 21, 2025 15:00
Copy link
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@overlookmotel i haven't added the merge tag on these two because there are prs lower in the stack that're assigned to you.

but both of these look ok to me to merge

@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_estree-compatible_ast_for_js_plugins branch from 16f54cc to df37940 Compare September 22, 2025 11:00
@overlookmotel overlookmotel force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch from d903879 to 6934416 Compare September 22, 2025 11:00
@overlookmotel overlookmotel added the 0-merge Merge with Graphite Merge Queue label Sep 22, 2025
Copy link
Member Author

overlookmotel commented Sep 22, 2025

Merge activity

  • Sep 22, 11:08 AM UTC: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Sep 22, 11:28 AM UTC: overlookmotel added this pull request to the Graphite merge queue.
  • Sep 22, 11:29 AM UTC: The Graphite merge queue couldn't merge this PR because it was not satisfying all requirements (Failed CI: 'Test NAPI').
  • Sep 22, 11:32 AM UTC: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Sep 22, 11:36 AM UTC: overlookmotel added this pull request to the Graphite merge queue.
  • Sep 22, 11:36 AM UTC: Merged by the Graphite merge queue.

@graphite-app graphite-app bot changed the base branch from 09-20-feat_linter_estree-compatible_ast_for_js_plugins to graphite-base/13944 September 22, 2025 11:16
@graphite-app graphite-app bot force-pushed the graphite-base/13944 branch from df37940 to bef8753 Compare September 22, 2025 11:22
@graphite-app graphite-app bot force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch from 6934416 to bf0fe86 Compare September 22, 2025 11:22
@graphite-app graphite-app bot changed the base branch from graphite-base/13944 to main September 22, 2025 11:23
@graphite-app graphite-app bot force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch from bf0fe86 to 1dabd2d Compare September 22, 2025 11:23
Add `createOnce` method for rules. This is the "alternative API" mentioned in #9905 (comment).

```js
export default {
  meta: { /* ... */ },
  // `createOnce`, not `create`. Called only once, NOT once per file.
  createOnce(context) {
    let classCount;
    return {
      before() {
        classCount = 0;
      },
      ClassDeclaration(klass) {
        classCount++;
      },
      after() {
        if (classCount > 5) {
          context.report({
            message: 'files should not contain more than 5 class declarations, '
              + `found ${classCount}`,
            node: { start: 0, end: 0 },
          });
        }
      },
    };
  }
};
```

If `before` method returns `false`, the rule is skipped for the current file. This is equivalent to the following pattern in ESLint:

```js
export default {
  meta: { /* ... */ },
  create(context) {
    if (shouldSkip(context)) return {}; // Skip
    return { /* visitor */ };
  }
};
```

Currently we don't capitalize on the potential perf benefits of this alternative API, but plugin authors can use it now, and once we do implement the perf optimizations this API enables, they'll get a speed boost just by upgrading Oxlint, without needing to change their plugin code.
Copilot AI review requested due to automatic review settings September 22, 2025 11:28
@graphite-app graphite-app bot force-pushed the 09-20-feat_linter_plugins_add_createonce_api branch from 1dabd2d to 2dc8adb Compare September 22, 2025 11:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Sep 22, 2025
@overlookmotel overlookmotel added the 0-merge Merge with Graphite Merge Queue label Sep 22, 2025
@graphite-app graphite-app bot merged commit 2dc8adb into main Sep 22, 2025
30 of 31 checks passed
@graphite-app graphite-app bot deleted the 09-20-feat_linter_plugins_add_createonce_api branch September 22, 2025 11:36
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Sep 22, 2025
camc314 added a commit that referenced this pull request Sep 23, 2025
## [1.17.0] - 2025-09-23

### 🚀 Features

- f47f978 linter/plugins: Add `definePlugin` API (#14008)
(overlookmotel)
- 3e117c6 linter/plugins: Add `defineRule` API (#13945) (overlookmotel)
- 2dc8adb linter/plugins: Add `createOnce` API (#13944) (overlookmotel)
- bef8753 linter/plugins: ESTree-compatible AST for JS plugins (#13942)
(overlookmotel)
- 55c2e11 editor: Add `oxc.fmt.experimental` flag (#13923) (Sysix)
- a21ff54 language_server: Introduce `ServerFormatter` (#13700) (Sysix)
- a14aa79 npm/oxlint: Convert to ES modules (#13876) (Boshen)
- 15eb326 linter: Add `vue/no-required-prop-with-default` rule (#13613)
(yefan)
- 5d3ba00 linter: Add `vue/require-typed-ref` rule (#13857) (yefan)
- b52389a node: Bump `engines` field to require Node.js 20.19.0+ for ESM
support (#13879) (Copilot)
- 8221a01 linter: Add `eslint/no-misleading-character-class` (#13365)
(Sysix)
- c75ae8c linter/plugins: Add options to `Context` (#13810)
(overlookmotel)
- 53d04dd linter: Convert `oxlint` to NAPI app (#13723) (overlookmotel)

### 🐛 Bug Fixes

- 1f4be38 napi/parser: Generate `.d.mts` extension for types (#14038)
(Daniel Roe)
- a018756 linter/plugins: Pin `tsdown` dependency to 0.15.1 (#14005)
(overlookmotel)
- b8790c2 language_server: Output correct position for parser & semantic
errors (#14010) (Sysix)
- 4d3c6e1 linter: Support let-chains in codegen node type detection
(#14006) (camc314)
- a34918a linter/plugins: Avoid lint warnings compiling WASM or
big-endian (#13968) (overlookmotel)
- 27022ab linter/switch-case-braces: Add support for string including
colon on case expression (#13687) (Lukinoh)
- dd3843f linter: Set package version in `package.json` (#13890)
(overlookmotel)
- fa866b3 linter: Sort optimized/unoptimized diagnostics before
comparison (#13850) (camc314)
- fac7624 linter/plugins: Improve error for no JS plugins (#13858)
(overlookmotel)

### 🚜 Refactor

- bb040bc parser, linter: Replace `.mjs` files with `.js` (#14045)
(overlookmotel)
- b353750 linter/plugins: Remove unnecessary `Serialize` derives
(#14031) (overlookmotel)
- 0d48511 linter/plugins: Improve handling `Context` method calls in
`createOnce` (#14032) (overlookmotel)
- 36ac0fb language_server: Don't create `mpsc` channel (#14011) (Sysix)
- 2e9ae3f linter: Make disable directives own the rule name (#13987)
(camc314)
- 6bc7664 oxlint: Run oxlint before tsgolint (#13519) (camc314)
- 0c93f33 language_server: Use minimal text edit for `ServerFormatter`
(#13960) (Sysix)
- 823cb57 langauge_server: Move `Backend` into own file (#13955) (Sysix)
- dc700f5 language_server: Introduce `LSPFileSystem` (#13731) (Sysix)
- 42e2c1d linter: Remove `Rc` from `DisableDirectives` (#13924)
(camc314)
- ac3e9e9 napi/parser: Move JS code into `src-js` directory (#13899)
(overlookmotel)
- e90bfe3 linter: Remove double reference in unicorn/error-message
(#13916) (camc314)
- 83791a0 linter: Remove double reference in vue/jsx-no-undef (#13915)
(camc314)
- ebd22de linter: Remove double reference in vue/require-typed-ref
(#13914) (camc314)
- 873e231 language_server: Move `needs_linter_restart` to `ServerLinter`
(#13834) (Sysix)
- 7e0d736 linter/plugins: Rename `--experimental-js-plugins` to
`--js-plugins` (#13860) (overlookmotel)
- 6245c8c linter/plugins: Make `Context` properties getters (#13809)
(overlookmotel)
- a2342a6 linter/plugins: Import named in tests (#13807) (overlookmotel)

### 📚 Documentation

- 601c876 linter: Add comment explaining why Mimalloc is feature-gated
(#14037) (overlookmotel)

### ⚡ Performance

- 4d04c6e linter/plugins: Flatten `LintFileResult` fields (#14033)
(overlookmotel)
- 06363e0 linter: Add node type codegen support for `match node.kind()`
(#13736) (camchenry)
- a79af0a linter: Replace `for (... of ...)` loops (#13913)
(overlookmotel)
- b53292d linter: Use unstable sort where possible (#13818) (sapphi-red)

### 🎨 Styling

- 8083740 linter: Import `Serialize` at top level (#14030)
(overlookmotel)

### 🧪 Testing

- b807b6f language_server: Skip formatter test on windows (#13986)
(Sysix)
- 2600858 language_server: Add Tester for ServerFormatter (#13969)
(Sysix)
- 37aadf0 language_server: Add `test_and_snapshot_multiple_file`
(#13966) (Sysix)
- ad14a41 editor: Fix test setup (#13929) (Sysix)
- f51240e linter/plugins: Tests for different import styles (#13859)
(overlookmotel)
- 407c95e linter/plugins: Check `this` is undefined in visit functions
(#13811) (overlookmotel)
- f023a22 linter/plugins: Include stack trace in plugin loading errors
(#13808) (overlookmotel)

### 💼 Other

- 0630d68 linter: Build `oxlint` locally with Mimalloc in release mode
(#14034) (overlookmotel)

Co-authored-by: camc314 <18101008+camc314@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants