Commit Graph

160 Commits

Author SHA1 Message Date
camc314 4004c101ca fix(linter/eslint/no-irregular-whitespace): check comments by default (#25660)
## Summary

- align the skipComments default with ESLint
- report irregular whitespace in line and block comments by default
- preserve the skipComments: true opt-out
- verify suppressed comment diagnostics count disable directives as used
- regenerate the published configuration schema

Fixes #25616.
2026-08-14 12:59:55 +00:00
leemr 9771ee151c test(linter): give the prune test its own suppression fixture directory (#25445)
`test_suppressing_errors_update_the_file_when_errors_are_decreased` and
`test_prunning_errors_update_the_file_when_errors_are_decreased` both
point at `fixtures/suppression/with_arg_and_decreased_errors`. Every
other `SuppressionTester` fixture has a single owner. Both of these run
oxlint in that directory, which rewrites `oxlint-suppressions.json`, and
both then delete it and restore it from the backup in `Drop`.

It showed up as an intermittent red in `just ready` while I was working
on something unrelated, and it cost enough re-runs that I went looking.
I flagged it at the end of #25412. This is that fix.

Measured with `cargo test -p oxlint suppress`, ten runs per setting, on
an 18 core machine:

```
--test-threads   failures
1                0/10
12               0/10
16               0/10
17               0/10
18               3/10
20               0/10
24               0/10
```

18 is `hw.ncpu` there, and it is what `cargo test` picks by default. 20
and 24 are more parallel and never failed, so this is not load and it is
not machine speed. The two tests have to land in the same dispatch wave,
which depends on the divisor. The `Test Linux` job runs `cargo test
--all-features` and stays green, which I read as a different core count
rather than anything about the runner.

Three distinct failure modes came out of the one shared directory:

```
tester.rs:249   one test's opening assert runs while the other sits
                between remove_file and fs::copy
tester.rs:295   both Drop calls delete the same path, and the second gets ENOENT
tester.rs:274   one test reads the file while the other is inside a truncating write
```

Before settling on the fixture split I checked whether repairing `Drop`
would be enough, since deleting before copying is what opens the widest
window. It is not enough. Guarding the delete with `&&
!self.have_backup_file`, so the file is never absent, left the rate
where it was and only changed the message:

```
Drop shape                   directory   failures
delete then copy, as today   shared      3/20
copy only                    shared      4/40
unchanged                    separate    0/40
```

To find out what the reader was actually getting in that third mode, I
patched the panic at `tester.rs:274` to print the observed content. That
patch was throwaway and is not in this diff:

```
PROBE observed len=0 serde=EOF while parsing a value at line 1 column 0 first80=""
```

Length zero, not a torn file. `SuppressionFile::save` uses `fs::write`,
which is `File::create` plus `write_all`, and `File::create` opens with
`O_TRUNC`. The truncate commits at open time and the bytes arrive on the
next syscall, so the file is briefly empty. A separate directory is the
only change that closes both that window and the `Drop` one.

Calling out one thing up front: the new directory is a byte for byte
copy of the old one. `--suppress-all` and `--prune-suppressions`
converge in the decreased case, so the expected content is the same for
both tests. The directory exists for isolation, not for content.
`with_arg_and_increased_errors` and
`with_arg_and_increased_errors_prune` are the same split for the case
where the two commands diverge, so five of six files match there and six
of six match here.

This is the same shape as #20717, where `--init` writes leaked across
parallel tests.

With the change in, the suppression module is 0/20 at 18 threads and
0/10 at the default. The rest of `just ready` is green as well: `typos`,
`cargo lintgen`, `just fmt`, `just check`, `just test`, `just lint`,
`just doc` and `just ast`, with 4446 tests passing under
`--test-threads=1`.

Three other suppression fixtures have more than one owner, and I left
all three alone. `fixed_violations_are_reported` has two readers.
`type_check_only_with_regular_rule` also has two, and although the
second passes `--suppress-all` and `--prune-suppressions`, `lint.rs:426`
rejects that combination before any lint runs, so nothing writes.
`diagnostics_filtered_if_count_is_the_same` is the only other one where
a write really happens, so it carries the truncating write window in
principle, but that window is a single `fs::write` over a few hundred
bytes, where the one this PR fixes spanned a whole `Drop`
delete-then-copy plus the other test's entire run. Forty runs with those
two tests forced to overlap found nothing. I did not want to change
something I cannot show is broken. Happy to fold it in if the whole
class should close in one go.

Disclosure, per CONTRIBUTING.md: I used Claude for the investigation and
for the patch. I have reviewed and tested all of it myself.
2026-08-12 10:18:27 +01:00
leaysgur e81b2ff6c5 fix(oxlint,oxfmt): report error for invalid glob patterns (#24744)
Fixes #24612

- Update `fast-glob` to `1.1.0` which exposes `validate()` api
- Use it in `oxc_config`, apps will be validated through `deserialize`
- Oxfmt supports globs for CLI paths, also validated
2026-07-21 04:43:49 +00:00
Stephen Zhou df67932e6d fix(linter): skip suppression validation with --type-check-only (#24462)
## Summary

- skip bulk suppression finalization in `--type-check-only` mode
- reject `--suppress-all` and `--prune-suppressions` when combined with
`--type-check-only`
- add a CLI regression fixture for a still-valid regular lint
suppression

## Root cause

`--type-check-only` intentionally skips regular lint rules, but bulk
suppression finalization still compared the full baseline against the
partial runtime rule map. A file processed by type checking was marked
as seen without regular rule counts, so valid regular suppressions were
interpreted as stale.

Suppression update operations are also unsafe with this partial result
because they could remove or replace entries for rules that did not run.

## Validation

- `just ready` with Node.js 24.14.0
- verified the original Dify single-file reproduction with both regular
lint and `--type-check-only`

## AI usage

I used OpenAI Codex to help investigate, implement, test, and prepare
this pull request. I reviewed the changes and take responsibility for
the submission.

Fixes #24460

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-13 14:49:11 +01:00
camc314 e6d5cfe503 test(oxlint): remove redundant ignore pattern CLI test (#24353)
## Summary

- remove the platform-dependent CLI snapshot test for parent-directory ignore patterns
- remove the dedicated CLI fixtures and snapshot
- rely on the existing `oxc_config` unit tests for pattern semantics and the existing `ConfigStoreBuilder` test for Oxlint integration
2026-07-10 09:50:52 +00:00
leaysgur 83378351e4 fix(linter): error on ignorePatterns that cannot match files aoutside the config directory (#24341)
Follow up on #24339

- Added the same guard as Oxfmt
- Since they are identical, I moved them into `oxc_config` so they can be shared
2026-07-10 09:05:48 +00:00
leaysgur 2ce5a33ecc fix(linter): resolve ignorePatterns relative to the config dir (#24339)
Fixes #24310

Root config's `ignorePatterns` are now resolved relative to the directory containing the config file, instead of CWD.

Also fixes a latent issue: a `--config <path>` containing `..` silently disabled all `ignorePatterns` (the unnormalized parent dir never prefix-matches lint target paths). Explicit config paths are now lexically normalized, same as Oxfmt.

### Behavior change

The new anchoring applies in all cases, including `--config` / LSP `configPath`. This intentionally differs from ESLint, which resolves alternate-config ignore patterns relative to CWD:

- `extends`, `overrides[].files`, and JS plugin specifiers are already config-file-relative, including via `--config`
  - rooting only `ignorePatterns` at CWD would give one file two coordinate systems
- Wrappers like Vite+ pass `--config <workspace-root config>` as an implementation detail while CWD stays at the invocation directory, so "`--config` means CWD-relative" does not hold in practice
  - #24276

Impact should be small: bare names (`dist`, `*.min.js`) and `**/`-prefixed patterns are unaffected by the anchor.

The updated `config_ignore_patterns/with_oxlintrc` snapshot shows the `--config` case.
2026-07-10 08:39:56 +00:00
camc314 1599f111b6 fix(linter): align lsp extends default plugins (#22788)
Fixes #22758.

The LSP path was not materializing the default plugin set before resolving a root config with `extends`, while the CLI path already did that before building the config. That meant a child config launched as the LSP workspace root could extend a parent config with an explicit `plugins` array and accidentally lose default plugins like `typescript`, even though `oxlint` CLI and `--print-config` showed those plugins as active.

This moves the default-plugin materialization into a shared helper used by both CLI and LSP config loading, so both paths resolve the same effective root config before `extends` are applied.

I added a regression fixture for the reported nested config shape and snapshot coverage for the missing TypeScript diagnostic.
2026-05-28 19:37:30 +00:00
camc314 52bd016237 fix(linter): respect allow unused disable directives in LSP (#22715)
Fixes #22713

This updates the LSP handling for `unusedDisableDirectives: "allow"` so it disables unused directive reporting instead of producing warning diagnostics and remove-directive code actions.

The behavior now matches the CLI path: only `warn` and `deny` enable unused-disable reporting, while `allow`/`off` are treated as disabled.

Added an LSP snapshot regression test covering the `"allow"` case.
2026-05-25 12:42:28 +00:00
Daniel Osmond 41fcdcf5fa fix(linter): Fix rule count not including override rules (#19898)
A fix for issue #19891

---------

Co-authored-by: Cam McHenry <camchenry@users.noreply.github.com>
2026-05-12 10:13:00 -04:00
Sysix 6b50f23ac4 fix(oxlint/cli): load root config by searching up parent directories (#22272)
Allow users to run `oxlint` in a sub package, when the monorepo has a base config.

Example:
`cd project/packages/pack-a && oxlint`

Now it detects the config from `project/.oxlintrc.json`, aligning how the LSP side works.
Aligns too how oxfmt searches config path.

closes https://github.com/oxc-project/oxc/issues/21533
found in https://github.com/voidzero-dev/vite-plus/pull/1378#discussion_r3078146663
2026-05-11 08:09:18 +00:00
Sysix 080d90ed6a fix(linter): move no-debugger fix to suggestion (#22256)
`console.log` and `debugger;` are utils while developing.
`console.log` is already a suggestion (aligned with ESLint), but `no-debugger` would be autofixed too.
ESLint does not have a fixer for his rule, but we do.

This is a part of #22195, where do not autofix suggestions on the editor side, aligning with ESLint.
`debugger;` should not be autofixed on save.
2026-05-09 10:20:33 +00:00
Said Atrahouch cf86d7ab44 feat(linter): bulk suppression (#19328)
# AI Disclosure

I have used AI to:

* Fix all my grammar mistakes in this PR description, as English isn't
my first language.
* Iterate on some ideas that I had during development, for example
whether it is better to modify the concurrent hash map or send diffs
through a channel.

Apart from these situations, the code has been written without AI
assistance. As mentioned in my first PR in Oxlint, these contributions
help improve Oxlint while at the same time helping me improve my Rust
skills.

# Description

This PR implements `bulk-suppressions` for Oxlint. I had in mind the
goals mentioned in
[https://github.com/oxc-project/oxc/issues/10549#issuecomment-3102429390](https://github.com/oxc-project/oxc/issues/10549#issuecomment-3102429390)

# Implementation details

It is split into sections with all the decisions that I have taken to
implement this PR.

## Suppression Manager

The code is located in `crates/oxc_linter/src/suppression/mod.rs` and it
is split into three files:

* `tracking.rs`: Contains all the code that handles the loading, saving,
and updating of `oxlint-suppressions.json`.
* `mod.rs`: Implements the `SuppressionManager`. It also acts as a
middleman between `oxlint` and `tsgolint` and `tracking` to update the
information, and `diff` to execute the diff operations.
* `diff.rs`: Hides all the complexity of how the diff works from the
rest of the project.

## Filtering Diagnostics

The Suppression Manager only filters diagnostics, that have a valid
`OxcCode`, otherwise the message is ignored as we can't scope it to a
rule or plugin.

The messages are only filtered if the new count is lower or equal than
the registered one; otherwise, they are displayed. Same behavior as
ESLint.

## Sharing and updating the data

Oxlint uses `rayon::scope` to create as many workers as there are
available threads. Those workers do the heavy linting work, and this is
the data that I need for filtering or creating the file.

The semantics of `Send + Sync` in Rust make it hard, for good reason, to
share information between threads. So the quick approach is for each
worker to read the whole file just to pick a subset of the data. On top
of that, the feature is probably more oriented toward medium/large
projects, so this approach doesn't scale.

So the implemented approach is the following:

* `SuppressionManager` ~~duplicates the data into a `concurrent hash
map`. This map is safe to be shared between threads and is only used in
read mode.~~ **Update:** The data is wrapped in a `Arc` instead of
duplicating it. It reduces a level of indirection. Thanks @wagenet for
the suggestion.
* Each worker holds a reference to a `DiffManager`, this struct contains
all data necessary for his operations.
* The file is linted. The errors emitted by the lint are used to track
the number of detected errors.
* `DiffManager` calculate a diff based on the args provided and if
`bulk-suppressions` file exists:
* If we have diffs and no CLI args are provided, then the diffs are
converted to `OxcDiagnostic` to be reported.
* If we have diffs and at least one of the CLI args is provided, then
the diffs are sent to the parent through a channel.

Once the linting is completed and we are back in the main thread, we
consume the channel with the diffs sent by the workers. If we are in
`update` or `create` mode and no diffs have been emitted, then we do
nothing. Otherwise, we mutate the map in the `SuppressionManager` with
the operations sent by the workers and save it.

In a few words, I'm trading memory usage for what is, in my opinion, a
simpler process. The option that I discarded was relying on `interior
mutability`, but that would mean ensuring that all operations are safe
and that no worker panics.

## TSGo lint errors are the only recorded errors.

Rather than completely changing how fixable and non-fixable errors are
emitted, I have attached to the existing flow. Type errors and related
errors are ignored and not recorded.

## CLI Args

Currently, both commands update the file, no matter the diff found. The
only situation that doesn't work the same is when the file
`oxlint-suppressions.json` does not exist. The only way to create it is
by running `oxlint --suppress-all`.

# Comments

* ~130 files from this PR are file in the fixtures folders.
* The current state of the PR handle lint errors emited by Oxlint,
JSPlugin and TSGO.
* All suppression test fixtures are self contained in the `suppression`
folder.
* Only the Default Output is rendered if the file has been created or
updated.
* ~~`--fix` or related commands do not update the file.~~ **UPDATE**:
The fix commands are handle.
* I have manually tested the feature in
[PostHog](https://github.com/PostHog/posthog) and in
https://github.com/TheAlexLichter/oxlint-react-compiler-rules
* Added a `SuppressionTest` that implements `Drop` to handle the cleanup
of this tests.
* Thanks @Sysix for you manually test in Windows, and mentioned how to
run the test in Windows using the CI.
* Windows CI are green
https://github.com/oxc-project/oxc/actions/runs/22840798852.


PostHog
<img width="790" height="155" alt="imagen"
src="https://github.com/user-attachments/assets/fe16b2a6-e98a-492f-a9c5-dd92d57c2091"
/>

Oxlint React Compiler Rules
<img width="1297" height="757" alt="imagen"
src="https://github.com/user-attachments/assets/fc9ac9b1-bb08-4ff8-825b-ca91d107f4dc"
/>

# Fixes

*
[https://github.com/oxc-project/oxc/issues/10549](https://github.com/oxc-project/oxc/issues/10549)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cam McHenry <camchenry@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
Co-authored-by: Copilot <copilot@github.com>
2026-05-05 22:58:39 -04:00
Sysix fd9510ec29 chore(oxlint/lsp): respect RuleCustomization.autofix for "fix all" code actions (#21781)
> ## Pull request overview

> Updates the oxlint LSP “fix all” / “fix all dangerous” code actions to respect `rulesCustomization.<rule>.autofix = false`, so rules opted out of autofix aren’t included in fix-all edits.
2026-05-05 09:48:14 +00:00
Sysix 692bab9457 chore(oxlint/lsp): respect RuleCustomization.severity for lsp diagnostics (#21757)
> ## Pull request overview

> This PR updates the oxlint LSP pipeline so that per-rule `rulesCustomization.severity` can override the severity of emitted LSP diagnostics (and suppress diagnostics entirely when set to `off`),
2026-05-05 09:37:25 +00:00
Sysix 8b4829b04d feat(linter): split no-negated-condition rule to unicorn & eslint (#21998)
>## Pull request overview

> Splits the previously shared `no-negated-condition` implementation into distinct `eslint/no-negated-condition` and `unicorn/no-negated-condition` rules while reusing a shared implementation module, and removes the now-unneeded unicorn↔eslint aliasing in config and rule-status tooling.

Question: Should we support `unicorn/no-named-default`? Because it is marked as not supported because it is already implemented in `import/no-named-default`.
See unicorn issue: https://github.com/oxc-project/oxc/issues/684
2026-05-01 08:12:27 +00:00
mustafa0x aace797941 fix(linter): detect Svelte TS and module scripts correctly (#20819)
## Summary
- parse Svelte <script> attributes instead of broad substring checks
- detect both module and context="module" scripts when creating partial
JS sources
- add unit and CLI coverage for module/instance scripts in both JS and
TS

## Validation
- mise x -- cargo test -p oxlint lint_svelte_
- mise x -- cargo test -p oxc_linter partial_loader::svelte

## AI usage disclosure
This PR was prepared with AI assistance (Codex). I reviewed and take
responsibility for the final changes.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-04-27 10:39:04 +01:00
Sysix 8c638c505e refactor(linter): move valid-title rule to shared and crate own rule for vitest (#18467) 2026-04-25 16:23:55 +00:00
Christian Vuerings 348f46cfc1 feat(linter): add respectEslintDisableDirectives option (#21384)
## Summary
- add a root-only `options.respectEslintDisableDirectives` config option
- make directive parsing and `reportUnusedDisableDirectives` honor that
switch
- preserve current behavior by default with `true`
- regenerate the schema / generated TS config types and add CLI + unit
coverage

## Proposal
Use a boolean option to control whether oxlint recognizes ESLint-style
disable directives:

```json
{
  "options": {
    "respectEslintDisableDirectives": false
  }
}
```

Behavior:
- unset or `true`: oxlint recognizes both `oxlint-*` and `eslint-*`
- `false`: oxlint only recognizes `oxlint-*`

This also applies to `reportUnusedDisableDirectives`.

## Notes
- unused-directive diagnostics now report the actual matched prefix
(`oxlint-disable` vs `eslint-disable`) instead of always saying
`eslint-disable`
- the option is root-only, consistent with the other global `options.*`
switches in the config loader

closes https://github.com/oxc-project/oxc/pull/20447
fixes https://github.com/oxc-project/oxc/issues/20375

---------

Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-04-23 13:30:47 +01:00
camc314 ae4531269f feat(linter): introduce --type-check-only flag (#21184) 2026-04-08 17:20:40 +00:00
bab af8e12202a fix(linter): render each config error as a separate diagnostic (#21120)
closes https://github.com/oxc-project/oxc/issues/21094

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-04-08 16:45:19 +01:00
camc314 7354f3cd64 feat(linter)!: error on no matched files (#21144) 2026-04-07 21:10:31 +00:00
camc314 5ed854fc02 test(linter): typecheck files even when zero rules are enabled (#21117)
not sure we had test coverage here previously, but it's important this case doesn't regress
2026-04-07 10:22:51 +00:00
bab 7a7b7b8d2e feat(oxlint/lsp): add source.fixAllDangerous.oxc code action kind (#20526)
wip

Fixes #20523

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-04-05 21:43:58 +01:00
Sysix 21133291cf test(oxlint): add test for nested config with cwd (#21050)
Added a test to show the bug in https://github.com/oxc-project/oxc/issues/21030 and https://github.com/oxc-project/oxc/issues/20904,
2026-04-05 11:49:55 +00:00
camc314 0b84de1c1a feat(oxlint): support allow option for prefer-promise-reject-errors (#20934)
Add the TypeScript rule config surface for the new `allow` specifier option and extend the oxlint CLI fixture to verify the option end to end.

Tested with:
- `cargo test -p oxc_linter prefer_promise_reject_errors -- --nocapture`
- `cargo test -p oxlint test_tsgolint_rule_options -- --nocapture`
- `node --run fmt`

AI usage disclosure: Codex was used to implement the config support, add the CLI fixture coverage, and prepare this PR. The changes were reviewed in the local workspace before submission.
2026-04-01 14:50:20 +00:00
renovate 382a469337 chore(deps): update dependency oxlint-tsgolint to v0.18.0 (#20798)
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/) |
|---|---|---|---|---|---|
| [oxlint-tsgolint](https://redirect.github.com/oxc-project/tsgolint) | [`0.17.4` → `0.18.0`](https://renovatebot.com/diffs/npm/oxlint-tsgolint/0.17.4/0.18.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint-tsgolint/0.18.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint-tsgolint/0.18.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint-tsgolint/0.17.4/0.18.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint-tsgolint/0.17.4/0.18.0?slim=true) |

---

### Release Notes

<details>
<summary>oxc-project/tsgolint (oxlint-tsgolint)</summary>

### [`v0.18.0`](https://redirect.github.com/oxc-project/tsgolint/releases/tag/v0.18.0)

[Compare Source](https://redirect.github.com/oxc-project/tsgolint/compare/v0.17.4...v0.18.0)

#### What's Changed

- fix(lint): suppress unparam on toStaticValue by [@&#8203;camc314](https://redirect.github.com/camc314) in [#&#8203;834](https://redirect.github.com/oxc-project/tsgolint/pull/834)
- fix(promise-function-async): place async fix after export modifiers by [@&#8203;camc314](https://redirect.github.com/camc314) in [#&#8203;839](https://redirect.github.com/oxc-project/tsgolint/pull/839)
- chore: improve assertion diagnostic msg by [@&#8203;camc314](https://redirect.github.com/camc314) in [#&#8203;842](https://redirect.github.com/oxc-project/tsgolint/pull/842)
- fix(dot-notation): ignore non-ascii property names by [@&#8203;camc314](https://redirect.github.com/camc314) in [#&#8203;840](https://redirect.github.com/oxc-project/tsgolint/pull/840)
- chore: update typescript-go submodule by [@&#8203;camc314](https://redirect.github.com/camc314) in [#&#8203;841](https://redirect.github.com/oxc-project/tsgolint/pull/841)

**Full Changelog**: <https://github.com/oxc-project/tsgolint/compare/v0.17.4...v0.18.0>

</details>

---

### Configuration

📅 **Schedule**: 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.

🔕 **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:eyJjcmVhdGVkSW5WZXIiOiI0My45My4wIiwidXBkYXRlZEluVmVyIjoiNDMuOTMuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
2026-03-27 13:27:56 +00:00
camc314 c0ebbce18c feat(linter)!: report error on unknown builtin rule (#20464) 2026-03-25 21:47:06 +00:00
camc314 0c57312607 fix(tsgolint): use primary span for the disable directive (#20436)
fixes https://github.com/oxc-project/tsgolint/issues/769
2026-03-16 19:52:22 +00:00
Sysix 42aff158ee perf(oxlint/lsp): avoid computing diagnostics for non invoked code actions requests (#20080)
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeActionTriggerKind

> 	/**
	 * Code actions were explicitly requested by the user or by an extension.
	 */
	export const Invoked: 1 = 1;
	/**
	 * Code actions were requested automatically.
	 *
	 * This typically happens when current selection in a file changes, but can
	 * also be triggered when file content changes.
	 */
	export const Automatic: 2 = 2;

---

> ## Pull request overview
> This PR optimizes the oxlint LSP server by avoiding unnecessary linting when code action requests are triggered automatically (e.g., on cursor move or file open) rather than explicitly invoked by the user. Previously, `get_code_actions_for_uri` would always run the linter if no cached actions existed; now it only does so when `trigger_kind` is `INVOKED`.

@nrayburn-tech When your code action from file explorer does not work anymore, you can blame this PR 😅
VSCode sends "automatic" for most of the time, only when opening the code action pop over it will send "invoked". At this time we already should have diagnostics because. Most triggers of code actions are diagnostics.
2026-03-09 13:26:38 +00:00
Sysix 065a358c90 test(oxlint): move non lsp fixtures to fixtures/cli (#20044)
Now there are only two folders in `apps/oxlint/fixtures`.
We can later create another directory for both integrations (like config walker).
2026-03-06 12:12:54 +00:00
Scott S. 2488a688f6 feat(linter): add .oxlintrc.jsonc config file support (#19870)
## Summary

- Teach config discovery to recognize `.oxlintrc.jsonc` alongside
`.oxlintrc.json`
- JSONC parsing already works via `json_strip_comments::strip()` in
`Oxlintrc::from_file()`, so this is purely a filename discovery change
- Prefer `.json` over `.jsonc` when both exist in the same directory
(matches oxfmt behavior)
   - Add `.oxlintrc.jsonc` to LSP file watch patterns
- Update CLI help text, error messages, and diagnostic notes to mention
`.jsonc`

   ## Changes

   | File | Change |
   |------|--------|
| `apps/oxlint/src/lib.rs` | Add `DEFAULT_JSONC_OXLINTRC_NAME` constant
|
| `apps/oxlint/src/config_loader.rs` | Update discovery functions
(`find_configs_in_directory`, `to_discovered_config`,
`try_load_config_from_dir`, `load_many`) + add tests |
| `apps/oxlint/src/lsp/server_linter.rs` | Add `.jsonc` to watch
patterns and extended path filter + update tests |
   | `apps/oxlint/src/command/lint.rs` | Update CLI help text |
   | `apps/oxlint/src/lint.rs` | Update fallback error message |

   ## Test plan

   - [x] `cargo check -p oxlint` — compiles cleanly
- [x] `cargo test -p oxlint -- test_jsonc_config_discovery` — new test:
`.oxlintrc.jsonc` is discovered and loaded
- [x] `cargo test -p oxlint -- test_json_preferred_over_jsonc` — new
test: `.json` preferred when both exist
- [x] `cargo test -p oxlint -- test_watchers` — all 10 watcher tests
pass with updated pattern counts

   Closes #19729

---------

Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-03-03 17:15:40 +00:00
Peter Wagenet 61bf3883fd feat(linter): add options.reportUnusedDisableDirectives to config file (#19799)
See #15972.

## Summary

- Adds `options.reportUnusedDisableDirectives` to `.oxlintrc.json`,
following the same pattern as `typeAware` (#19614) and `typeCheck`
(#19764)
- Root-config-only — nested configs are rejected with a clear diagnostic
error
- CLI `--report-unused-disable-directives` /
`--report-unused-disable-directives-severity` take precedence over the
config file value when both are set
- Schema (`npm/oxlint/configuration_schema.json`), TypeScript types
(`config.generated.ts`), and website snapshots regenerated

## Test plan

- [ ] Unit tests in `oxlintrc.rs`: deserialization, `is_empty`, `merge`
- [ ] Unit tests in `config_store.rs`: accessor returns value / `None`
by default
- [ ] Unit tests in `config_loader.rs`: nested config rejection
- [ ] Integration tests in `config_builder.rs`: `extends` inheritance
and override precedence
- [ ] `cargo test -p oxc_linter && cargo test -p oxlint`

## Note on AI usage

This PR was implemented with Claude Code assistance and has been
reviewed and tested by the contributor.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wagenet <9835+wagenet@users.noreply.github.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-03-03 13:17:50 +00:00
camc314 0337c6dc1f feat(linter): implement typescript/no-unecessary-type-conversion (#19955) 2026-03-03 09:20:08 +00:00
camc314 2919313574 feat(linter): introduce denyWarnings config options (#19926) 2026-03-02 13:25:43 +00:00
camc314 a60711957e feat(linter): introduce maxWarnings config option (#19777) 2026-03-02 12:26:56 +00:00
camc314 f34f6fad28 feat(linter): introduce typeCheck config option (#19764) 2026-02-26 14:54:51 +00:00
camc314 694be7d211 feat(linter): introduce typeAware as config options (#19614) 2026-02-25 11:55:54 +00:00
connorshea 7958b56cdb fix(linter): Fix syntax error reporting in some output formatters. (#19590)
Add snapshot tests for all the formatters with this case to make sure we don't regress on this for any of them in the future.

Basically, we were being overly aggressive in the stripping of the rule ID from the message, which caused messages with colons in them (e.g. parser errors like `Expected `;` but found `:``) to be truncated to just the character after the first colon.

We don't actually need to do this anymore, as the `diagnostic.to_string()` method doesn't include the rule ID (if it ever did), so we can just use the full string as the message without any additional parsing.

Generated with Claude Code.

Fixes https://github.com/oxc-project/oxc/issues/19588.
2026-02-21 12:14:18 +00:00
camc314 50fc70d1a6 fix(linter/type-aware): use correct span for disable directives (#19576)
fixes https://github.com/oxc-project/oxc/issues/19575
2026-02-20 15:55:08 +00:00
camc314 82ca5c3dfa feat(linter): add typescript/dot-notation rule (#19442) 2026-02-19 17:26:46 +00:00
camc314 735d0e4b2d feat(linter): implement typescript/no-useless-default-assignment (#19488) 2026-02-17 13:15:26 +00:00
camc314 31c3a930ab feat(linter): add typescript/no-unnecessary-type-parameters rule (#19450) 2026-02-16 20:09:56 +00:00
camc314 c94809068d feat(linter): add typescript/consistent-return rule (#19449) 2026-02-16 20:09:56 +00:00
camc314 9f87df0b7e feat(linter): add typescript/prefer-string-starts-ends-with rule (#19448) 2026-02-16 19:37:01 +00:00
camc314 04536be729 feat(linter): add typescript/prefer-regexp-exec rule (#19447) 2026-02-16 19:37:00 +00:00
camc314 56a7feb22f feat(linter): add typescript/prefer-readonly rule (#19446) 2026-02-16 19:37:00 +00:00
camc314 a1cea63070 feat(linter): add typescript/no-unnecessary-qualifier rule (#19445) 2026-02-16 19:37:00 +00:00
camc314 e3144d223a feat(linter): add typescript/prefer-find rule (#19444) 2026-02-16 19:36:59 +00:00
camc314 13c7408d03 feat(linter): add typescript/prefer-readonly-parameter-types rule (#19443) 2026-02-16 19:28:18 +00:00