eslint 9.23.0 → 9.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/README.md +1 -1
  2. package/lib/cli-engine/cli-engine.js +2 -2
  3. package/lib/cli.js +98 -1
  4. package/lib/config/config-loader.js +108 -34
  5. package/lib/config/flat-config-helpers.js +7 -4
  6. package/lib/eslint/eslint-helpers.js +50 -5
  7. package/lib/eslint/eslint.js +17 -53
  8. package/lib/eslint/legacy-eslint.js +1 -1
  9. package/lib/linter/code-path-analysis/code-path-state.js +1 -1
  10. package/lib/linter/linter.js +1 -1
  11. package/lib/linter/rules.js +1 -1
  12. package/lib/options.js +29 -0
  13. package/lib/rule-tester/rule-tester.js +1 -1
  14. package/lib/rules/accessor-pairs.js +1 -1
  15. package/lib/rules/array-bracket-newline.js +1 -1
  16. package/lib/rules/array-bracket-spacing.js +1 -1
  17. package/lib/rules/array-callback-return.js +1 -1
  18. package/lib/rules/array-element-newline.js +1 -1
  19. package/lib/rules/arrow-body-style.js +1 -1
  20. package/lib/rules/arrow-parens.js +1 -1
  21. package/lib/rules/arrow-spacing.js +1 -1
  22. package/lib/rules/block-scoped-var.js +1 -1
  23. package/lib/rules/block-spacing.js +1 -1
  24. package/lib/rules/brace-style.js +1 -1
  25. package/lib/rules/callback-return.js +1 -1
  26. package/lib/rules/camelcase.js +1 -1
  27. package/lib/rules/capitalized-comments.js +1 -1
  28. package/lib/rules/class-methods-use-this.js +46 -2
  29. package/lib/rules/comma-dangle.js +1 -1
  30. package/lib/rules/comma-spacing.js +1 -1
  31. package/lib/rules/comma-style.js +1 -1
  32. package/lib/rules/complexity.js +1 -1
  33. package/lib/rules/computed-property-spacing.js +1 -1
  34. package/lib/rules/consistent-return.js +1 -1
  35. package/lib/rules/consistent-this.js +1 -1
  36. package/lib/rules/constructor-super.js +1 -1
  37. package/lib/rules/curly.js +1 -1
  38. package/lib/rules/default-case-last.js +1 -1
  39. package/lib/rules/default-case.js +1 -1
  40. package/lib/rules/default-param-last.js +1 -1
  41. package/lib/rules/dot-location.js +1 -1
  42. package/lib/rules/dot-notation.js +1 -1
  43. package/lib/rules/eol-last.js +1 -1
  44. package/lib/rules/eqeqeq.js +1 -1
  45. package/lib/rules/for-direction.js +1 -1
  46. package/lib/rules/func-call-spacing.js +1 -1
  47. package/lib/rules/func-name-matching.js +1 -1
  48. package/lib/rules/func-names.js +1 -1
  49. package/lib/rules/func-style.js +1 -1
  50. package/lib/rules/function-call-argument-newline.js +1 -1
  51. package/lib/rules/function-paren-newline.js +1 -1
  52. package/lib/rules/generator-star-spacing.js +1 -1
  53. package/lib/rules/getter-return.js +1 -1
  54. package/lib/rules/global-require.js +1 -1
  55. package/lib/rules/grouped-accessor-pairs.js +1 -1
  56. package/lib/rules/guard-for-in.js +1 -1
  57. package/lib/rules/handle-callback-err.js +1 -1
  58. package/lib/rules/id-blacklist.js +1 -1
  59. package/lib/rules/id-denylist.js +1 -1
  60. package/lib/rules/id-length.js +1 -1
  61. package/lib/rules/id-match.js +1 -1
  62. package/lib/rules/implicit-arrow-linebreak.js +1 -1
  63. package/lib/rules/indent-legacy.js +1 -1
  64. package/lib/rules/indent.js +1 -1
  65. package/lib/rules/init-declarations.js +22 -1
  66. package/lib/rules/jsx-quotes.js +1 -1
  67. package/lib/rules/key-spacing.js +1 -1
  68. package/lib/rules/keyword-spacing.js +1 -1
  69. package/lib/rules/line-comment-position.js +1 -1
  70. package/lib/rules/linebreak-style.js +1 -1
  71. package/lib/rules/lines-around-comment.js +1 -1
  72. package/lib/rules/lines-around-directive.js +1 -1
  73. package/lib/rules/lines-between-class-members.js +1 -1
  74. package/lib/rules/logical-assignment-operators.js +1 -1
  75. package/lib/rules/max-classes-per-file.js +1 -1
  76. package/lib/rules/max-depth.js +1 -1
  77. package/lib/rules/max-len.js +1 -1
  78. package/lib/rules/max-lines-per-function.js +1 -1
  79. package/lib/rules/max-lines.js +1 -1
  80. package/lib/rules/max-nested-callbacks.js +1 -1
  81. package/lib/rules/max-params.js +1 -1
  82. package/lib/rules/max-statements-per-line.js +1 -1
  83. package/lib/rules/max-statements.js +1 -1
  84. package/lib/rules/multiline-comment-style.js +1 -1
  85. package/lib/rules/multiline-ternary.js +1 -1
  86. package/lib/rules/new-cap.js +1 -1
  87. package/lib/rules/new-parens.js +1 -1
  88. package/lib/rules/newline-after-var.js +1 -1
  89. package/lib/rules/newline-before-return.js +1 -1
  90. package/lib/rules/newline-per-chained-call.js +1 -1
  91. package/lib/rules/no-alert.js +1 -1
  92. package/lib/rules/no-array-constructor.js +4 -1
  93. package/lib/rules/no-async-promise-executor.js +1 -1
  94. package/lib/rules/no-await-in-loop.js +1 -1
  95. package/lib/rules/no-bitwise.js +1 -1
  96. package/lib/rules/no-buffer-constructor.js +1 -1
  97. package/lib/rules/no-caller.js +1 -1
  98. package/lib/rules/no-case-declarations.js +1 -1
  99. package/lib/rules/no-catch-shadow.js +1 -1
  100. package/lib/rules/no-class-assign.js +1 -1
  101. package/lib/rules/no-compare-neg-zero.js +1 -1
  102. package/lib/rules/no-cond-assign.js +1 -1
  103. package/lib/rules/no-confusing-arrow.js +1 -1
  104. package/lib/rules/no-console.js +1 -1
  105. package/lib/rules/no-const-assign.js +1 -1
  106. package/lib/rules/no-constant-binary-expression.js +2 -2
  107. package/lib/rules/no-constant-condition.js +1 -1
  108. package/lib/rules/no-constructor-return.js +1 -1
  109. package/lib/rules/no-continue.js +1 -1
  110. package/lib/rules/no-control-regex.js +1 -1
  111. package/lib/rules/no-debugger.js +1 -1
  112. package/lib/rules/no-delete-var.js +1 -1
  113. package/lib/rules/no-div-regex.js +1 -1
  114. package/lib/rules/no-dupe-args.js +1 -1
  115. package/lib/rules/no-dupe-class-members.js +10 -1
  116. package/lib/rules/no-dupe-else-if.js +1 -1
  117. package/lib/rules/no-dupe-keys.js +1 -1
  118. package/lib/rules/no-duplicate-case.js +1 -1
  119. package/lib/rules/no-duplicate-imports.js +1 -1
  120. package/lib/rules/no-else-return.js +1 -1
  121. package/lib/rules/no-empty-character-class.js +1 -1
  122. package/lib/rules/no-empty-function.js +1 -1
  123. package/lib/rules/no-empty-pattern.js +1 -1
  124. package/lib/rules/no-empty-static-block.js +1 -1
  125. package/lib/rules/no-empty.js +1 -1
  126. package/lib/rules/no-eq-null.js +1 -1
  127. package/lib/rules/no-eval.js +1 -1
  128. package/lib/rules/no-ex-assign.js +1 -1
  129. package/lib/rules/no-extend-native.js +1 -1
  130. package/lib/rules/no-extra-bind.js +1 -1
  131. package/lib/rules/no-extra-boolean-cast.js +1 -1
  132. package/lib/rules/no-extra-label.js +1 -1
  133. package/lib/rules/no-extra-parens.js +1 -1
  134. package/lib/rules/no-extra-semi.js +1 -1
  135. package/lib/rules/no-fallthrough.js +1 -1
  136. package/lib/rules/no-floating-decimal.js +1 -1
  137. package/lib/rules/no-func-assign.js +1 -1
  138. package/lib/rules/no-global-assign.js +1 -1
  139. package/lib/rules/no-implicit-coercion.js +1 -1
  140. package/lib/rules/no-implicit-globals.js +1 -1
  141. package/lib/rules/no-implied-eval.js +1 -1
  142. package/lib/rules/no-import-assign.js +1 -1
  143. package/lib/rules/no-inline-comments.js +1 -1
  144. package/lib/rules/no-inner-declarations.js +1 -1
  145. package/lib/rules/no-invalid-regexp.js +1 -1
  146. package/lib/rules/no-invalid-this.js +1 -1
  147. package/lib/rules/no-irregular-whitespace.js +1 -1
  148. package/lib/rules/no-iterator.js +1 -1
  149. package/lib/rules/no-label-var.js +1 -1
  150. package/lib/rules/no-labels.js +1 -1
  151. package/lib/rules/no-lone-blocks.js +1 -1
  152. package/lib/rules/no-lonely-if.js +1 -1
  153. package/lib/rules/no-loop-func.js +8 -4
  154. package/lib/rules/no-loss-of-precision.js +3 -1
  155. package/lib/rules/no-magic-numbers.js +1 -1
  156. package/lib/rules/no-misleading-character-class.js +1 -1
  157. package/lib/rules/no-mixed-operators.js +1 -1
  158. package/lib/rules/no-mixed-requires.js +1 -1
  159. package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
  160. package/lib/rules/no-multi-assign.js +1 -1
  161. package/lib/rules/no-multi-spaces.js +1 -1
  162. package/lib/rules/no-multi-str.js +1 -1
  163. package/lib/rules/no-multiple-empty-lines.js +1 -1
  164. package/lib/rules/no-native-reassign.js +1 -1
  165. package/lib/rules/no-negated-condition.js +1 -1
  166. package/lib/rules/no-negated-in-lhs.js +1 -1
  167. package/lib/rules/no-nested-ternary.js +1 -1
  168. package/lib/rules/no-new-func.js +1 -1
  169. package/lib/rules/no-new-native-nonconstructor.js +1 -1
  170. package/lib/rules/no-new-object.js +1 -1
  171. package/lib/rules/no-new-require.js +1 -1
  172. package/lib/rules/no-new-symbol.js +1 -1
  173. package/lib/rules/no-new-wrappers.js +1 -1
  174. package/lib/rules/no-new.js +1 -1
  175. package/lib/rules/no-nonoctal-decimal-escape.js +1 -1
  176. package/lib/rules/no-obj-calls.js +1 -1
  177. package/lib/rules/no-object-constructor.js +1 -1
  178. package/lib/rules/no-octal-escape.js +1 -1
  179. package/lib/rules/no-octal.js +1 -1
  180. package/lib/rules/no-param-reassign.js +1 -1
  181. package/lib/rules/no-path-concat.js +1 -1
  182. package/lib/rules/no-plusplus.js +1 -1
  183. package/lib/rules/no-process-env.js +1 -1
  184. package/lib/rules/no-process-exit.js +1 -1
  185. package/lib/rules/no-promise-executor-return.js +1 -1
  186. package/lib/rules/no-proto.js +1 -1
  187. package/lib/rules/no-prototype-builtins.js +1 -1
  188. package/lib/rules/no-redeclare.js +1 -1
  189. package/lib/rules/no-regex-spaces.js +1 -1
  190. package/lib/rules/no-restricted-exports.js +1 -1
  191. package/lib/rules/no-restricted-globals.js +1 -1
  192. package/lib/rules/no-restricted-imports.js +1 -1
  193. package/lib/rules/no-restricted-modules.js +1 -1
  194. package/lib/rules/no-restricted-properties.js +1 -1
  195. package/lib/rules/no-restricted-syntax.js +1 -1
  196. package/lib/rules/no-return-assign.js +1 -1
  197. package/lib/rules/no-return-await.js +1 -1
  198. package/lib/rules/no-script-url.js +1 -1
  199. package/lib/rules/no-self-assign.js +1 -1
  200. package/lib/rules/no-self-compare.js +1 -1
  201. package/lib/rules/no-sequences.js +1 -1
  202. package/lib/rules/no-setter-return.js +1 -1
  203. package/lib/rules/no-shadow-restricted-names.js +1 -1
  204. package/lib/rules/no-shadow.js +1 -1
  205. package/lib/rules/no-spaced-func.js +1 -1
  206. package/lib/rules/no-sparse-arrays.js +1 -1
  207. package/lib/rules/no-sync.js +1 -1
  208. package/lib/rules/no-tabs.js +1 -1
  209. package/lib/rules/no-template-curly-in-string.js +1 -1
  210. package/lib/rules/no-ternary.js +1 -1
  211. package/lib/rules/no-this-before-super.js +1 -1
  212. package/lib/rules/no-throw-literal.js +1 -1
  213. package/lib/rules/no-trailing-spaces.js +1 -1
  214. package/lib/rules/no-undef-init.js +1 -1
  215. package/lib/rules/no-undef.js +1 -1
  216. package/lib/rules/no-undefined.js +1 -1
  217. package/lib/rules/no-underscore-dangle.js +1 -1
  218. package/lib/rules/no-unexpected-multiline.js +1 -1
  219. package/lib/rules/no-unmodified-loop-condition.js +1 -1
  220. package/lib/rules/no-unneeded-ternary.js +1 -1
  221. package/lib/rules/no-unreachable-loop.js +1 -1
  222. package/lib/rules/no-unreachable.js +1 -1
  223. package/lib/rules/no-unsafe-finally.js +1 -1
  224. package/lib/rules/no-unsafe-negation.js +1 -1
  225. package/lib/rules/no-unsafe-optional-chaining.js +1 -1
  226. package/lib/rules/no-unused-expressions.js +1 -1
  227. package/lib/rules/no-unused-labels.js +1 -1
  228. package/lib/rules/no-unused-private-class-members.js +1 -1
  229. package/lib/rules/no-unused-vars.js +3 -3
  230. package/lib/rules/no-use-before-define.js +1 -1
  231. package/lib/rules/no-useless-assignment.js +1 -1
  232. package/lib/rules/no-useless-backreference.js +1 -1
  233. package/lib/rules/no-useless-call.js +1 -1
  234. package/lib/rules/no-useless-catch.js +1 -1
  235. package/lib/rules/no-useless-computed-key.js +1 -1
  236. package/lib/rules/no-useless-concat.js +1 -1
  237. package/lib/rules/no-useless-constructor.js +1 -1
  238. package/lib/rules/no-useless-escape.js +1 -1
  239. package/lib/rules/no-useless-rename.js +1 -1
  240. package/lib/rules/no-useless-return.js +1 -1
  241. package/lib/rules/no-var.js +1 -1
  242. package/lib/rules/no-void.js +1 -1
  243. package/lib/rules/no-warning-comments.js +1 -1
  244. package/lib/rules/no-whitespace-before-property.js +1 -1
  245. package/lib/rules/no-with.js +1 -1
  246. package/lib/rules/nonblock-statement-body-position.js +1 -1
  247. package/lib/rules/object-curly-newline.js +1 -1
  248. package/lib/rules/object-curly-spacing.js +1 -1
  249. package/lib/rules/object-property-newline.js +1 -1
  250. package/lib/rules/object-shorthand.js +1 -1
  251. package/lib/rules/one-var-declaration-per-line.js +1 -1
  252. package/lib/rules/one-var.js +1 -1
  253. package/lib/rules/operator-assignment.js +1 -1
  254. package/lib/rules/operator-linebreak.js +1 -1
  255. package/lib/rules/padded-blocks.js +1 -1
  256. package/lib/rules/padding-line-between-statements.js +1 -1
  257. package/lib/rules/prefer-arrow-callback.js +1 -1
  258. package/lib/rules/prefer-const.js +1 -1
  259. package/lib/rules/prefer-destructuring.js +1 -1
  260. package/lib/rules/prefer-exponentiation-operator.js +1 -1
  261. package/lib/rules/prefer-named-capture-group.js +1 -1
  262. package/lib/rules/prefer-numeric-literals.js +1 -1
  263. package/lib/rules/prefer-object-has-own.js +1 -1
  264. package/lib/rules/prefer-object-spread.js +1 -1
  265. package/lib/rules/prefer-promise-reject-errors.js +1 -1
  266. package/lib/rules/prefer-reflect.js +1 -1
  267. package/lib/rules/prefer-regex-literals.js +1 -1
  268. package/lib/rules/prefer-rest-params.js +1 -1
  269. package/lib/rules/prefer-spread.js +1 -1
  270. package/lib/rules/prefer-template.js +1 -1
  271. package/lib/rules/quote-props.js +1 -1
  272. package/lib/rules/quotes.js +1 -1
  273. package/lib/rules/radix.js +1 -1
  274. package/lib/rules/require-atomic-updates.js +1 -1
  275. package/lib/rules/require-await.js +1 -1
  276. package/lib/rules/require-unicode-regexp.js +1 -1
  277. package/lib/rules/require-yield.js +1 -1
  278. package/lib/rules/rest-spread-spacing.js +1 -1
  279. package/lib/rules/semi-spacing.js +1 -1
  280. package/lib/rules/semi-style.js +1 -1
  281. package/lib/rules/semi.js +1 -1
  282. package/lib/rules/sort-imports.js +1 -1
  283. package/lib/rules/sort-keys.js +1 -1
  284. package/lib/rules/sort-vars.js +1 -1
  285. package/lib/rules/space-before-blocks.js +1 -1
  286. package/lib/rules/space-before-function-paren.js +1 -1
  287. package/lib/rules/space-in-parens.js +1 -1
  288. package/lib/rules/space-infix-ops.js +1 -1
  289. package/lib/rules/space-unary-ops.js +1 -1
  290. package/lib/rules/spaced-comment.js +1 -1
  291. package/lib/rules/strict.js +1 -1
  292. package/lib/rules/switch-colon-spacing.js +1 -1
  293. package/lib/rules/symbol-description.js +1 -1
  294. package/lib/rules/template-curly-spacing.js +1 -1
  295. package/lib/rules/template-tag-spacing.js +1 -1
  296. package/lib/rules/unicode-bom.js +1 -1
  297. package/lib/rules/use-isnan.js +1 -1
  298. package/lib/rules/valid-typeof.js +1 -1
  299. package/lib/rules/vars-on-top.js +1 -1
  300. package/lib/rules/wrap-iife.js +1 -1
  301. package/lib/rules/wrap-regex.js +1 -1
  302. package/lib/rules/yield-star-spacing.js +1 -1
  303. package/lib/rules/yoda.js +1 -1
  304. package/lib/services/suppressions-service.js +289 -0
  305. package/lib/shared/flags.js +4 -0
  306. package/lib/shared/types.js +4 -27
  307. package/lib/types/index.d.ts +7 -7
  308. package/package.json +5 -5
