eslint 9.36.0 → 9.37.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 (86) hide show
  1. package/README.md +2 -2
  2. package/lib/cli-engine/lint-result-cache.js +47 -29
  3. package/lib/eslint/eslint-helpers.js +6 -3
  4. package/lib/eslint/eslint.js +151 -37
  5. package/lib/eslint/worker.js +1 -3
  6. package/lib/linter/esquery.js +1 -1
  7. package/lib/rules/array-bracket-newline.js +1 -1
  8. package/lib/rules/array-bracket-spacing.js +1 -1
  9. package/lib/rules/array-element-newline.js +1 -1
  10. package/lib/rules/arrow-parens.js +1 -1
  11. package/lib/rules/arrow-spacing.js +1 -1
  12. package/lib/rules/block-spacing.js +1 -1
  13. package/lib/rules/brace-style.js +1 -1
  14. package/lib/rules/comma-dangle.js +1 -1
  15. package/lib/rules/comma-spacing.js +1 -1
  16. package/lib/rules/comma-style.js +1 -1
  17. package/lib/rules/computed-property-spacing.js +1 -1
  18. package/lib/rules/dot-location.js +1 -1
  19. package/lib/rules/eol-last.js +1 -1
  20. package/lib/rules/func-call-spacing.js +2 -2
  21. package/lib/rules/function-call-argument-newline.js +1 -1
  22. package/lib/rules/function-paren-newline.js +1 -1
  23. package/lib/rules/generator-star-spacing.js +1 -1
  24. package/lib/rules/implicit-arrow-linebreak.js +1 -1
  25. package/lib/rules/indent-legacy.js +1 -0
  26. package/lib/rules/indent.js +1 -1
  27. package/lib/rules/jsx-quotes.js +1 -1
  28. package/lib/rules/key-spacing.js +1 -1
  29. package/lib/rules/keyword-spacing.js +1 -1
  30. package/lib/rules/line-comment-position.js +1 -1
  31. package/lib/rules/linebreak-style.js +1 -1
  32. package/lib/rules/lines-around-comment.js +1 -1
  33. package/lib/rules/lines-around-directive.js +1 -1
  34. package/lib/rules/lines-between-class-members.js +1 -1
  35. package/lib/rules/max-len.js +1 -1
  36. package/lib/rules/max-statements-per-line.js +1 -1
  37. package/lib/rules/multiline-comment-style.js +1 -1
  38. package/lib/rules/multiline-ternary.js +1 -1
  39. package/lib/rules/new-parens.js +1 -1
  40. package/lib/rules/newline-after-var.js +1 -1
  41. package/lib/rules/newline-before-return.js +1 -1
  42. package/lib/rules/newline-per-chained-call.js +1 -1
  43. package/lib/rules/no-confusing-arrow.js +1 -1
  44. package/lib/rules/no-extra-parens.js +1 -1
  45. package/lib/rules/no-extra-semi.js +1 -1
  46. package/lib/rules/no-floating-decimal.js +1 -1
  47. package/lib/rules/no-loss-of-precision.js +5 -8
  48. package/lib/rules/no-mixed-operators.js +1 -1
  49. package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
  50. package/lib/rules/no-multi-spaces.js +1 -1
  51. package/lib/rules/no-multiple-empty-lines.js +1 -1
  52. package/lib/rules/no-restricted-imports.js +171 -4
  53. package/lib/rules/no-spaced-func.js +1 -1
  54. package/lib/rules/no-tabs.js +1 -1
  55. package/lib/rules/no-trailing-spaces.js +1 -1
  56. package/lib/rules/no-whitespace-before-property.js +1 -1
  57. package/lib/rules/nonblock-statement-body-position.js +1 -1
  58. package/lib/rules/object-curly-newline.js +1 -1
  59. package/lib/rules/object-curly-spacing.js +1 -1
  60. package/lib/rules/object-property-newline.js +1 -1
  61. package/lib/rules/one-var-declaration-per-line.js +1 -1
  62. package/lib/rules/operator-linebreak.js +1 -1
  63. package/lib/rules/padded-blocks.js +1 -1
  64. package/lib/rules/padding-line-between-statements.js +1 -1
  65. package/lib/rules/preserve-caught-error.js +1 -5
  66. package/lib/rules/quote-props.js +1 -1
  67. package/lib/rules/quotes.js +1 -1
  68. package/lib/rules/rest-spread-spacing.js +1 -1
  69. package/lib/rules/semi-spacing.js +1 -1
  70. package/lib/rules/semi-style.js +1 -1
  71. package/lib/rules/semi.js +1 -1
  72. package/lib/rules/space-before-blocks.js +1 -1
  73. package/lib/rules/space-before-function-paren.js +1 -1
  74. package/lib/rules/space-in-parens.js +1 -1
  75. package/lib/rules/space-infix-ops.js +1 -1
  76. package/lib/rules/space-unary-ops.js +1 -1
  77. package/lib/rules/spaced-comment.js +1 -1
  78. package/lib/rules/switch-colon-spacing.js +1 -1
  79. package/lib/rules/template-curly-spacing.js +1 -1
  80. package/lib/rules/template-tag-spacing.js +1 -1
  81. package/lib/rules/wrap-iife.js +1 -1
  82. package/lib/rules/wrap-regex.js +1 -1
  83. package/lib/rules/yield-star-spacing.js +1 -1
  84. package/lib/types/index.d.ts +8 -5
  85. package/lib/types/rules.d.ts +2 -0
  86. package/package.json +6 -6
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  [Contribute to ESLint](https://eslint.org/docs/latest/contribute) |
14
14
  [Report Bugs](https://eslint.org/docs/latest/contribute/report-bugs) |
15
15
  [Code of Conduct](https://eslint.org/conduct) |
16
- [Twitter](https://twitter.com/geteslint) |
16
+ [X](https://x.com/geteslint) |
17
17
  [Discord](https://eslint.org/chat) |
18
18
  [Mastodon](https://fosstodon.org/@eslint) |
19
19
  [Bluesky](https://bsky.app/profile/eslint.org)
@@ -333,7 +333,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
333
333
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
334
334
  <p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
335
335
  <p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
336
- <p><a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://sentry.io"><img src="https://github.com/getsentry.png" alt="Sentry" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
336
+ <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
337
337
  <h3>Technology Sponsors</h3>
338
338
  Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
339
339
  <p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
@@ -17,6 +17,12 @@ const hash = require("./hash");
17
17
 
18
18
  const debug = require("debug")("eslint:lint-result-cache");
19
19
 
20
+ //------------------------------------------------------------------------------
21
+ // Typedefs
22
+ //------------------------------------------------------------------------------
23
+
24
+ /** @typedef {import("../types").Linter.Config} Config */
25
+
20
26
  //-----------------------------------------------------------------------------
21
27
  // Helpers
22
28
  //-----------------------------------------------------------------------------
@@ -40,7 +46,7 @@ function isValidCacheStrategy(cacheStrategy) {
40
46
 
41
47
  /**
42
48
  * Calculates the hash of the config
43
- * @param {ConfigArray} config The config.
49
+ * @param {Config} config The config.
44
50
  * @returns {string} The hash of the config
45
51
  */
46
52
  function hashOfConfigFor(config) {
@@ -96,38 +102,13 @@ class LintResultCache {
96
102
  * cache. If the file is present and has not been changed, rebuild any
97
103
  * missing result information.
98
104
  * @param {string} filePath The file for which to retrieve lint results.
99
- * @param {ConfigArray} config The config of the file.
105
+ * @param {Config} config The config of the file.
100
106
  * @returns {Object|null} The rebuilt lint results, or null if the file is
101
107
  * changed or not in the filesystem.
102
108
  */
103
109
  getCachedLintResults(filePath, config) {
104
- /*
105
- * Cached lint results are valid if and only if:
106
- * 1. The file is present in the filesystem
107
- * 2. The file has not changed since the time it was previously linted
108
- * 3. The ESLint configuration has not changed since the time the file
109
- * was previously linted
110
- * If any of these are not true, we will not reuse the lint results.
111
- */
112
- const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
113
- const hashOfConfig = hashOfConfigFor(config);
114
- const changed =
115
- fileDescriptor.changed ||
116
- fileDescriptor.meta.hashOfConfig !== hashOfConfig;
110
+ const cachedResults = this.getValidCachedLintResults(filePath, config);
117
111
 
118
- if (fileDescriptor.notFound) {
119
- debug(`File not found on the file system: ${filePath}`);
120
- return null;
121
- }
122
-
123
- if (changed) {
124
- debug(`Cache entry not found or no longer valid: ${filePath}`);
125
- return null;
126
- }
127
-
128
- const cachedResults = fileDescriptor.meta.results;
129
-
130
- // Just in case, not sure if this can ever happen.
131
112
  if (!cachedResults) {
132
113
  return cachedResults;
133
114
  }
@@ -151,6 +132,43 @@ class LintResultCache {
151
132
  return results;
152
133
  }
153
134
 
135
+ /**
136
+ * Retrieve cached lint results for a given file path, if present in the
137
+ * cache and still valid.
138
+ * @param {string} filePath The file for which to retrieve lint results.
139
+ * @param {Config} config The config of the file.
140
+ * @returns {Object|null} The cached lint results if present in the cache
141
+ * and still valid; null otherwise.
142
+ */
143
+ getValidCachedLintResults(filePath, config) {
144
+ /*
145
+ * Cached lint results are valid if and only if:
146
+ * 1. The file is present in the filesystem
147
+ * 2. The file has not changed since the time it was previously linted
148
+ * 3. The ESLint configuration has not changed since the time the file
149
+ * was previously linted
150
+ * If any of these are not true, we will not reuse the lint results.
151
+ */
152
+ const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
153
+
154
+ if (fileDescriptor.notFound) {
155
+ debug(`File not found on the file system: ${filePath}`);
156
+ return null;
157
+ }
158
+
159
+ const hashOfConfig = hashOfConfigFor(config);
160
+ const changed =
161
+ fileDescriptor.changed ||
162
+ fileDescriptor.meta.hashOfConfig !== hashOfConfig;
163
+
164
+ if (changed) {
165
+ debug(`Cache entry not found or no longer valid: ${filePath}`);
166
+ return null;
167
+ }
168
+
169
+ return fileDescriptor.meta.results;
170
+ }
171
+
154
172
  /**
155
173
  * Set the cached lint results for a given file path, after removing any
156
174
  * information that will be both unnecessary and difficult to serialize.
@@ -158,7 +176,7 @@ class LintResultCache {
158
176
  * applied), to prevent potentially incorrect results if fixes are not
159
177
  * written to disk.
160
178
  * @param {string} filePath The file for which to set lint results.
161
- * @param {ConfigArray} config The config of the file.
179
+ * @param {Config} config The config of the file.
162
180
  * @param {Object} result The lint result to be set for the file.
163
181
  * @returns {void}
164
182
  */
@@ -29,6 +29,7 @@ const createDebug = require("debug");
29
29
 
30
30
  const Minimatch = minimatch.Minimatch;
31
31
  const MINIMATCH_OPTIONS = { dot: true };
32
+ const hrtimeBigint = process.hrtime.bigint;
32
33
 
33
34
  //-----------------------------------------------------------------------------
34
35
  // Types
@@ -55,13 +56,13 @@ const MINIMATCH_OPTIONS = { dot: true };
55
56
  */
56
57
 
57
58
  //------------------------------------------------------------------------------
58
- // Internal Helpers
59
+ // Debug Helpers
59
60
  //------------------------------------------------------------------------------
60
61
 
61
- const hrtimeBigint = process.hrtime.bigint;
62
-
62
+ // Add %t formatter to print bigint nanosecond times in milliseconds.
63
63
  createDebug.formatters.t = timeDiff =>
64
64
  `${(timeDiff + 500_000n) / 1_000_000n} ms`;
65
+
65
66
  const debug = createDebug(
66
67
  `eslint:eslint-helpers${isMainThread ? "" : `:thread-${threadId}`}`,
67
68
  );
@@ -1437,6 +1438,8 @@ function createConfigLoader(
1437
1438
  //-----------------------------------------------------------------------------
1438
1439
 
1439
1440
  module.exports = {
1441
+ createDebug,
1442
+
1440
1443
  findFiles,
1441
1444
 
1442
1445
  isNonEmptyString,
@@ -19,6 +19,8 @@ const { version } = require("../../package.json");
19
19
  const { defaultConfig } = require("../config/default-config");
20
20
 
21
21
  const {
22
+ createDebug,
23
+
22
24
  findFiles,
23
25
  getCacheFile,
24
26
 
@@ -51,11 +53,6 @@ const {
51
53
  } = require("../shared/naming.js");
52
54
  const { resolve } = require("../shared/relative-module-resolver.js");
53
55
 
54
- /*
55
- * This is necessary to allow overwriting writeFile for testing purposes.
56
- * We can just use fs/promises once we drop Node.js 12 support.
57
- */
58
-
59
56
  //------------------------------------------------------------------------------
60
57
  // Typedefs
61
58
  //------------------------------------------------------------------------------
@@ -106,7 +103,9 @@ const { resolve } = require("../shared/relative-module-resolver.js");
106
103
  // Helpers
107
104
  //------------------------------------------------------------------------------
108
105
 
109
- const debug = require("debug")("eslint:eslint");
106
+ const hrtimeBigint = process.hrtime.bigint;
107
+
108
+ const debug = createDebug("eslint:eslint");
110
109
  const privateMembers = new WeakMap();
111
110
  const removedFormatters = new Set([
112
111
  "checkstyle",
@@ -279,36 +278,155 @@ function createExtraneousResultsError(cause) {
279
278
  * Maximum number of files assumed to be best handled by one worker thread.
280
279
  * This value is a heuristic estimation that can be adjusted if required.
281
280
  */
282
- const AUTO_FILES_PER_WORKER = 35;
281
+ const AUTO_FILES_PER_WORKER = 50;
282
+
283
+ /**
284
+ * Calculates the number of worker threads to run for "auto" concurrency depending on the number of
285
+ * files that need to be processed.
286
+ *
287
+ * The number of worker threads is calculated as the number of files that need to be processed
288
+ * (`processableFileCount`) divided by the number of files assumed to be best handled by one worker
289
+ * thread (`AUTO_FILES_PER_WORKER`), rounded up to the next integer.
290
+ * Two adjustments are made to this calculation: first, the number of workers is capped at half the
291
+ * number of available CPU cores (`maxWorkers`); second, a value of 1 is converted to 0.
292
+ * The following table shows the relationship between the number of files to be processed and the
293
+ * number of workers:
294
+ *
295
+ * Files to be processed | Workers
296
+ * -------------------------------------------------------------------|-----------------
297
+ * 0 | 0
298
+ * 1, 2, …, AUTO_FILES_PER_WORKER | 0 (there's no 1)
299
+ * AUTO_FILES_PER_WORKER + 1, …, AUTO_FILES_PER_WORKER * 2 | 2
300
+ * AUTO_FILES_PER_WORKER * 2 + 1, …, AUTO_FILES_PER_WORKER * 3 | 3
301
+ * ⋯ | ⋯
302
+ * AUTO_FILES_PER_WORKER * (𝑛 - 1) + 1, …, AUTO_FILES_PER_WORKER * 𝑛 | 𝑛
303
+ * ⋯ | ⋯
304
+ * AUTO_FILES_PER_WORKER * (maxWorkers - 1) + 1, … | maxWorkers
305
+ *
306
+ * The number of files to be processed should be determined by the calling function.
307
+ * @param {number} processableFileCount The number of files that need to be processed.
308
+ * @param {number} maxWorkers The maximum number of workers to run.
309
+ * @returns {number} The number of worker threads to run.
310
+ */
311
+ function getWorkerCountFor(processableFileCount, maxWorkers) {
312
+ let workerCount = Math.ceil(processableFileCount / AUTO_FILES_PER_WORKER);
313
+ if (workerCount > maxWorkers) {
314
+ workerCount = maxWorkers;
315
+ }
316
+ if (workerCount <= 1) {
317
+ workerCount = 0;
318
+ }
319
+ return workerCount;
320
+ }
321
+
322
+ /**
323
+ * Returns true if a file has no valid cached results or if it needs to be reprocessed because there are violations that may need fixing.
324
+ * This function will access the filesystem.
325
+ * @param {LintResultCache} lintResultCache The lint result cache.
326
+ * @param {boolean} fix The fix option.
327
+ * @param {string} filePath The file for which to retrieve lint results.
328
+ * @param {Config} config The config of the file.
329
+ * @returns {boolean} True if the file needs to be reprocessed.
330
+ */
331
+ function needsReprocessing(lintResultCache, fix, filePath, config) {
332
+ const results = lintResultCache.getValidCachedLintResults(filePath, config);
333
+
334
+ // This reflects the reprocessing logic of the `lintFile` helper function.
335
+ return !results || (fix && results.messages && results.messages.length > 0);
336
+ }
337
+
338
+ /**
339
+ * Calculates the number of worker threads to run for "auto" concurrency.
340
+ *
341
+ * The number of worker threads depends on the number files that need to be processed.
342
+ * Typically, this includes all non-ignored files.
343
+ * In a cached run with "metadata" strategy, files with a valid cached result aren't counted.
344
+ * @param {ESLint} eslint ESLint instance.
345
+ * @param {string[]} filePaths File paths to lint.
346
+ * @param {number} maxWorkers The maximum number of workers to run.
347
+ * @returns {number} The number of worker threads to run for "auto" concurrency.
348
+ */
349
+ function calculateAutoWorkerCount(eslint, filePaths, maxWorkers) {
350
+ const startTime = hrtimeBigint();
351
+ const {
352
+ configLoader,
353
+ lintResultCache,
354
+ options: { cacheStrategy, fix },
355
+ } = privateMembers.get(eslint);
356
+ /** True if cache is not used or if strategy is "content". */
357
+ const countAllMatched = !lintResultCache || cacheStrategy === "content";
358
+
359
+ let processableFileCount = 0;
360
+ let remainingFiles = filePaths.length;
361
+
362
+ /** The number of workers if none of the remaining files were to be counted. */
363
+ let lowWorkerCount = 0;
364
+
365
+ /*
366
+ * Rather than counting all files to be processed in advance, we stop iterating as soon as we reach
367
+ * a point where adding more files doesn't change the number of workers anymore.
368
+ */
369
+ for (const filePath of filePaths) {
370
+ /** The number of workers if all of the remaining files were to be counted. */
371
+ const highWorkerCount = getWorkerCountFor(
372
+ processableFileCount + remainingFiles,
373
+ maxWorkers,
374
+ );
375
+ if (lowWorkerCount >= highWorkerCount) {
376
+ // The highest possible number of workers has been reached, so stop counting.
377
+ break;
378
+ }
379
+ remainingFiles--;
380
+ const configs = configLoader.getCachedConfigArrayForFile(filePath);
381
+ const config = configs.getConfig(filePath);
382
+ if (!config) {
383
+ // file is ignored
384
+ continue;
385
+ }
386
+ if (
387
+ countAllMatched ||
388
+ needsReprocessing(lintResultCache, fix, filePath, config)
389
+ ) {
390
+ processableFileCount++;
391
+ lowWorkerCount = getWorkerCountFor(
392
+ processableFileCount,
393
+ maxWorkers,
394
+ );
395
+ }
396
+ }
397
+ debug(
398
+ "%d file(s) to process counted in %t",
399
+ processableFileCount,
400
+ hrtimeBigint() - startTime,
401
+ );
402
+ return lowWorkerCount;
403
+ }
283
404
 
284
405
  /**
285
406
  * Calculates the number of workers to run based on the concurrency setting and the number of files to lint.
286
- * @param {number | "auto" | "off"} concurrency The normalized concurrency setting.
287
- * @param {number} fileCount The number of files to be linted.
407
+ * @param {ESLint} eslint The ESLint instance.
408
+ * @param {string[]} filePaths File paths to lint.
288
409
  * @param {{ availableParallelism: () => number }} [os] Node.js `os` module, or a mock for testing.
289
410
  * @returns {number} The effective number of worker threads to be started. A value of zero disables multithread linting.
290
411
  */
291
412
  function calculateWorkerCount(
292
- concurrency,
293
- fileCount,
413
+ eslint,
414
+ filePaths,
294
415
  { availableParallelism } = os,
295
416
  ) {
296
- let workerCount;
417
+ const { concurrency } = privateMembers.get(eslint).options;
297
418
  switch (concurrency) {
298
419
  case "off":
299
420
  return 0;
300
421
  case "auto": {
301
- workerCount = Math.min(
302
- availableParallelism() >> 1,
303
- Math.ceil(fileCount / AUTO_FILES_PER_WORKER),
304
- );
305
- break;
422
+ const maxWorkers = availableParallelism() >> 1;
423
+ return calculateAutoWorkerCount(eslint, filePaths, maxWorkers);
424
+ }
425
+ default: {
426
+ const workerCount = Math.min(concurrency, filePaths.length);
427
+ return workerCount > 1 ? workerCount : 0;
306
428
  }
307
- default:
308
- workerCount = Math.min(concurrency, fileCount);
309
- break;
310
429
  }
311
- return workerCount > 1 ? workerCount : 0;
312
430
  }
313
431
 
314
432
  // Used internally. Do not expose.
@@ -360,7 +478,6 @@ async function runWorkers(
360
478
  },
361
479
  };
362
480
 
363
- const hrtimeBigint = process.hrtime.bigint;
364
481
  let worstNetLintingRatio = 1;
365
482
 
366
483
  /**
@@ -859,16 +976,11 @@ class ESLint {
859
976
 
860
977
  debug(`Using file patterns: ${normalizedPatterns}`);
861
978
 
862
- const {
863
- cache,
864
- concurrency,
865
- cwd,
866
- globInputPaths,
867
- errorOnUnmatchedPattern,
868
- } = eslintOptions;
979
+ const { concurrency, cwd, globInputPaths, errorOnUnmatchedPattern } =
980
+ eslintOptions;
869
981
 
870
982
  // Delete cache file; should this be done here?
871
- if (!cache && cacheFilePath) {
983
+ if (!lintResultCache && cacheFilePath) {
872
984
  debug(`Deleting cache file at ${cacheFilePath}`);
873
985
 
874
986
  try {
@@ -882,7 +994,7 @@ class ESLint {
882
994
  }
883
995
  }
884
996
 
885
- const startTime = Date.now();
997
+ const startTime = hrtimeBigint();
886
998
  const filePaths = await findFiles({
887
999
  patterns: normalizedPatterns,
888
1000
  cwd,
@@ -891,7 +1003,9 @@ class ESLint {
891
1003
  errorOnUnmatchedPattern,
892
1004
  });
893
1005
  debug(
894
- `${filePaths.length} files found in: ${Date.now() - startTime}ms`,
1006
+ "%d file(s) found in %t",
1007
+ filePaths.length,
1008
+ hrtimeBigint() - startTime,
895
1009
  );
896
1010
 
897
1011
  /** @type {LintResult[]} */
@@ -899,8 +1013,8 @@ class ESLint {
899
1013
 
900
1014
  // The value of `module.exports.calculateWorkerCount` can be overridden in tests.
901
1015
  const workerCount = module.exports.calculateWorkerCount(
902
- concurrency,
903
- filePaths.length,
1016
+ this,
1017
+ filePaths,
904
1018
  );
905
1019
  if (workerCount) {
906
1020
  debug(`Linting using ${workerCount} worker thread(s).`);
@@ -999,7 +1113,7 @@ class ESLint {
999
1113
  stats,
1000
1114
  } = eslintOptions;
1001
1115
  const results = [];
1002
- const startTime = Date.now();
1116
+ const startTime = hrtimeBigint();
1003
1117
  const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
1004
1118
  const resolvedFilename = path.resolve(
1005
1119
  cwd,
@@ -1044,7 +1158,7 @@ class ESLint {
1044
1158
  );
1045
1159
  }
1046
1160
 
1047
- debug(`Linting complete in: ${Date.now() - startTime}ms`);
1161
+ debug("Linting complete in %t", hrtimeBigint() - startTime);
1048
1162
 
1049
1163
  return processLintReport(this, results);
1050
1164
  }
@@ -1185,7 +1299,7 @@ class ESLint {
1185
1299
  * @returns {Promise<string|undefined>} The path to the config file being used or
1186
1300
  * `undefined` if no config file is being used.
1187
1301
  */
1188
- findConfigFile(filePath) {
1302
+ async findConfigFile(filePath) {
1189
1303
  const options = privateMembers.get(this).options;
1190
1304
 
1191
1305
  /*
@@ -17,9 +17,9 @@ require("node:module").enableCompileCache?.();
17
17
  //------------------------------------------------------------------------------
18
18
 
19
19
  const { parentPort, threadId, workerData } = require("node:worker_threads");
20
- const createDebug = require("debug");
21
20
  const {
22
21
  createConfigLoader,
22
+ createDebug,
23
23
  createDefaultConfigs,
24
24
  createLinter,
25
25
  createLintResultCache,
@@ -52,8 +52,6 @@ const depsLoadedTime = hrtimeBigint();
52
52
  //------------------------------------------------------------------------------
53
53
 
54
54
  const debug = createDebug(`eslint:worker:thread-${threadId}`);
55
- createDebug.formatters.t = timeDiff =>
56
- `${(timeDiff + 500_000n) / 1_000_000n} ms`;
57
55
 
58
56
  //------------------------------------------------------------------------------
59
57
  // Main
@@ -90,7 +90,7 @@ class ESQueryParsedSelector {
90
90
  }
91
91
 
92
92
  /**
93
- * Compares this selector's specifity to another selector for sorting purposes.
93
+ * Compares this selector's specificity to another selector for sorting purposes.
94
94
  * @param {ESQueryParsedSelector} otherSelector The selector to compare against
95
95
  * @returns {number}
96
96
  * a value less than 0 if this selector is less specific than otherSelector
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -18,7 +18,7 @@ module.exports = {
18
18
  message: "Formatting rules are being moved out of ESLint core.",
19
19
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
20
20
  deprecatedSince: "8.53.0",
21
- availableUntil: "10.0.0",
21
+ availableUntil: "11.0.0",
22
22
  replacedBy: [
23
23
  {
24
24
  message:
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -35,7 +35,7 @@ module.exports = {
35
35
  message: "Formatting rules are being moved out of ESLint core.",
36
36
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
37
37
  deprecatedSince: "8.53.0",
38
- availableUntil: "10.0.0",
38
+ availableUntil: "11.0.0",
39
39
  replacedBy: [
40
40
  {
41
41
  message:
@@ -22,7 +22,7 @@ module.exports = {
22
22
  message: "Formatting rules are being moved out of ESLint core.",
23
23
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
24
24
  deprecatedSince: "8.53.0",
25
- availableUntil: "10.0.0",
25
+ availableUntil: "11.0.0",
26
26
  replacedBy: [
27
27
  {
28
28
  message:
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -78,7 +78,7 @@ module.exports = {
78
78
  message: "Formatting rules are being moved out of ESLint core.",
79
79
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
80
80
  deprecatedSince: "8.53.0",
81
- availableUntil: "10.0.0",
81
+ availableUntil: "11.0.0",
82
82
  replacedBy: [
83
83
  {
84
84
  message:
@@ -18,7 +18,7 @@ module.exports = {
18
18
  message: "Formatting rules are being moved out of ESLint core.",
19
19
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
20
20
  deprecatedSince: "8.53.0",
21
- availableUntil: "10.0.0",
21
+ availableUntil: "11.0.0",
22
22
  replacedBy: [
23
23
  {
24
24
  message:
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -18,7 +18,7 @@ module.exports = {
18
18
  message: "Formatting rules are being moved out of ESLint core.",
19
19
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
20
20
  deprecatedSince: "8.53.0",
21
- availableUntil: "10.0.0",
21
+ availableUntil: "11.0.0",
22
22
  replacedBy: [
23
23
  {
24
24
  message:
@@ -19,7 +19,7 @@ module.exports = {
19
19
  message: "Formatting rules are being moved out of ESLint core.",
20
20
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
21
21
  deprecatedSince: "8.53.0",
22
- availableUntil: "10.0.0",
22
+ availableUntil: "11.0.0",
23
23
  replacedBy: [
24
24
  {
25
25
  message:
@@ -16,7 +16,7 @@ module.exports = {
16
16
  message: "Formatting rules are being moved out of ESLint core.",
17
17
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
18
18
  deprecatedSince: "8.53.0",
19
- availableUntil: "10.0.0",
19
+ availableUntil: "11.0.0",
20
20
  replacedBy: [
21
21
  {
22
22
  message:
@@ -23,7 +23,7 @@ module.exports = {
23
23
  message: "Formatting rules are being moved out of ESLint core.",
24
24
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
25
25
  deprecatedSince: "8.53.0",
26
- availableUntil: "10.0.0",
26
+ availableUntil: "11.0.0",
27
27
  replacedBy: [
28
28
  {
29
29
  message:
@@ -105,7 +105,7 @@ module.exports = {
105
105
  * Check if open space is present in a function name
106
106
  * @param {ASTNode} node node to evaluate
107
107
  * @param {Token} leftToken The last token of the callee. This may be the closing parenthesis that encloses the callee.
108
- * @param {Token} rightToken Tha first token of the arguments. this is the opening parenthesis that encloses the arguments.
108
+ * @param {Token} rightToken The first token of the arguments. this is the opening parenthesis that encloses the arguments.
109
109
  * @returns {void}
110
110
  * @private
111
111
  */
@@ -17,7 +17,7 @@ module.exports = {
17
17
  message: "Formatting rules are being moved out of ESLint core.",
18
18
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
19
19
  deprecatedSince: "8.53.0",
20
- availableUntil: "10.0.0",
20
+ availableUntil: "11.0.0",
21
21
  replacedBy: [
22
22
  {
23
23
  message:
@@ -22,7 +22,7 @@ module.exports = {
22
22
  message: "Formatting rules are being moved out of ESLint core.",
23
23
  url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
24
24
  deprecatedSince: "8.53.0",
25
- availableUntil: "10.0.0",
25
+ availableUntil: "11.0.0",
26
26
  replacedBy: [
27
27
  {
28
28
  message: