eslint 9.39.1 → 10.0.0-alpha.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.
- package/README.md +3 -3
- package/bin/eslint.js +1 -2
- package/lib/api.js +4 -15
- package/lib/cli.js +14 -56
- package/lib/config/config-loader.js +6 -154
- package/lib/eslint/eslint-helpers.js +5 -8
- package/lib/eslint/eslint.js +1 -1
- package/lib/eslint/index.js +0 -2
- package/lib/languages/js/source-code/source-code.js +39 -87
- package/lib/languages/js/source-code/token-store/utils.js +29 -8
- package/lib/linter/apply-disable-directives.js +0 -1
- package/lib/linter/file-context.js +0 -56
- package/lib/linter/file-report.js +0 -4
- package/lib/linter/linter.js +45 -1086
- package/lib/linter/rule-fixer.js +30 -0
- package/lib/options.js +62 -182
- package/lib/rule-tester/rule-tester.js +255 -194
- package/lib/rules/dot-notation.js +2 -2
- package/lib/rules/func-names.js +2 -0
- package/lib/rules/no-eval.js +1 -1
- package/lib/rules/no-invalid-regexp.js +1 -0
- package/lib/rules/no-shadow-restricted-names.js +1 -1
- package/lib/rules/no-unassigned-vars.js +1 -1
- package/lib/rules/no-useless-assignment.js +1 -1
- package/lib/rules/preserve-caught-error.js +1 -1
- package/lib/rules/radix.js +25 -48
- package/lib/services/parser-service.js +0 -1
- package/lib/services/processor-service.js +0 -1
- package/lib/services/warning-service.js +0 -11
- package/lib/shared/flags.js +0 -19
- package/lib/shared/translate-cli-options.js +106 -164
- package/lib/types/index.d.ts +7 -60
- package/lib/types/rules.d.ts +11 -2
- package/lib/types/use-at-your-own-risk.d.ts +1 -54
- package/lib/unsupported-api.js +3 -6
- package/package.json +14 -19
- package/conf/default-cli-options.js +0 -32
- package/lib/cli-engine/cli-engine.js +0 -1109
- package/lib/cli-engine/file-enumerator.js +0 -541
- package/lib/cli-engine/index.js +0 -7
- package/lib/cli-engine/load-rules.js +0 -46
- package/lib/eslint/legacy-eslint.js +0 -786
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
|
|
|
42
42
|
|
|
43
43
|
## Installation and Usage
|
|
44
44
|
|
|
45
|
-
Prerequisites: [Node.js](https://nodejs.org/) (`^
|
|
45
|
+
Prerequisites: [Node.js](https://nodejs.org/) (`^20.19.0`, `^22.13.0`, or `>=24`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
|
|
46
46
|
|
|
47
47
|
You can install and configure ESLint using this command:
|
|
48
48
|
|
|
@@ -341,9 +341,9 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
|
|
341
341
|
|
|
342
342
|
<h3>Platinum Sponsors</h3>
|
|
343
343
|
<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>
|
|
344
|
-
<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://
|
|
344
|
+
<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://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
|
|
345
345
|
<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/2d6c3b6/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>
|
|
346
|
-
<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://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" 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>
|
|
346
|
+
<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://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" 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>
|
|
347
347
|
<h3>Technology Sponsors</h3>
|
|
348
348
|
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.
|
|
349
349
|
<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>
|
package/bin/eslint.js
CHANGED
|
@@ -174,8 +174,7 @@ ${getErrorMessage(error)}`;
|
|
|
174
174
|
const cli = require("../lib/cli");
|
|
175
175
|
const exitCode = await cli.execute(
|
|
176
176
|
process.argv,
|
|
177
|
-
process.argv.includes("--stdin") ? await readStdin() :
|
|
178
|
-
true,
|
|
177
|
+
process.argv.includes("--stdin") ? await readStdin() : void 0,
|
|
179
178
|
);
|
|
180
179
|
|
|
181
180
|
/*
|
package/lib/api.js
CHANGED
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
// Requirements
|
|
10
10
|
//-----------------------------------------------------------------------------
|
|
11
11
|
|
|
12
|
-
const { ESLint
|
|
13
|
-
const { LegacyESLint } = require("./eslint/legacy-eslint");
|
|
12
|
+
const { ESLint } = require("./eslint/eslint");
|
|
14
13
|
const { Linter } = require("./linter");
|
|
15
14
|
const { RuleTester } = require("./rule-tester");
|
|
16
15
|
const { SourceCode } = require("./languages/js/source-code");
|
|
@@ -21,20 +20,10 @@ const { SourceCode } = require("./languages/js/source-code");
|
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* Loads the correct ESLint constructor given the options.
|
|
24
|
-
* @
|
|
25
|
-
* @param {boolean} [options.useFlatConfig] Whether or not to use a flat config
|
|
26
|
-
* @returns {Promise<ESLint|LegacyESLint>} The ESLint constructor
|
|
23
|
+
* @returns {Promise<ESLint>} The ESLint constructor
|
|
27
24
|
*/
|
|
28
|
-
async function loadESLint(
|
|
29
|
-
|
|
30
|
-
* Note: The v8.x version of this function also accepted a `cwd` option, but
|
|
31
|
-
* it is not used in this implementation so we silently ignore it.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
const shouldESLintUseFlatConfig =
|
|
35
|
-
useFlatConfig ?? (await shouldUseFlatConfig());
|
|
36
|
-
|
|
37
|
-
return shouldESLintUseFlatConfig ? ESLint : LegacyESLint;
|
|
25
|
+
async function loadESLint() {
|
|
26
|
+
return ESLint;
|
|
38
27
|
}
|
|
39
28
|
|
|
40
29
|
//-----------------------------------------------------------------------------
|
package/lib/cli.js
CHANGED
|
@@ -19,12 +19,7 @@ const fs = require("node:fs"),
|
|
|
19
19
|
{ mkdir, stat, writeFile } = require("node:fs/promises"),
|
|
20
20
|
path = require("node:path"),
|
|
21
21
|
{ pathToFileURL } = require("node:url"),
|
|
22
|
-
{
|
|
23
|
-
{
|
|
24
|
-
ESLint,
|
|
25
|
-
shouldUseFlatConfig,
|
|
26
|
-
locateConfigFileToUse,
|
|
27
|
-
} = require("./eslint/eslint"),
|
|
22
|
+
{ ESLint, locateConfigFileToUse } = require("./eslint/eslint"),
|
|
28
23
|
createCLIOptions = require("./options"),
|
|
29
24
|
log = require("./shared/logging"),
|
|
30
25
|
RuntimeInfo = require("./shared/runtime-info"),
|
|
@@ -76,7 +71,7 @@ function createOptionsModule(options) {
|
|
|
76
71
|
).href;
|
|
77
72
|
const optionsSrc =
|
|
78
73
|
`import translateOptions from ${JSON.stringify(translateOptionsFileURL)};\n` +
|
|
79
|
-
`export default await translateOptions(${JSON.stringify(options)}
|
|
74
|
+
`export default await translateOptions(${JSON.stringify(options)});\n`;
|
|
80
75
|
|
|
81
76
|
// Base64 encoding is typically shorter than URL encoding
|
|
82
77
|
return new URL(
|
|
@@ -199,32 +194,14 @@ const cli = {
|
|
|
199
194
|
* Executes the CLI based on an array of arguments that is passed in.
|
|
200
195
|
* @param {string|Array|Object} args The arguments to process.
|
|
201
196
|
* @param {string} [text] The text to lint (used for TTY).
|
|
202
|
-
* @param {boolean} [allowFlatConfig=true] Whether or not to allow flat config.
|
|
203
197
|
* @returns {Promise<number>} The exit code for the operation.
|
|
204
198
|
*/
|
|
205
|
-
async execute(args, text
|
|
199
|
+
async execute(args, text) {
|
|
206
200
|
if (Array.isArray(args)) {
|
|
207
201
|
debug("CLI args: %o", args.slice(2));
|
|
208
202
|
}
|
|
209
203
|
|
|
210
|
-
|
|
211
|
-
* Before doing anything, we need to see if we are using a
|
|
212
|
-
* flat config file. If so, then we need to change the way command
|
|
213
|
-
* line args are parsed. This is temporary, and when we fully
|
|
214
|
-
* switch to flat config we can remove this logic.
|
|
215
|
-
*/
|
|
216
|
-
|
|
217
|
-
const usingFlatConfig =
|
|
218
|
-
allowFlatConfig && (await shouldUseFlatConfig());
|
|
219
|
-
|
|
220
|
-
debug("Using flat config?", usingFlatConfig);
|
|
221
|
-
|
|
222
|
-
if (allowFlatConfig && !usingFlatConfig) {
|
|
223
|
-
const { WarningService } = require("./services/warning-service");
|
|
224
|
-
new WarningService().emitESLintRCWarning();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const CLIOptions = createCLIOptions(usingFlatConfig);
|
|
204
|
+
const CLIOptions = createCLIOptions();
|
|
228
205
|
|
|
229
206
|
/** @type {ParsedCLIOptions} */
|
|
230
207
|
let options;
|
|
@@ -233,16 +210,7 @@ const cli = {
|
|
|
233
210
|
options = CLIOptions.parse(args);
|
|
234
211
|
validateConcurrency(options.concurrency);
|
|
235
212
|
} catch (error) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
let errorMessage = error.message;
|
|
239
|
-
|
|
240
|
-
if (usingFlatConfig) {
|
|
241
|
-
errorMessage +=
|
|
242
|
-
"\nYou're using eslint.config.js, some command line flags are no longer available. Please see https://eslint.org/docs/latest/use/command-line-interface for details.";
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
log.error(errorMessage);
|
|
213
|
+
log.error(error.message);
|
|
246
214
|
return 2;
|
|
247
215
|
}
|
|
248
216
|
|
|
@@ -282,9 +250,7 @@ const cli = {
|
|
|
282
250
|
return 2;
|
|
283
251
|
}
|
|
284
252
|
|
|
285
|
-
const engine =
|
|
286
|
-
? new ESLint(await translateOptions(options, "flat"))
|
|
287
|
-
: new LegacyESLint(await translateOptions(options));
|
|
253
|
+
const engine = new ESLint(await translateOptions(options));
|
|
288
254
|
const fileConfig = await engine.calculateConfigForFile(
|
|
289
255
|
options.printConfig,
|
|
290
256
|
);
|
|
@@ -299,7 +265,7 @@ const cli = {
|
|
|
299
265
|
);
|
|
300
266
|
|
|
301
267
|
try {
|
|
302
|
-
const flatOptions = await translateOptions(options
|
|
268
|
+
const flatOptions = await translateOptions(options);
|
|
303
269
|
const spawn = require("cross-spawn");
|
|
304
270
|
const flags = await cli.calculateInspectConfigFlags(
|
|
305
271
|
flatOptions.overrideConfigFile,
|
|
@@ -349,7 +315,7 @@ const cli = {
|
|
|
349
315
|
return 2;
|
|
350
316
|
}
|
|
351
317
|
|
|
352
|
-
if (
|
|
318
|
+
if (options.ext) {
|
|
353
319
|
// Passing `--ext ""` results in `options.ext` being an empty array.
|
|
354
320
|
if (options.ext.length === 0) {
|
|
355
321
|
log.error("The --ext option value cannot be empty.");
|
|
@@ -400,29 +366,21 @@ const cli = {
|
|
|
400
366
|
return 2;
|
|
401
367
|
}
|
|
402
368
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
/** @type {ESLint|LegacyESLint} */
|
|
369
|
+
/** @type {ESLint} */
|
|
406
370
|
let engine;
|
|
407
371
|
|
|
408
|
-
if (options.concurrency
|
|
372
|
+
if (options.concurrency !== "off") {
|
|
409
373
|
const optionsURL = createOptionsModule(options);
|
|
410
374
|
engine = await ESLint.fromOptionsModule(optionsURL);
|
|
411
375
|
} else {
|
|
412
|
-
const eslintOptions = await translateOptions(
|
|
413
|
-
|
|
414
|
-
usingFlatConfig ? "flat" : "eslintrc",
|
|
415
|
-
);
|
|
416
|
-
engine = new ActiveESLint(eslintOptions);
|
|
376
|
+
const eslintOptions = await translateOptions(options);
|
|
377
|
+
engine = new ESLint(eslintOptions);
|
|
417
378
|
}
|
|
418
379
|
let results;
|
|
419
380
|
|
|
420
381
|
if (useStdin) {
|
|
421
382
|
results = await engine.lintText(text, {
|
|
422
383
|
filePath: options.stdinFilename,
|
|
423
|
-
|
|
424
|
-
// flatConfig respects CLI flag and constructor warnIgnored, eslintrc forces true for backwards compatibility
|
|
425
|
-
warnIgnored: usingFlatConfig ? void 0 : true,
|
|
426
384
|
});
|
|
427
385
|
} else {
|
|
428
386
|
results = await engine.lintFiles(files);
|
|
@@ -430,7 +388,7 @@ const cli = {
|
|
|
430
388
|
|
|
431
389
|
if (options.fix) {
|
|
432
390
|
debug("Fix mode enabled - applying fixes");
|
|
433
|
-
await
|
|
391
|
+
await ESLint.outputFixes(results);
|
|
434
392
|
}
|
|
435
393
|
|
|
436
394
|
let unusedSuppressions = {};
|
|
@@ -489,7 +447,7 @@ const cli = {
|
|
|
489
447
|
|
|
490
448
|
if (options.quiet) {
|
|
491
449
|
debug("Quiet mode enabled - filtering out warnings");
|
|
492
|
-
resultsToPrint =
|
|
450
|
+
resultsToPrint = ESLint.getErrorResults(resultsToPrint);
|
|
493
451
|
}
|
|
494
452
|
|
|
495
453
|
const resultCounts = countErrors(results);
|
|
@@ -147,8 +147,11 @@ async function loadTypeScriptConfigFileWithJiti(filePath, fileURL, mtime) {
|
|
|
147
147
|
);
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
|
|
150
|
+
// Ensure the version is at least 2.2.0.
|
|
151
|
+
const [jitiMajor, jitiMinor] = jitiVersion
|
|
152
|
+
.split(".")
|
|
153
|
+
.map(versionPart => Number(versionPart));
|
|
154
|
+
if (jitiMajor < 2 || (jitiMajor === 2 && jitiMinor < 2)) {
|
|
152
155
|
throw new Error(
|
|
153
156
|
"You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features.",
|
|
154
157
|
);
|
|
@@ -162,10 +165,6 @@ async function loadTypeScriptConfigFileWithJiti(filePath, fileURL, mtime) {
|
|
|
162
165
|
moduleCache: false,
|
|
163
166
|
};
|
|
164
167
|
|
|
165
|
-
if (jitiVersion.startsWith("2.1.")) {
|
|
166
|
-
jitiOptions.interopDefault = false;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
168
|
const jiti = createJiti(__filename, jitiOptions);
|
|
170
169
|
const config = await jiti.import(fileURL.href);
|
|
171
170
|
|
|
@@ -666,151 +665,4 @@ class ConfigLoader {
|
|
|
666
665
|
}
|
|
667
666
|
}
|
|
668
667
|
|
|
669
|
-
|
|
670
|
-
* Encapsulates the loading and caching of configuration files when looking up
|
|
671
|
-
* from the current working directory.
|
|
672
|
-
*/
|
|
673
|
-
class LegacyConfigLoader extends ConfigLoader {
|
|
674
|
-
/**
|
|
675
|
-
* The options to use when loading configuration files.
|
|
676
|
-
* @type {ConfigLoaderOptions}
|
|
677
|
-
*/
|
|
678
|
-
#options;
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* The cached config file path for this instance.
|
|
682
|
-
* @type {Promise<{configFilePath:string,basePath:string}|undefined>}
|
|
683
|
-
*/
|
|
684
|
-
#configFilePath;
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* The cached config array for this instance.
|
|
688
|
-
* @type {FlatConfigArray|Promise<FlatConfigArray>}
|
|
689
|
-
*/
|
|
690
|
-
#configArray;
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* Creates a new instance.
|
|
694
|
-
* @param {ConfigLoaderOptions} options The options to use when loading configuration files.
|
|
695
|
-
*/
|
|
696
|
-
constructor(options) {
|
|
697
|
-
const normalizedOptions = options.warningService
|
|
698
|
-
? options
|
|
699
|
-
: { ...options, warningService: new WarningService() };
|
|
700
|
-
super(normalizedOptions);
|
|
701
|
-
this.#options = normalizedOptions;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
/**
|
|
705
|
-
* Determines which config file to use. This is determined by seeing if an
|
|
706
|
-
* override config file was specified, and if so, using it; otherwise, as long
|
|
707
|
-
* as override config file is not explicitly set to `false`, it will search
|
|
708
|
-
* upwards from the cwd for a file named `eslint.config.js`.
|
|
709
|
-
* @returns {Promise<{configFilePath:string|undefined,basePath:string}>} Location information for
|
|
710
|
-
* the config file.
|
|
711
|
-
*/
|
|
712
|
-
#locateConfigFileToUse() {
|
|
713
|
-
if (!this.#configFilePath) {
|
|
714
|
-
this.#configFilePath = ConfigLoader.locateConfigFileToUse({
|
|
715
|
-
useConfigFile: this.#options.configFile,
|
|
716
|
-
cwd: this.#options.cwd,
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
return this.#configFilePath;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
/**
|
|
724
|
-
* Calculates the config array for this run based on inputs.
|
|
725
|
-
* @param {string} configFilePath The absolute path to the config file to use if not overridden.
|
|
726
|
-
* @param {string} basePath The base path to use for relative paths in the config file.
|
|
727
|
-
* @returns {Promise<FlatConfigArray>} The config array for `eslint`.
|
|
728
|
-
*/
|
|
729
|
-
async #calculateConfigArray(configFilePath, basePath) {
|
|
730
|
-
// check for cached version first
|
|
731
|
-
if (this.#configArray) {
|
|
732
|
-
return this.#configArray;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// ensure `ConfigLoader.calculateConfigArray` is called only once
|
|
736
|
-
this.#configArray = ConfigLoader.calculateConfigArray(
|
|
737
|
-
configFilePath,
|
|
738
|
-
basePath,
|
|
739
|
-
this.#options,
|
|
740
|
-
);
|
|
741
|
-
|
|
742
|
-
// Unwrap the promise. This is primarily for the sync `getCachedConfigArrayForPath` method.
|
|
743
|
-
this.#configArray = await this.#configArray;
|
|
744
|
-
|
|
745
|
-
return this.#configArray;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
/**
|
|
749
|
-
* Returns the config file path for the given directory. This will either use
|
|
750
|
-
* the override config file that was specified in the constructor options or
|
|
751
|
-
* search for a config file from the directory of the file being linted.
|
|
752
|
-
* @param {string} dirPath The directory path to get the config file path for.
|
|
753
|
-
* @returns {Promise<string|undefined>} The config file path or `undefined` if not found.
|
|
754
|
-
* @throws {Error} If `fileOrDirPath` is not a non-empty string.
|
|
755
|
-
* @throws {Error} If `fileOrDirPath` is not an absolute path.
|
|
756
|
-
*/
|
|
757
|
-
async findConfigFileForPath(dirPath) {
|
|
758
|
-
assertValidFilePath(dirPath);
|
|
759
|
-
|
|
760
|
-
const { configFilePath } = await this.#locateConfigFileToUse();
|
|
761
|
-
|
|
762
|
-
return configFilePath;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/**
|
|
766
|
-
* Returns a configuration object for the given file based on the CLI options.
|
|
767
|
-
* This is the same logic used by the ESLint CLI executable to determine
|
|
768
|
-
* configuration for each file it processes.
|
|
769
|
-
* @param {string} dirPath The path of the directory to retrieve config for.
|
|
770
|
-
* @returns {Promise<FlatConfigArray>} A configuration object for the file.
|
|
771
|
-
*/
|
|
772
|
-
async loadConfigArrayForDirectory(dirPath) {
|
|
773
|
-
assertValidFilePath(dirPath);
|
|
774
|
-
|
|
775
|
-
debug(`[Legacy]: Calculating config for ${dirPath}`);
|
|
776
|
-
|
|
777
|
-
const { configFilePath, basePath } =
|
|
778
|
-
await this.#locateConfigFileToUse();
|
|
779
|
-
|
|
780
|
-
debug(
|
|
781
|
-
`[Legacy]: Using config file ${configFilePath} and base path ${basePath}`,
|
|
782
|
-
);
|
|
783
|
-
return this.#calculateConfigArray(configFilePath, basePath);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
/**
|
|
787
|
-
* Returns a configuration array for the given directory based on the CLI options.
|
|
788
|
-
* This is a synchronous operation and does not read any files from disk. It's
|
|
789
|
-
* intended to be used in locations where we know the config file has already
|
|
790
|
-
* been loaded and we just need to get the configuration for a file.
|
|
791
|
-
* @param {string} dirPath The path of the directory to retrieve a config object for.
|
|
792
|
-
* @returns {FlatConfigArray} A configuration object for the file.
|
|
793
|
-
* @throws {Error} If `dirPath` is not a non-empty string.
|
|
794
|
-
* @throws {Error} If `dirPath` is not an absolute path.
|
|
795
|
-
* @throws {Error} If the config file was not already loaded.
|
|
796
|
-
*/
|
|
797
|
-
getCachedConfigArrayForPath(dirPath) {
|
|
798
|
-
assertValidFilePath(dirPath);
|
|
799
|
-
|
|
800
|
-
debug(`[Legacy]: Looking up cached config for ${dirPath}`);
|
|
801
|
-
|
|
802
|
-
if (!this.#configArray) {
|
|
803
|
-
throw new Error(`Could not find config file for ${dirPath}`);
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
if (typeof this.#configArray.then === "function") {
|
|
807
|
-
throw new Error(
|
|
808
|
-
`Config array for ${dirPath} has not yet been calculated or an error occurred during the calculation`,
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
return this.#configArray;
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
module.exports = { ConfigLoader, LegacyConfigLoader };
|
|
668
|
+
module.exports = { ConfigLoader };
|
|
@@ -20,7 +20,7 @@ const globParent = require("glob-parent");
|
|
|
20
20
|
const { Linter } = require("../linter");
|
|
21
21
|
const { getShorthandName } = require("../shared/naming");
|
|
22
22
|
const LintResultCache = require("../cli-engine/lint-result-cache");
|
|
23
|
-
const { ConfigLoader
|
|
23
|
+
const { ConfigLoader } = require("../config/config-loader");
|
|
24
24
|
const createDebug = require("debug");
|
|
25
25
|
|
|
26
26
|
//-----------------------------------------------------------------------------
|
|
@@ -247,7 +247,7 @@ async function globMatch({ basePath, pattern }) {
|
|
|
247
247
|
* to match.
|
|
248
248
|
* @param {Array<string>} options.rawPatterns An array of glob patterns
|
|
249
249
|
* as the user inputted them. Used for errors.
|
|
250
|
-
* @param {ConfigLoader
|
|
250
|
+
* @param {ConfigLoader} options.configLoader The config array to use for
|
|
251
251
|
* determining what to ignore.
|
|
252
252
|
* @param {boolean} options.errorOnUnmatchedPattern Determines if an error
|
|
253
253
|
* should be thrown when a pattern is unmatched.
|
|
@@ -425,7 +425,7 @@ async function throwErrorForUnmatchedPatterns({
|
|
|
425
425
|
* @param {Object} options The options for this function.
|
|
426
426
|
* @param {Map<string,GlobSearch>} options.searches
|
|
427
427
|
* A map of absolute path glob patterns to match.
|
|
428
|
-
* @param {ConfigLoader
|
|
428
|
+
* @param {ConfigLoader} options.configLoader The config loader to use for
|
|
429
429
|
* determining what to ignore.
|
|
430
430
|
* @param {boolean} options.errorOnUnmatchedPattern Determines if an
|
|
431
431
|
* unmatched glob pattern should throw an error.
|
|
@@ -506,7 +506,7 @@ async function globMultiSearch({
|
|
|
506
506
|
* @param {boolean} args.globInputPaths true to interpret glob patterns,
|
|
507
507
|
* false to not interpret glob patterns.
|
|
508
508
|
* @param {string} args.cwd The current working directory to find from.
|
|
509
|
-
* @param {ConfigLoader
|
|
509
|
+
* @param {ConfigLoader} args.configLoader The config loader for the current run.
|
|
510
510
|
* @param {boolean} args.errorOnUnmatchedPattern Determines if an unmatched pattern
|
|
511
511
|
* should throw an error.
|
|
512
512
|
* @returns {Promise<Array<string>>} The fully resolved file paths.
|
|
@@ -708,7 +708,6 @@ function createIgnoreResult(filePath, baseDir, configStatus) {
|
|
|
708
708
|
fatal: false,
|
|
709
709
|
severity: 1,
|
|
710
710
|
message,
|
|
711
|
-
nodeType: null,
|
|
712
711
|
},
|
|
713
712
|
],
|
|
714
713
|
suppressedMessages: [],
|
|
@@ -1428,9 +1427,7 @@ function createConfigLoader(
|
|
|
1428
1427
|
warningService,
|
|
1429
1428
|
};
|
|
1430
1429
|
|
|
1431
|
-
return
|
|
1432
|
-
? new ConfigLoader(configLoaderOptions)
|
|
1433
|
-
: new LegacyConfigLoader(configLoaderOptions);
|
|
1430
|
+
return new ConfigLoader(configLoaderOptions);
|
|
1434
1431
|
}
|
|
1435
1432
|
|
|
1436
1433
|
//-----------------------------------------------------------------------------
|
package/lib/eslint/eslint.js
CHANGED
|
@@ -1347,7 +1347,7 @@ class ESLint {
|
|
|
1347
1347
|
* @returns {Promise<boolean>} Whether flat config should be used.
|
|
1348
1348
|
*/
|
|
1349
1349
|
async function shouldUseFlatConfig() {
|
|
1350
|
-
return
|
|
1350
|
+
return true;
|
|
1351
1351
|
}
|
|
1352
1352
|
|
|
1353
1353
|
//------------------------------------------------------------------------------
|
package/lib/eslint/index.js
CHANGED
|
@@ -20,8 +20,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
|
|
|
20
20
|
VisitNodeStep,
|
|
21
21
|
CallMethodStep,
|
|
22
22
|
Directive,
|
|
23
|
-
} = require("@eslint/plugin-kit")
|
|
24
|
-
eslintScope = require("eslint-scope");
|
|
23
|
+
} = require("@eslint/plugin-kit");
|
|
25
24
|
|
|
26
25
|
//------------------------------------------------------------------------------
|
|
27
26
|
// Type Definitions
|
|
@@ -29,6 +28,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
|
|
|
29
28
|
|
|
30
29
|
/** @typedef {import("eslint-scope").Variable} Variable */
|
|
31
30
|
/** @typedef {import("eslint-scope").Scope} Scope */
|
|
31
|
+
/** @typedef {import("eslint-scope").ScopeManager} ScopeManager */
|
|
32
32
|
/** @typedef {import("@eslint/core").SourceCode} ISourceCode */
|
|
33
33
|
/** @typedef {import("@eslint/core").Directive} IDirective */
|
|
34
34
|
/** @typedef {import("@eslint/core").TraversalStep} ITraversalStep */
|
|
@@ -264,103 +264,37 @@ function findLineNumberBinarySearch(lineStartIndices, target) {
|
|
|
264
264
|
* Ensures that variables representing built-in properties of the Global Object,
|
|
265
265
|
* and any globals declared by special block comments, are present in the global
|
|
266
266
|
* scope.
|
|
267
|
-
* @param {
|
|
267
|
+
* @param {ScopeManager} scopeManager Scope manager.
|
|
268
268
|
* @param {Object|undefined} configGlobals The globals declared in configuration
|
|
269
269
|
* @param {Object|undefined} inlineGlobals The globals declared in the source code
|
|
270
270
|
* @returns {void}
|
|
271
271
|
*/
|
|
272
272
|
function addDeclaredGlobals(
|
|
273
|
-
|
|
274
|
-
configGlobals =
|
|
275
|
-
inlineGlobals =
|
|
273
|
+
scopeManager,
|
|
274
|
+
configGlobals = Object.create(null),
|
|
275
|
+
inlineGlobals = Object.create(null),
|
|
276
276
|
) {
|
|
277
|
-
|
|
278
|
-
for (const id of new Set([
|
|
279
|
-
...Object.keys(configGlobals),
|
|
280
|
-
...Object.keys(inlineGlobals),
|
|
281
|
-
])) {
|
|
282
|
-
/*
|
|
283
|
-
* `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
|
|
284
|
-
* typically be caught when validating a config anyway (validity for inline global comments is checked separately).
|
|
285
|
-
*/
|
|
286
|
-
const configValue =
|
|
287
|
-
configGlobals[id] === void 0
|
|
288
|
-
? void 0
|
|
289
|
-
: normalizeConfigGlobal(configGlobals[id]);
|
|
290
|
-
const commentValue = inlineGlobals[id] && inlineGlobals[id].value;
|
|
291
|
-
const value = commentValue || configValue;
|
|
292
|
-
const sourceComments = inlineGlobals[id] && inlineGlobals[id].comments;
|
|
293
|
-
|
|
294
|
-
if (value === "off") {
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
let variable = globalScope.set.get(id);
|
|
299
|
-
|
|
300
|
-
if (!variable) {
|
|
301
|
-
variable = new eslintScope.Variable(id, globalScope);
|
|
302
|
-
|
|
303
|
-
globalScope.variables.push(variable);
|
|
304
|
-
globalScope.set.set(id, variable);
|
|
305
|
-
}
|
|
277
|
+
const finalGlobals = { __proto__: null, ...configGlobals };
|
|
306
278
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
variable.eslintExplicitGlobalComments = sourceComments;
|
|
310
|
-
variable.writeable = value === "writable";
|
|
279
|
+
for (const [name, data] of Object.entries(inlineGlobals)) {
|
|
280
|
+
finalGlobals[name] = data.value;
|
|
311
281
|
}
|
|
312
282
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
* references and remove the ones that were added by configuration.
|
|
317
|
-
*/
|
|
318
|
-
globalScope.through = globalScope.through.filter(reference => {
|
|
319
|
-
const name = reference.identifier.name;
|
|
320
|
-
const variable = globalScope.set.get(name);
|
|
321
|
-
|
|
322
|
-
if (variable) {
|
|
323
|
-
/*
|
|
324
|
-
* Links the variable and the reference.
|
|
325
|
-
* And this reference is removed from `Scope#through`.
|
|
326
|
-
*/
|
|
327
|
-
reference.resolved = variable;
|
|
328
|
-
variable.references.push(reference);
|
|
283
|
+
const names = Object.keys(finalGlobals).filter(
|
|
284
|
+
name => finalGlobals[name] !== "off",
|
|
285
|
+
);
|
|
329
286
|
|
|
330
|
-
|
|
331
|
-
}
|
|
287
|
+
scopeManager.addGlobals(names);
|
|
332
288
|
|
|
333
|
-
|
|
334
|
-
});
|
|
289
|
+
const globalScope = scopeManager.scopes[0];
|
|
335
290
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
* implicitly by assigning values to undeclared variables in non-strict code).
|
|
339
|
-
* Since we augment the global scope using configuration, we need to remove
|
|
340
|
-
* the ones that were added by configuration, as they are either built-in
|
|
341
|
-
* or declared elsewhere, therefore not implicit.
|
|
342
|
-
* Since the "implicit" property was not documented, first we'll check if it exists
|
|
343
|
-
* because it's possible that not all custom scope managers create this property.
|
|
344
|
-
* If it exists, we assume it has properties `variables` and `set`. Property
|
|
345
|
-
* `left` is considered optional (for example, typescript-eslint's scope manage
|
|
346
|
-
* has this property named `leftToBeResolved`).
|
|
347
|
-
*/
|
|
348
|
-
const { implicit } = globalScope;
|
|
349
|
-
if (typeof implicit === "object" && implicit !== null) {
|
|
350
|
-
implicit.variables = implicit.variables.filter(variable => {
|
|
351
|
-
const name = variable.name;
|
|
352
|
-
if (globalScope.set.has(name)) {
|
|
353
|
-
implicit.set.delete(name);
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
return true;
|
|
357
|
-
});
|
|
291
|
+
for (const name of names) {
|
|
292
|
+
const variable = globalScope.set.get(name);
|
|
358
293
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
294
|
+
variable.eslintImplicitGlobalSetting = configGlobals[name];
|
|
295
|
+
variable.eslintExplicitGlobal = !!inlineGlobals[name];
|
|
296
|
+
variable.eslintExplicitGlobalComments = inlineGlobals[name]?.comments;
|
|
297
|
+
variable.writeable = finalGlobals[name] === "writable";
|
|
364
298
|
}
|
|
365
299
|
}
|
|
366
300
|
|
|
@@ -1162,6 +1096,15 @@ class SourceCode extends TokenStore {
|
|
|
1162
1096
|
: void 0,
|
|
1163
1097
|
languageOptions.globals,
|
|
1164
1098
|
);
|
|
1099
|
+
|
|
1100
|
+
/*
|
|
1101
|
+
* `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
|
|
1102
|
+
* typically be caught when validating a config anyway (validity for inline global comments is checked separately).
|
|
1103
|
+
*/
|
|
1104
|
+
for (const [name, value] of Object.entries(configGlobals)) {
|
|
1105
|
+
configGlobals[name] = normalizeConfigGlobal(value);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1165
1108
|
const varsCache = this[caches].get("vars");
|
|
1166
1109
|
|
|
1167
1110
|
varsCache.set("configGlobals", configGlobals);
|
|
@@ -1243,6 +1186,15 @@ class SourceCode extends TokenStore {
|
|
|
1243
1186
|
|
|
1244
1187
|
break;
|
|
1245
1188
|
}
|
|
1189
|
+
case "eslint-env": {
|
|
1190
|
+
problems.push({
|
|
1191
|
+
ruleId: null,
|
|
1192
|
+
loc: comment.loc,
|
|
1193
|
+
message:
|
|
1194
|
+
"/* eslint-env */ comments are no longer supported.",
|
|
1195
|
+
});
|
|
1196
|
+
break;
|
|
1197
|
+
}
|
|
1246
1198
|
|
|
1247
1199
|
// no default
|
|
1248
1200
|
}
|
|
@@ -1273,7 +1225,7 @@ class SourceCode extends TokenStore {
|
|
|
1273
1225
|
const exportedVariables = varsCache.get("exportedVariables");
|
|
1274
1226
|
const globalScope = this.scopeManager.scopes[0];
|
|
1275
1227
|
|
|
1276
|
-
addDeclaredGlobals(
|
|
1228
|
+
addDeclaredGlobals(this.scopeManager, configGlobals, inlineGlobals);
|
|
1277
1229
|
|
|
1278
1230
|
if (exportedVariables) {
|
|
1279
1231
|
markExportedVariables(globalScope, exportedVariables);
|