Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 19, 2025

When both JS-based plugins and the import plugin are enabled on large codebases (10k+ files), oxlint exhausts resources due to architectural conflicts between the two plugin types. Previously required users to manually run two separate lint passes.

Changes

Automatic pass detection and orchestration (apps/oxlint/src/lint.rs):

  • Detect when both use_cross_module (import plugin) and has_external_linter (JS plugins) are true
  • Replace error with automatic two-pass execution:
    • Pass 1: Native rules + import plugin + type-aware linting (external_linter = None)
    • Pass 2: JS plugins only (cross_module = false, type_aware = false)
  • Single DiagnosticService collects and merges results from both passes
  • Added run_two_pass_lint_impl static method to orchestrate passes without self-borrowing issues

Type exports (apps/oxlint/src/command/mod.rs):

  • Export FixOptions and InlineConfigOptions for internal two-pass implementation

Behavior

// Before: Error on 10k+ files with both plugins
if number_of_files > 10_000 && use_cross_module && has_external_linter {
    return CliRunResult::TooManyFilesWithImportAndJsPlugins;
}

// After: Automatic two-pass linting
if use_cross_module && has_external_linter {
    return Self::run_two_pass_lint_impl(...);
}

Users see combined diagnostics from both passes as a single lint run. Single-plugin configurations unchanged.

Remaining Work

  • Add tests for two-pass behavior and backward compatibility
  • Update CLI help and documentation
  • Verify resource improvements on large codebases
Original prompt

Implement automatic two-pass linting in oxlint when both JS-based plugins and the import plugin are enabled, as described in #15863 and the @copilot instructions.

Context from the maintainer's comment:

Required behavior:

  1. Detect when BOTH of the following are true for a given lint run:

    • JS plugins are enabled (via external_linter or equivalent configuration flag for JS-based plugins).
    • The import plugin is enabled (native import rules / plugin).
  2. In that case, perform linting in two internal passes instead of a single pass, without requiring user intervention:

    • First pass:
      • Run with JS plugins disabled.
      • Type-aware linting (tsgolint) should still run in this pass.
      • This pass should include import plugin and other native rules as in a normal run without JS plugins.
    • Second pass:
      • Run with only JS plugins.
      • That means:
        • Import plugin should be disabled.
        • Any other rules or behaviors that must not run concurrently with JS plugins for resource reasons should be disabled or adjusted according to current design.
  3. Implementation notes from the maintainer:

    • Implementing the 1st pass is straightforward: set external_linter to None (or the relevant configuration mechanism that disables JS plugins) while keeping the rest of the configuration the same.
    • For the 2nd pass, you must construct or adjust the configuration so that only JS plugins run.
    • Ensure type-aware linting (tsgolint) remains in the 1st pass.
  4. Design and implementation constraints:

    • Reuse as much of the existing lint pipeline as possible; avoid duplicating business logic.
    • The two passes should be internal to a single oxlint invocation from the user's perspective:
      • CLI flags, exit codes, and basic UX should remain intuitive and consistent with a single run.
      • Results from both passes should be merged so users see a single combined set of diagnostics.
    • Make sure diagnostics from both passes:
      • Are all reported (no loss between passes).
      • Have stable ordering (if ordering is observable today, preserve or document changes).
      • Correctly map to files and positions.
    • Performance & resource behavior:
      • The goal is to avoid the resource exhaustion seen on 10k+ file projects with both JS plugins and import plugin enabled.
      • If the repo already has resource guards or limits, ensure this new behavior integrates with them logically.
  5. CLI / configuration behavior:

    • The behavior should be opt-out or opt-in according to maintainer preference in the codebase (check existing patterns for new features):
      • If there is an existing config or CLI flag style (e.g. --no-split-js-import-passes or --split-js-import-passes), follow that pattern.
      • By default, when both JS plugins and import plugin are enabled, the automatic two-pass behavior should be active unless maintainers prefer an explicit flag.
    • Ensure that existing configs that only enable JS plugins OR only enable the import plugin behave exactly as before (no change in behavior or performance characteristics except potential refactoring side effects).
  6. Tests:

    • Add unit/integration tests that cover at minimum:
      • Only JS plugins enabled: single pass behavior unchanged.
      • Only import plugin enabled: single pass behavior unchanged.
      • Both JS plugins and import plugin enabled: two passes occur and diagnostics from both passes are present.
      • Type-aware linting (tsgolint) diagnostics appear only from the first pass and still work as expected.
      • Large project / many files scenario simulated via tests to ensure no resource exhaustion errors occur or that protective behavior is improved.
    • If there is an existing test harness for CLI or integration tests, use it; otherwise, add appropriate tests following existing patterns in oxc-project/oxc.
  7. Documentation:

    • Update any relevant documentation (CLI help, README, linting docs) to describe the new automatic two-pass behavior when both JS plugins and import plugin are enabled.
    • Clearly state that users no longer need to manually split their lint runs in this scenario, unless they wish to for fine-grained control.

