feat: Consider bulk suppressions when running Lint via the Node.js API
Summary
This RFC proposes integrating bulk suppressions support into the Node.js API via the ESLint and LegacyESLint classes, specifically focusing on considering existing bulk suppressions when linting files or text through the API. This change ensures that suppression files (eslint-suppressions.json) created via CLI commands are automatically respected when using the programmatic API, maintaining consistency between CLI and API behavior.
The scope is limited to applying existing suppressions during linting and does not include suppression file manipulation features (such as --suppress-all, --suppress-rule, or --prune-suppressions), which remain CLI-exclusive functionalities.
Related Issues
- https://github.com/eslint/eslint/issues/19603
The committers listed above are authorized under a signed CLA.
- :white_check_mark: login: sushichan044 / name: Kentaro Suzuki (40473fd3ba2991c20222505c167d8516aa5cd3f9, f63e63ff66c01b922ac8379b0e60701f7055031c, bc82f31a850218f6ef9cca3b00ac7fa9889b2cb6, fa25623767c24c22f0aafd4bae2236103111e728, 8b6e9734a1b02b128d751449bf335bf968f8fe3f, 00ba3e9e6c7d9dc232908841b6c056a7c8ce4601, c5b4134d87d0250bdbcf0298e848834c992881f5)
Specific code examples for LegacyESLint are WIP, but will be added soon.
@sushichan044 please take a moment to sign the CLA (see first comment).
@nzakas Thank you! I am very busy right now, so my reply will be delayed until around next Monday.
@sushichan044 no problem, thanks for letting us know.
I noticed this RFC specifically mentions this is not for exposing a bulk suppressions file creation method for the API.
As a contributor/maintainer of xo we would be interested in having an API method exposed to generate the bulk suppressions file as well. I'm sure other ESLint wrappers would appreciate that in the future too.
- Ideally with an option to give the file a custom name.
- Perhaps could just expose the suppression service or the suppress method.
@spence-s that's out of scope for this RFC. Please open a separate issue to discuss.
@sushichan044 it looks like the remaining work here it to ensure the functionality works the same as with the CLI. Are you still working on that point?
The fact that suppressions are only applied to the CLI is actually a really big feature for me. I want to see the violations in the IDE, but not have them cause my CI to fail. The only change I'd like is the ability for my IDE to show suppressed violations in a different color. Hiding suppressed violations in the IDE would be a regression for me.
I would definitely agree with @wagenet on this. Having suppressions show in IDE is a big improvement IMO over disables. This allows lints to be started, suppressed and team members to know this is a work item.
Having IDEs and other tools being able to distinguish between suppressed and not though is also something important. For someone opening a file only to know by running CLI what is new work that needs fixing vs suppressed that is nice to tidy up is a big win for this workflow.
About displaying diagnostic information for suppressed violations:
https://github.com/eslint/rfcs/pull/133#discussion_r2299950151
@sushichan044 just checking in -- are you still planning on working on this?
@nzakas
Sorry, my academic research has kept me very busy and my response is delayed.
What I’m currently thinking is to have SuppressionService.applySuppressions return not only the LintResult[] after bulk suppression is applied, but also a separate set of suppressed LintResult[]. Then, the lintText / lintFiles APIs would return that information as well.
This approach would simplify the implementation, but it might place more burden on the ecosystem using the API.
Anyway, I’ll make time to reconsider this by the coming weekend.
To match CLI behavior, we’d need to extend LintResult for bulk-suppression related data and add a new API like ESLint.outputFixes.
As for changes that impose less burden on the ecosystem, I'm also considering the following ideas. These can be implemented sufficiently with the existing logic, but if API users make mistakes in their implementation, it may result in confusing behavior.
In lintText() and lintFiles():
• When fix is false: apply bulk suppression directly to LintResult[].messages.
• When fix is true: apply bulk suppression to LintResult[].messages entries that cannot be speculatively auto-fixed, on the assumption that outputFixes() will be called in later processing.
note:
In this case, considering the use cases, it is necessary to add some property to LintResult that stores the LintMessage[] removed by bulk suppression.
Alternatively, it may be acceptable to use the existing LintResult.suppressedMessages, as long as we make it possible to distinguish between eslint-disable and bulk suppression.
Thanks for the update, and no worries -- we don't have any time constraints here. :)
Alternatively, it may be acceptable to use the existing
LintResult.suppressedMessages, as long as we make it possible to distinguish between eslint-disable and bulk suppression.
We don't currently distinguish between the two types of suppressions, so I'm not sure I understand why the distinction is necessary here. Can you explain your thinking a bit more?
We do want to be careful about maintaining existing public interfaces like lintText() and lintFiles(), as these are used quite heavily in the ecosystem.