Closes#22131
## Summary
- normalize `oxlint-plugin-*` names the same way as existing
`eslint-plugin-*` names
- keep Rust `normalize_plugin_name` and JS `normalizePluginName`
behavior in sync
- reject `oxlint-plugin-*` aliases as non-normalized plugin names
- add JS plugin fixtures for package-name, `meta.name`, and scoped
package normalization
## AI Assistance
This PR was prepared with AI assistance. I reviewed the generated
changes and test results, and I am responsible for the contribution.
Co-authored-by: xiaokhkh <10765730+xiaokhkh@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
Fixes#21805.
This was generated with Claude Code and reviewed/tested by me. The first
commit is the change to the code, the second is all the snapshots that
needed to be updated.
Before:
```
x eslint-plugin-jest(no-restricted-jest-methods): Use of `advanceTimersByTime` is not allowed
,-[test.js:7:6]
6 | it('calls the callback after 1 second via advanceTimersByTime', () => {
7 | vi.advanceTimersByTime(1000);
: ^^^^^^^^^^^^^^^^^^^
8 | })
`----
```
After:
```
x jest(no-restricted-jest-methods): Use of `advanceTimersByTime` is not allowed
,-[test.js:7:6]
6 | it('calls the callback after 1 second via advanceTimersByTime', () => {
7 | vi.advanceTimersByTime(1000);
: ^^^^^^^^^^^^^^^^^^^
8 | })
`----
```
Note that I need to confirm whether this change will be a problem for
the LSP integrations (I don't think it will?), as well as any other
tooling we have. I am pretty confident that oxlint-migrate won't care,
and neither should vite-plus - except maybe with integration/snapshot
tests in vite-plus.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cameron Clark <cameron.clark@hey.com>
As we prepare for alpha release of JS plugins, it feels like we can remove the warning logged to stderr.
```
WARNING: JS plugins are experimental and not subject to semver.
Breaking changes are possible while JS plugins support is under development.
```
They do still remain experimental, but I don't think we need to shout that quite as loudly now.
This ensures that we print the expected number of rules for users that are using JS Plugins.
Fix#17519.
Based on #17517, because otherwise we'd end up with weird snapshot differences when trying to merge these anyway.
AI Disclosure: The fix here was generated with Copilot + GitHub's Raptor mini model.
For a while, we've been skipping the printing of rule runs unless `--disable-nested-config` was passed. This was a result of the nested_configs value including the base config (see #16356). When we were checking whether that value was empty, it would always have at least 1 item (unless nested configs were entirely disabled).
As part of this, I've updated some configs in the fixtures to disable correctness rules, otherwise we will end up with a bunch of fixture snapshots needing updates every time a new default rule is added.
It's probably easiest to review this one commit at a time.
Fixes#14557.
Split full rule names into plugin name + rule name on *last* slash instead of first slash, if rule name starts with `@`.
e.g. `@tanstack/query/exhaustive-deps`:
* Plugin name: `@tanstack/query`
* Rule name: `exhaustive-deps`
The PR only affects parsing rule names in configs. I'm leaving dealing with `// oxlint-disable @tanstack/query/exhaustive-deps` to a later PR.
A couple of changes to how plugin names are dealt with:
### Package names
Don't use package name if the specifier used to load the plugin is a relative path.
If your project is called `super-server`, and you load a plugin from `../plugins/no-foo.js`, that plugin shouldn't be called `super-server` - that's the name of the project, not the plugin.
Now it throws an error, telling you to give the plugin a name.
### Ensure `context.id` matches the plugin name
Previously `context.id` might not match the actual plugin name (it could include e.g. `eslint-plugin-` prefix, for example). Now it always matches.
This required re-implementing `normalize_plugin_name` on JS side too.
### Tests
Add a bunch of tests for every combination I could imagine of `plugin.meta.name`, package name, and alias. Those tests make sure `context.id` is same as the plugin name on Rust side.
### Incomplete
There's 2 things remaining to get naming completely correct:
1. Support plugin names with slashes in them e.g. `@scope/eslint-plugin-name` (#14557).
2. It's possible for the same plugin to have different names in different places, because you can alias the same plugin twice with different names in a config, and an override. Plugin names (in `context.id`, and in `// oxlint-disable` comments) should reflect the plugin name *as it is in the config which enabled that rule*.
I'm leaving those 2 for now.