@@ -14,7 +14,7 @@ const astUtils = require("./utils/ast-utils");
14
14
  // Rule Definition
15
15
  //------------------------------------------------------------------------------
16
16
 
17
- /** @type {import('../shared/types').Rule} */
17
+ /** @type {import('../types').Rule.RuleModule} */
18
18
  module.exports = {
19
19
  meta: {
20
20
  type: "problem",
@@ -9,7 +9,7 @@
9
9
  // Rule Definition
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- /** @type {import('../shared/types').Rule} */
12
+ /** @type {import('../types').Rule.RuleModule} */
13
13
  module.exports = {
14
14
  meta: {
15
15
  type: "suggestion",
@@ -37,7 +37,7 @@ function isCalleeOfNewExpression(node) {
37
37
  // Rule Definition
38
38
  //------------------------------------------------------------------------------
39
39
 
40
- /** @type {import('../shared/types').Rule} */
40
+ /** @type {import('../types').Rule.RuleModule} */
41
41
  module.exports = {
42
42
  meta: {
43
43
  deprecated: {
@@ -10,7 +10,7 @@
10
10
  // Rule Definition
11
11
  //------------------------------------------------------------------------------
12
12
 
13
- /** @type {import('../shared/types').Rule} */
13
+ /** @type {import('../types').Rule.RuleModule} */
14
14
  module.exports = {
15
15
  meta: {
16
16
  deprecated: {
@@ -10,7 +10,7 @@
10
10
  // Rule Definition
11
11
  //------------------------------------------------------------------------------
12
12
 
13
- /** @type {import('../shared/types').Rule} */
13
+ /** @type {import('../types').Rule.RuleModule} */
14
14
  module.exports = {
15
15
  meta: {
16
16
  deprecated: {
package/lib/rules/yoda.js CHANGED
@@ -108,7 +108,7 @@ function getNormalizedLiteral(node) {
108
108
  // Rule Definition
109
109
  //------------------------------------------------------------------------------
110
110
 
111
- /** @type {import('../shared/types').Rule} */
111
+ /** @type {import('../types').Rule.RuleModule} */
112
112
  module.exports = {
113
113
  meta: {
114
114
  type: "suggestion",
@@ -0,0 +1,289 @@
1
+ /**
2
+ * @fileoverview Manages the suppressed violations.
3
+ * @author Iacovos Constantinou
4
+ */
5
+
6
+ "use strict";
7
+
8
+ //-----------------------------------------------------------------------------
9
+ // Requirements
10
+ //-----------------------------------------------------------------------------
11
+
12
+ const fs = require("node:fs");
13
+ const path = require("node:path");
14
+ const { calculateStatsPerFile } = require("../eslint/eslint-helpers");
15
+
16
+ //------------------------------------------------------------------------------
17
+ // Typedefs
18
+ //------------------------------------------------------------------------------
19
+
20
+ // For VSCode IntelliSense
21
+ /** @typedef {import("../shared/types").LintResult} LintResult */
22
+ /** @typedef {import("../shared/types").SuppressedViolations} SuppressedViolations */
23
+
24
+ //-----------------------------------------------------------------------------
25
+ // Exports
26
+ //-----------------------------------------------------------------------------
27
+
28
+ /**
29
+ * Manages the suppressed violations.
30
+ */
31
+ class SuppressionsService {
32
+ filePath = "";
33
+ cwd = "";
34
+
35
+ /**
36
+ * Creates a new instance of SuppressionsService.
37
+ * @param {Object} options The options.
38
+ * @param {string} [options.filePath] The location of the suppressions file.
39
+ * @param {string} [options.cwd] The current working directory.
40
+ */
41
+ constructor({ filePath, cwd }) {
42
+ this.filePath = filePath;
43
+ this.cwd = cwd;
44
+ }
45
+
46
+ /**
47
+ * Updates the suppressions file based on the current violations and the provided rules.
48
+ * If no rules are provided, all violations are suppressed.
49
+ * @param {LintResult[]|undefined} results The lint results.
50
+ * @param {string[]|undefined} rules The rules to suppress.
51
+ * @returns {Promise<void>}
52
+ */
53
+ async suppress(results, rules) {
54
+ const suppressions = await this.load();
55
+
56
+ for (const result of results) {
57
+ const relativeFilePath = this.getRelativeFilePath(result.filePath);
58
+ const violationsByRule = SuppressionsService.countViolationsByRule(
59
+ result.messages,
60
+ );
61
+
62
+ for (const ruleId in violationsByRule) {
63
+ if (rules && !rules.includes(ruleId)) {
64
+ continue;
65
+ }
66
+
67
+ suppressions[relativeFilePath] ??= {};
68
+ suppressions[relativeFilePath][ruleId] =
69
+ violationsByRule[ruleId];
70
+ }
71
+ }
72
+
73
+ return this.save(suppressions);
74
+ }
75
+
76
+ /**
77
+ * Removes old, unused suppressions for violations that do not occur anymore.
78
+ * @param {LintResult[]} results The lint results.
79
+ * @returns {Promise<void>} No return value.
80
+ */
81
+ async prune(results) {
82
+ const suppressions = await this.load();
83
+ const { unused } = this.applySuppressions(results, suppressions);
84
+
85
+ for (const file in unused) {
86
+ if (!suppressions[file]) {
87
+ continue;
88
+ }
89
+
90
+ for (const rule in unused[file]) {
91
+ if (!suppressions[file][rule]) {
92
+ continue;
93
+ }
94
+
95
+ const suppressionsCount = suppressions[file][rule].count;
96
+ const violationsCount = unused[file][rule].count;
97
+
98
+ if (suppressionsCount === violationsCount) {
99
+ // Remove unused rules
100
+ delete suppressions[file][rule];
101
+ } else {
102
+ // Update the count to match the new number of violations
103
+ suppressions[file][rule].count -= violationsCount;
104
+ }
105
+ }
106
+
107
+ // Cleanup files with no rules
108
+ if (Object.keys(suppressions[file]).length === 0) {
109
+ delete suppressions[file];
110
+ }
111
+ }
112
+
113
+ return this.save(suppressions);
114
+ }
115
+
116
+ /**
117
+ * Checks the provided suppressions against the lint results.
118
+ *
119
+ * For each file, counts the number of violations per rule.
120
+ * For each rule in each file, compares the number of violations against the counter from the suppressions file.
121
+ * If the number of violations is less or equal to the counter, messages are moved to `LintResult#suppressedMessages` and ignored.
122
+ * Otherwise, all violations are reported as usual.
123
+ * @param {LintResult[]} results The lint results.
124
+ * @param {SuppressedViolations} suppressions The suppressions.
125
+ * @returns {{
126
+ * results: LintResult[],
127
+ * unused: SuppressedViolations
128
+ * }} The updated results and the unused suppressions.
129
+ */
130
+ applySuppressions(results, suppressions) {
131
+ /**
132
+ * We copy the results to avoid modifying the original objects
133
+ * We remove only result messages that are matched and hence suppressed
134
+ * We leave the rest untouched to minimize the risk of losing parts of the original data
135
+ */
136
+ const filtered = structuredClone(results);
137
+ const unused = {};
138
+
139
+ for (const result of filtered) {
140
+ const relativeFilePath = this.getRelativeFilePath(result.filePath);
141
+
142
+ if (!suppressions[relativeFilePath]) {
143
+ continue;
144
+ }
145
+
146
+ const violationsByRule = SuppressionsService.countViolationsByRule(
147
+ result.messages,
148
+ );
149
+ let wasSuppressed = false;
150
+
151
+ for (const ruleId in violationsByRule) {
152
+ if (!suppressions[relativeFilePath][ruleId]) {
153
+ continue;
154
+ }
155
+
156
+ const suppressionsCount =
157
+ suppressions[relativeFilePath][ruleId].count;
158
+ const violationsCount = violationsByRule[ruleId].count;
159
+
160
+ // Suppress messages if the number of violations is less or equal to the suppressions count
161
+ if (violationsCount <= suppressionsCount) {
162
+ SuppressionsService.suppressMessagesByRule(result, ruleId);
163
+ wasSuppressed = true;
164
+ }
165
+
166
+ // Update the count to match the new number of violations, otherwise remove the rule entirely
167
+ if (violationsCount < suppressionsCount) {
168
+ unused[relativeFilePath] ??= {};
169
+ unused[relativeFilePath][ruleId] ??= {};
170
+ unused[relativeFilePath][ruleId].count =
171
+ suppressionsCount - violationsCount;
172
+ }
173
+ }
174
+
175
+ // Mark as unused all the suppressions that were not matched against a rule
176
+ for (const ruleId in suppressions[relativeFilePath]) {
177
+ if (violationsByRule[ruleId]) {
178
+ continue;
179
+ }
180
+
181
+ unused[relativeFilePath] ??= {};
182
+ unused[relativeFilePath][ruleId] =
183
+ suppressions[relativeFilePath][ruleId];
184
+ }
185
+
186
+ // Recalculate stats if messages were suppressed
187
+ if (wasSuppressed) {
188
+ Object.assign(result, calculateStatsPerFile(result.messages));
189
+ }
190
+ }
191
+
192
+ return {
193
+ results: filtered,
194
+ unused,
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Loads the suppressions file.
200
+ * @throws {Error} If the suppressions file cannot be parsed.
201
+ * @returns {Promise<SuppressedViolations>} The suppressions.
202
+ */
203
+ async load() {
204
+ try {
205
+ const data = await fs.promises.readFile(this.filePath, "utf8");
206
+
207
+ return JSON.parse(data);
208
+ } catch (err) {
209
+ if (err.code === "ENOENT") {
210
+ return {};
211
+ }
212
+ throw new Error(
213
+ `Failed to parse suppressions file at ${this.filePath}`,
214
+ );
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Updates the suppressions file.
220
+ * @param {SuppressedViolations} suppressions The suppressions to save.
221
+ * @returns {Promise<void>}
222
+ * @private
223
+ */
224
+ save(suppressions) {
225
+ return fs.promises.writeFile(
226
+ this.filePath,
227
+ JSON.stringify(suppressions, null, 2),
228
+ );
229
+ }
230
+
231
+ /**
232
+ * Counts the violations by rule, ignoring warnings.
233
+ * @param {LintMessage[]} messages The messages to count.
234
+ * @returns {Record<string, number>} The number of violations by rule.
235
+ */
236
+ static countViolationsByRule(messages) {
237
+ return messages.reduce((totals, message) => {
238
+ if (message.severity === 2 && message.ruleId) {
239
+ totals[message.ruleId] ??= { count: 0 };
240
+ totals[message.ruleId].count++;
241
+ }
242
+ return totals;
243
+ }, {});
244
+ }
245
+
246
+ /**
247
+ * Returns the relative path of a file to the current working directory.
248
+ * Always in POSIX format for consistency and interoperability.
249
+ * @param {string} filePath The file path.
250
+ * @returns {string} The relative file path.
251
+ */
252
+ getRelativeFilePath(filePath) {
253
+ return path
254
+ .relative(this.cwd, filePath)
255
+ .split(path.sep)
256
+ .join(path.posix.sep);
257
+ }
258
+
259
+ /**
260
+ * Moves the messages matching the rule to `LintResult#suppressedMessages` and updates the stats.
261
+ * @param {LintResult} result The result to update.
262
+ * @param {string} ruleId The rule to suppress.
263
+ * @returns {void}
264
+ */
265
+ static suppressMessagesByRule(result, ruleId) {
266
+ const suppressedMessages = result.messages.filter(
267
+ message => message.ruleId === ruleId,
268
+ );
269
+
270
+ result.suppressedMessages = result.suppressedMessages.concat(
271
+ suppressedMessages.map(message => {
272
+ message.suppressions = [
273
+ {
274
+ kind: "file",
275
+ justification: "",
276
+ },
277
+ ];
278
+
279
+ return message;
280
+ }),
281
+ );
282
+
283
+ result.messages = result.messages.filter(
284
+ message => message.ruleId !== ruleId,
285
+ );
286
+ }
287
+ }
288
+
289
+ module.exports = { SuppressionsService };
@@ -31,6 +31,10 @@ const activeFlags = new Map([
31
31
  "unstable_config_lookup_from_file",
32
32
  "Look up `eslint.config.js` from the file being linted.",
33
33
  ],
34
+ [
35
+ "unstable_native_nodejs_ts_config",
36
+ "Use native Node.js to load TypeScript configuration.",
37
+ ],
34
38
  ]);
35
39
 
36
40
  /**
@@ -124,6 +124,10 @@ module.exports = {};
124
124
  * @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
125
125
  */
126
126
 
127
+ /**
128
+ * @typedef {Record<string, Record<string, { count: number }>>} SuppressedViolations
129
+ */
130
+
127
131
  /**
128
132
  * @typedef {Object} SuggestionResult
129
133
  * @property {string} desc A short description.
@@ -162,25 +166,6 @@ module.exports = {};
162
166
  * @property {{ name?: string, url?: string }} [rule] Name and information of the replacement rule
163
167
  */
164
168
 
165
- /**
166
- * @typedef {Object} RuleMeta
167
- * @property {boolean|DeprecatedInfo} [deprecated] If `true` then the rule has been deprecated.
168
- * @property {Array} [defaultOptions] Default options for the rule.
169
- * @property {RuleMetaDocs} docs The document information of the rule.
170
- * @property {"code"|"whitespace"} [fixable] The autofix type.
171
- * @property {boolean} [hasSuggestions] If `true` then the rule provides suggestions.
172
- * @property {Record<string,string>} [messages] The messages the rule reports.
173
- * @property {string[]} [replacedBy] The IDs of the alternative rules.
174
- * @property {Array|Object} schema The option schema of the rule.
175
- * @property {"problem"|"suggestion"|"layout"} type The rule type.
176
- */
177
-
178
- /**
179
- * @typedef {Object} Rule
180
- * @property {Function} create The factory of the rule.
181
- * @property {RuleMeta} meta The meta data of the rule.
182
- */
183
-
184
169
  /**
185
170
  * @typedef {Object} Plugin
186
171
  * @property {Record<string, ConfigData>} [configs] The definition of plugin configs.
@@ -259,11 +244,3 @@ module.exports = {};
259
244
  * @typedef {Object} ResultsMeta
260
245
  * @property {MaxWarningsExceeded} [maxWarningsExceeded] Present if the maxWarnings threshold was exceeded.
261
246
  */
262
-
263
- /**
264
- * A formatter function.
265
- * @callback FormatterFunction
266
- * @param {LintResult[]} results The list of linting results.
267
- * @param {{cwd: string, maxWarningsExceeded?: MaxWarningsExceeded, rulesMeta: Record<string, RuleMeta>}} context A context object.
268
- * @returns {string | Promise<string>} Formatted text.
269
- */
@@ -1174,13 +1174,13 @@ export namespace Rule {
1174
1174
  }
1175
1175
 
1176
1176
  interface RuleContext
1177
- extends CoreRuleContext<
1178
- RuleContextTypeOptions & {
1179
- LangOptions: Linter.LanguageOptions;
1180
- Code: SourceCode;
1181
- Node: ESTree.Node;
1182
- }
1183
- > {
1177
+ extends CoreRuleContext<{
1178
+ LangOptions: Linter.LanguageOptions;
1179
+ Code: SourceCode;
1180
+ RuleOptions: any[];
1181
+ Node: ESTree.Node;
1182
+ MessageIds: string;
1183
+ }> {
1184
1184
  /*
1185
1185
  * Need to extend the `RuleContext` interface to include the
1186
1186
  * deprecated methods that have not yet been removed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "9.23.0",
3
+ "version": "9.24.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "type": "commonjs",
@@ -58,7 +58,7 @@
58
58
  "lint:docs:rule-examples": "node Makefile.js checkRuleExamples",
59
59
  "lint:unused": "knip",
60
60
  "lint:fix": "trunk check -y --ignore=docs/**/*.js -a --filter=eslint && trunk check -y --ignore=docs/**/*.js",
61
- "lint:fix:docs:js": "trunk check -y --ignore=** --ignore=!docs/**/*.js -a --flter=eslint && trunk check -y --ignore=** --ignore=!docs/**/*.js",
61
+ "lint:fix:docs:js": "trunk check -y --ignore=** --ignore=!docs/**/*.js -a --filter=eslint && trunk check -y --ignore=** --ignore=!docs/**/*.js",
62
62
  "lint:rule-types": "node tools/update-rule-type-headers.js --check",
63
63
  "lint:types": "attw --pack",
64
64
  "release:generate:alpha": "node Makefile.js generatePrerelease -- alpha",
@@ -106,11 +106,11 @@
106
106
  "dependencies": {
107
107
  "@eslint-community/eslint-utils": "^4.2.0",
108
108
  "@eslint-community/regexpp": "^4.12.1",
109
- "@eslint/config-array": "^0.19.2",
109
+ "@eslint/config-array": "^0.20.0",
110
110
  "@eslint/config-helpers": "^0.2.0",
111
111
  "@eslint/core": "^0.12.0",
112
112
  "@eslint/eslintrc": "^3.3.1",
113
- "@eslint/js": "9.23.0",
113
+ "@eslint/js": "9.24.0",
114
114
  "@eslint/plugin-kit": "^0.2.7",
115
115
  "@humanfs/node": "^0.16.6",
116
116
  "@humanwhocodes/module-importer": "^1.0.1",
@@ -147,7 +147,7 @@
147
147
  "@cypress/webpack-preprocessor": "^6.0.2",
148
148
  "@eslint/json": "^0.11.0",
149
149
  "@trunkio/launcher": "^1.3.0",
150
- "@types/node": "^20.11.5",
150
+ "@types/node": "^22.13.14",
151
151
  "@typescript-eslint/parser": "^8.4.0",
152
152
  "babel-loader": "^8.0.5",
153
153
  "c8": "^7.12.0",