Please:

  • Identify and modify the appropriate modules/files that configure and orchestrate lint passes, including where external_linter and the import plugin are wired into the runtime.
  • Implement the two-pass orchestration logic and configuration handling.
  • Add comprehensive automated tests per the above.
  • Update relevant documentation and help text.
  • Ope...

This pull request was created as a result of the following prompt from Copilot chat.

Implement automatic two-pass linting in oxlint when both JS-based plugins and the import plugin are enabled, as described in #15863 and the @copilot instructions.

Context from the maintainer's comment:

Required behavior:

  1. Detect when BOTH of the following are true for a given lint run:

    • JS plugins are enabled (via external_linter or equivalent configuration flag for JS-based plugins).
    • The import plugin is enabled (native import rules / plugin).
  2. In that case, perform linting in two internal passes instead of a single pass, without requiring user intervention:

    • First pass:
      • Run with JS plugins disabled.
      • Type-aware linting (tsgolint) should still run in this pass.
      • This pass should include import plugin and other native rules as in a normal run without JS plugins.
    • Second pass:
      • Run with only JS plugins.
      • That means:
        • Import plugin should be disabled.
        • Any other rules or behaviors that must not run concurrently with JS plugins for resource reasons should be disabled or adjusted according to current design.
  3. Implementation notes from the maintainer:

    • Implementing the 1st pass is straightforward: set external_linter to None (or the relevant configuration mechanism that disables JS plugins) while keeping the rest of the configuration the same.
    • For the 2nd pass, you must construct or adjust the configuration so that only JS plugins run.
    • Ensure type-aware linting (tsgolint) remains in the 1st pass.
  4. Design and implementation constraints:

    • Reuse as much of the existing lint pipeline as possible; avoid duplicating business logic.
    • The two passes should be internal to a single oxlint invocation from the user's perspective:
      • CLI flags, exit codes, and basic UX should remain intuitive and consistent with a single run.
      • Results from both passes should be merged so users see a single combined set of diagnostics.
    • Make sure diagnostics from both passes:
      • Are all reported (no loss between passes).
      • Have stable ordering (if ordering is observable today, preserve or document changes).
      • Correctly map to files and positions.
    • Performance & resource behavior:
      • The goal is to avoid the resource exhaustion seen on 10k+ file projects with both JS plugins and import plugin enabled.
      • If the repo already has resource guards or limits, ensure this new behavior integrates with them logically.
  5. CLI / configuration behavior:

    • The behavior should be opt-out or opt-in according to maintainer preference in the codebase (check existing patterns for new features):
      • If there is an existing config or CLI flag style (e.g. --no-split-js-import-passes or --split-js-import-passes), follow that pattern.
      • By default, when both JS plugins and import plugin are enabled, the automatic two-pass behavior should be active unless maintainers prefer an explicit flag.
    • Ensure that existing configs that only enable JS plugins OR only enable the import plugin behave exactly as before (no change in behavior or performance characteristics except potential refactoring side effects).
  6. Tests:

    • Add unit/integration tests that cover at minimum:
      • Only JS plugins enabled: single pass behavior unchanged.
      • Only import plugin enabled: single pass behavior unchanged.
      • Both JS plugins and import plugin enabled: two passes occur and diagnostics from both passes are present.
      • Type-aware linting (tsgolint) diagnostics appear only from the first pass and still work as expected.
      • Large project / many files scenario simulated via tests to ensure no resource exhaustion errors occur or that protective behavior is improved.
    • If there is an existing test harness for CLI or integration tests, use it; otherwise, add appropriate tests following existing patterns in oxc-project/oxc.
  7. Documentation:

    • Update any relevant documentation (CLI help, README, linting docs) to describe the new automatic two-pass behavior when both JS plugins and import plugin are enabled.
    • Clearly state that users no longer need to manually split their lint runs in this scenario, unless they wish to for fine-grained control.

Please:

  • Identify and modify the appropriate modules/files that configure and orchestrate lint passes, including where external_linter and the import plugin are wired into the runtime.
  • Implement the two-pass orchestration logic and configuration handling.
  • Add comprehensive automated tests per the above.
  • Update relevant documentation and help text.
  • Open a pull request with a clear title and description summarizing the change, rationale (resource exhaustion with large projects), and migration notes for users if any behavior differences exist.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 19, 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.

- Detect when both JS plugins and import plugin are enabled
- Automatically run two internal passes instead of failing
- First pass: native rules + import plugin + type-aware linting (no JS plugins)
- Second pass: only JS plugins (no native rules, no type-aware linting)
- Merge diagnostics from both passes into single output
- Export FixOptions and InlineConfigOptions for internal use

Co-authored-by: overlookmotel <[email protected]>
Copilot AI changed the title [WIP] Add automatic two-pass linting for oxlint with JS and import plugins Implement automatic two-pass linting when both JS plugins and import plugin are enabled Nov 19, 2025
Copilot AI requested a review from overlookmotel November 19, 2025 18:51
Copilot finished work on behalf of overlookmotel November 19, 2025 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants