eslint 8.22.0 → 8.33.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 +51 -45
- package/bin/eslint.js +2 -4
- package/conf/globals.js +6 -1
- package/conf/rule-type-list.json +2 -2
- package/lib/cli-engine/file-enumerator.js +4 -2
- package/lib/cli-engine/formatters/formatters-meta.json +46 -0
- package/lib/cli-engine/formatters/html.js +76 -51
- package/lib/cli.js +163 -40
- package/lib/config/default-config.js +2 -2
- package/lib/config/flat-config-array.js +1 -1
- package/lib/eslint/eslint-helpers.js +409 -87
- package/lib/eslint/eslint.js +5 -2
- package/lib/eslint/flat-eslint.js +113 -110
- package/lib/linter/code-path-analysis/code-path-segment.js +2 -2
- package/lib/linter/code-path-analysis/code-path-state.js +7 -7
- package/lib/linter/code-path-analysis/debug-helpers.js +3 -3
- package/lib/linter/code-path-analysis/id-generator.js +2 -2
- package/lib/linter/config-comment-parser.js +1 -2
- package/lib/linter/linter.js +17 -7
- package/lib/linter/timing.js +4 -4
- package/lib/options.js +293 -239
- package/lib/rule-tester/flat-rule-tester.js +13 -11
- package/lib/rule-tester/rule-tester.js +15 -11
- package/lib/rules/array-callback-return.js +2 -2
- package/lib/rules/comma-dangle.js +3 -3
- package/lib/rules/for-direction.js +1 -1
- package/lib/rules/func-name-matching.js +2 -2
- package/lib/rules/getter-return.js +14 -8
- package/lib/rules/global-require.js +2 -1
- package/lib/rules/id-length.js +43 -2
- package/lib/rules/indent-legacy.js +4 -4
- package/lib/rules/indent.js +23 -15
- package/lib/rules/index.js +3 -0
- package/lib/rules/key-spacing.js +50 -38
- package/lib/rules/lines-around-comment.js +2 -2
- package/lib/rules/logical-assignment-operators.js +474 -0
- package/lib/rules/multiline-ternary.js +2 -2
- package/lib/rules/new-cap.js +2 -2
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-static-block.js +47 -0
- package/lib/rules/no-empty.js +19 -2
- package/lib/rules/no-extra-boolean-cast.js +1 -1
- package/lib/rules/no-extra-parens.js +18 -3
- package/lib/rules/no-fallthrough.js +26 -5
- package/lib/rules/no-implicit-coercion.js +20 -1
- package/lib/rules/no-implicit-globals.js +5 -0
- package/lib/rules/no-invalid-regexp.js +40 -18
- package/lib/rules/no-labels.js +1 -1
- package/lib/rules/no-lone-blocks.js +1 -1
- package/lib/rules/no-loss-of-precision.js +2 -2
- package/lib/rules/no-magic-numbers.js +18 -1
- package/lib/rules/no-misleading-character-class.js +4 -4
- package/lib/rules/no-new-native-nonconstructor.js +64 -0
- package/lib/rules/no-obj-calls.js +1 -1
- package/lib/rules/no-restricted-exports.js +106 -10
- package/lib/rules/no-return-await.js +28 -1
- package/lib/rules/no-underscore-dangle.js +36 -11
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-use-before-define.js +1 -1
- package/lib/rules/no-useless-computed-key.js +1 -1
- package/lib/rules/no-var.js +2 -2
- package/lib/rules/no-warning-comments.js +24 -5
- package/lib/rules/padded-blocks.js +1 -1
- package/lib/rules/prefer-arrow-callback.js +4 -3
- package/lib/rules/prefer-const.js +13 -1
- package/lib/rules/prefer-named-capture-group.js +71 -6
- package/lib/rules/prefer-object-spread.js +1 -1
- package/lib/rules/prefer-regex-literals.js +147 -32
- package/lib/rules/prefer-rest-params.js +1 -1
- package/lib/rules/require-yield.js +0 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/utils/ast-utils.js +10 -4
- package/lib/shared/directives.js +15 -0
- package/lib/shared/logging.js +1 -1
- package/lib/shared/runtime-info.js +1 -1
- package/lib/shared/traverser.js +1 -1
- package/lib/shared/types.js +15 -2
- package/lib/source-code/token-store/cursor.js +1 -1
- package/messages/print-config-with-directory-path.js +1 -1
- package/package.json +27 -27
package/lib/cli.js
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
"use strict";
|
7
7
|
|
8
8
|
/*
|
9
|
-
* The CLI object should *not* call process.exit() directly. It should only return
|
9
|
+
* NOTE: The CLI object should *not* call process.exit() directly. It should only return
|
10
10
|
* exit codes. This allows other programs to use the CLI object and still control
|
11
11
|
* when the program exits.
|
12
12
|
*/
|
@@ -19,9 +19,13 @@ const fs = require("fs"),
|
|
19
19
|
path = require("path"),
|
20
20
|
{ promisify } = require("util"),
|
21
21
|
{ ESLint } = require("./eslint"),
|
22
|
-
|
22
|
+
{ FlatESLint } = require("./eslint/flat-eslint"),
|
23
|
+
createCLIOptions = require("./options"),
|
23
24
|
log = require("./shared/logging"),
|
24
25
|
RuntimeInfo = require("./shared/runtime-info");
|
26
|
+
const { Legacy: { naming } } = require("@eslint/eslintrc");
|
27
|
+
const { findFlatConfigFile } = require("./eslint/flat-eslint");
|
28
|
+
const { ModuleImporter } = require("@humanwhocodes/module-importer");
|
25
29
|
|
26
30
|
const debug = require("debug")("eslint:cli");
|
27
31
|
|
@@ -33,6 +37,7 @@ const debug = require("debug")("eslint:cli");
|
|
33
37
|
/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
|
34
38
|
/** @typedef {import("./eslint/eslint").LintResult} LintResult */
|
35
39
|
/** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
|
40
|
+
/** @typedef {import("./shared/types").ResultsMeta} ResultsMeta */
|
36
41
|
|
37
42
|
//------------------------------------------------------------------------------
|
38
43
|
// Helpers
|
@@ -54,17 +59,20 @@ function quietFixPredicate(message) {
|
|
54
59
|
}
|
55
60
|
|
56
61
|
/**
|
57
|
-
* Translates the CLI options into the options expected by the
|
62
|
+
* Translates the CLI options into the options expected by the ESLint constructor.
|
58
63
|
* @param {ParsedCLIOptions} cliOptions The CLI options to translate.
|
59
|
-
* @
|
64
|
+
* @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the
|
65
|
+
* config to generate.
|
66
|
+
* @returns {Promise<ESLintOptions>} The options object for the ESLint constructor.
|
60
67
|
* @private
|
61
68
|
*/
|
62
|
-
function translateOptions({
|
69
|
+
async function translateOptions({
|
63
70
|
cache,
|
64
71
|
cacheFile,
|
65
72
|
cacheLocation,
|
66
73
|
cacheStrategy,
|
67
74
|
config,
|
75
|
+
configLookup,
|
68
76
|
env,
|
69
77
|
errorOnUnmatchedPattern,
|
70
78
|
eslintrc,
|
@@ -85,19 +93,60 @@ function translateOptions({
|
|
85
93
|
resolvePluginsRelativeTo,
|
86
94
|
rule,
|
87
95
|
rulesdir
|
88
|
-
}) {
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
96
|
+
}, configType) {
|
97
|
+
|
98
|
+
let overrideConfig, overrideConfigFile;
|
99
|
+
const importer = new ModuleImporter();
|
100
|
+
|
101
|
+
if (configType === "flat") {
|
102
|
+
overrideConfigFile = (typeof config === "string") ? config : !configLookup;
|
103
|
+
if (overrideConfigFile === false) {
|
104
|
+
overrideConfigFile = void 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
let globals = {};
|
108
|
+
|
109
|
+
if (global) {
|
110
|
+
globals = global.reduce((obj, name) => {
|
111
|
+
if (name.endsWith(":true")) {
|
112
|
+
obj[name.slice(0, -5)] = "writable";
|
113
|
+
} else {
|
114
|
+
obj[name] = "readonly";
|
115
|
+
}
|
116
|
+
return obj;
|
117
|
+
}, globals);
|
118
|
+
}
|
119
|
+
|
120
|
+
overrideConfig = [{
|
121
|
+
languageOptions: {
|
122
|
+
globals,
|
123
|
+
parserOptions: parserOptions || {}
|
124
|
+
},
|
125
|
+
rules: rule ? rule : {}
|
126
|
+
}];
|
127
|
+
|
128
|
+
if (parser) {
|
129
|
+
overrideConfig[0].languageOptions.parser = await importer.import(parser);
|
130
|
+
}
|
131
|
+
|
132
|
+
if (plugin) {
|
133
|
+
const plugins = {};
|
134
|
+
|
135
|
+
for (const pluginName of plugin) {
|
136
|
+
|
137
|
+
const shortName = naming.getShorthandName(pluginName, "eslint-plugin");
|
138
|
+
const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
|
139
|
+
|
140
|
+
plugins[shortName] = await importer.import(longName);
|
141
|
+
}
|
142
|
+
|
143
|
+
overrideConfig[0].plugins = plugins;
|
144
|
+
}
|
145
|
+
|
146
|
+
} else {
|
147
|
+
overrideConfigFile = config;
|
148
|
+
|
149
|
+
overrideConfig = {
|
101
150
|
env: env && env.reduce((obj, name) => {
|
102
151
|
obj[name] = true;
|
103
152
|
return obj;
|
@@ -115,19 +164,40 @@ function translateOptions({
|
|
115
164
|
parserOptions,
|
116
165
|
plugins: plugin,
|
117
166
|
rules: rule
|
118
|
-
}
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
167
|
+
};
|
168
|
+
}
|
169
|
+
|
170
|
+
const options = {
|
171
|
+
allowInlineConfig: inlineConfig,
|
172
|
+
cache,
|
173
|
+
cacheLocation: cacheLocation || cacheFile,
|
174
|
+
cacheStrategy,
|
175
|
+
errorOnUnmatchedPattern,
|
176
|
+
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
|
177
|
+
fixTypes: fixType,
|
178
|
+
ignore,
|
179
|
+
overrideConfig,
|
180
|
+
overrideConfigFile,
|
181
|
+
reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0
|
124
182
|
};
|
183
|
+
|
184
|
+
if (configType === "flat") {
|
185
|
+
options.ignorePatterns = ignorePattern;
|
186
|
+
} else {
|
187
|
+
options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
|
188
|
+
options.rulePaths = rulesdir;
|
189
|
+
options.useEslintrc = eslintrc;
|
190
|
+
options.extensions = ext;
|
191
|
+
options.ignorePath = ignorePath;
|
192
|
+
}
|
193
|
+
|
194
|
+
return options;
|
125
195
|
}
|
126
196
|
|
127
197
|
/**
|
128
198
|
* Count error messages.
|
129
199
|
* @param {LintResult[]} results The lint results.
|
130
|
-
* @returns {{errorCount:number;warningCount:number}} The number of error messages.
|
200
|
+
* @returns {{errorCount:number;fatalErrorCount:number,warningCount:number}} The number of error messages.
|
131
201
|
*/
|
132
202
|
function countErrors(results) {
|
133
203
|
let errorCount = 0;
|
@@ -165,10 +235,11 @@ async function isDirectory(filePath) {
|
|
165
235
|
* @param {LintResult[]} results The results to print.
|
166
236
|
* @param {string} format The name of the formatter to use or the path to the formatter.
|
167
237
|
* @param {string} outputFile The path for the output file.
|
238
|
+
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
|
168
239
|
* @returns {Promise<boolean>} True if the printing succeeds, false if not.
|
169
240
|
* @private
|
170
241
|
*/
|
171
|
-
async function printResults(engine, results, format, outputFile) {
|
242
|
+
async function printResults(engine, results, format, outputFile, resultsMeta) {
|
172
243
|
let formatter;
|
173
244
|
|
174
245
|
try {
|
@@ -178,7 +249,7 @@ async function printResults(engine, results, format, outputFile) {
|
|
178
249
|
return false;
|
179
250
|
}
|
180
251
|
|
181
|
-
const output = await formatter.format(results);
|
252
|
+
const output = await formatter.format(results, resultsMeta);
|
182
253
|
|
183
254
|
if (output) {
|
184
255
|
if (outputFile) {
|
@@ -204,6 +275,31 @@ async function printResults(engine, results, format, outputFile) {
|
|
204
275
|
return true;
|
205
276
|
}
|
206
277
|
|
278
|
+
/**
|
279
|
+
* Returns whether flat config should be used.
|
280
|
+
* @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
|
281
|
+
* @returns {Promise<boolean>} Where flat config should be used.
|
282
|
+
*/
|
283
|
+
async function shouldUseFlatConfig(allowFlatConfig) {
|
284
|
+
if (!allowFlatConfig) {
|
285
|
+
return false;
|
286
|
+
}
|
287
|
+
|
288
|
+
switch (process.env.ESLINT_USE_FLAT_CONFIG) {
|
289
|
+
case "true":
|
290
|
+
return true;
|
291
|
+
case "false":
|
292
|
+
return false;
|
293
|
+
default:
|
294
|
+
|
295
|
+
/*
|
296
|
+
* If neither explicitly enabled nor disabled, then use the presence
|
297
|
+
* of a flat config file to determine enablement.
|
298
|
+
*/
|
299
|
+
return !!(await findFlatConfigFile(process.cwd()));
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
207
303
|
//------------------------------------------------------------------------------
|
208
304
|
// Public Interface
|
209
305
|
//------------------------------------------------------------------------------
|
@@ -218,19 +314,34 @@ const cli = {
|
|
218
314
|
* Executes the CLI based on an array of arguments that is passed in.
|
219
315
|
* @param {string|Array|Object} args The arguments to process.
|
220
316
|
* @param {string} [text] The text to lint (used for TTY).
|
317
|
+
* @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
|
221
318
|
* @returns {Promise<number>} The exit code for the operation.
|
222
319
|
*/
|
223
|
-
async execute(args, text) {
|
320
|
+
async execute(args, text, allowFlatConfig) {
|
224
321
|
if (Array.isArray(args)) {
|
225
322
|
debug("CLI args: %o", args.slice(2));
|
226
323
|
}
|
227
324
|
|
325
|
+
/*
|
326
|
+
* Before doing anything, we need to see if we are using a
|
327
|
+
* flat config file. If so, then we need to change the way command
|
328
|
+
* line args are parsed. This is temporary, and when we fully
|
329
|
+
* switch to flat config we can remove this logic.
|
330
|
+
*/
|
331
|
+
|
332
|
+
const usingFlatConfig = await shouldUseFlatConfig(allowFlatConfig);
|
333
|
+
|
334
|
+
debug("Using flat config?", usingFlatConfig);
|
335
|
+
|
336
|
+
const CLIOptions = createCLIOptions(usingFlatConfig);
|
337
|
+
|
228
338
|
/** @type {ParsedCLIOptions} */
|
229
339
|
let options;
|
230
340
|
|
231
341
|
try {
|
232
342
|
options = CLIOptions.parse(args);
|
233
343
|
} catch (error) {
|
344
|
+
debug("Error parsing CLI options:", error.message);
|
234
345
|
log.error(error.message);
|
235
346
|
return 2;
|
236
347
|
}
|
@@ -251,6 +362,7 @@ const cli = {
|
|
251
362
|
log.info(RuntimeInfo.environment());
|
252
363
|
return 0;
|
253
364
|
} catch (err) {
|
365
|
+
debug("Error retrieving environment info");
|
254
366
|
log.error(err.message);
|
255
367
|
return 2;
|
256
368
|
}
|
@@ -266,7 +378,9 @@ const cli = {
|
|
266
378
|
return 2;
|
267
379
|
}
|
268
380
|
|
269
|
-
const engine =
|
381
|
+
const engine = usingFlatConfig
|
382
|
+
? new FlatESLint(await translateOptions(options, "flat"))
|
383
|
+
: new ESLint(await translateOptions(options));
|
270
384
|
const fileConfig =
|
271
385
|
await engine.calculateConfigForFile(options.printConfig);
|
272
386
|
|
@@ -289,7 +403,9 @@ const cli = {
|
|
289
403
|
return 2;
|
290
404
|
}
|
291
405
|
|
292
|
-
const
|
406
|
+
const ActiveESLint = usingFlatConfig ? FlatESLint : ESLint;
|
407
|
+
|
408
|
+
const engine = new ActiveESLint(await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc"));
|
293
409
|
let results;
|
294
410
|
|
295
411
|
if (useStdin) {
|
@@ -303,27 +419,34 @@ const cli = {
|
|
303
419
|
|
304
420
|
if (options.fix) {
|
305
421
|
debug("Fix mode enabled - applying fixes");
|
306
|
-
await
|
422
|
+
await ActiveESLint.outputFixes(results);
|
307
423
|
}
|
308
424
|
|
309
425
|
let resultsToPrint = results;
|
310
426
|
|
311
427
|
if (options.quiet) {
|
312
428
|
debug("Quiet mode enabled - filtering out warnings");
|
313
|
-
resultsToPrint =
|
429
|
+
resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint);
|
314
430
|
}
|
315
431
|
|
316
|
-
|
432
|
+
const resultCounts = countErrors(results);
|
433
|
+
const tooManyWarnings = options.maxWarnings >= 0 && resultCounts.warningCount > options.maxWarnings;
|
434
|
+
const resultsMeta = tooManyWarnings
|
435
|
+
? {
|
436
|
+
maxWarningsExceeded: {
|
437
|
+
maxWarnings: options.maxWarnings,
|
438
|
+
foundWarnings: resultCounts.warningCount
|
439
|
+
}
|
440
|
+
}
|
441
|
+
: {};
|
317
442
|
|
318
|
-
|
319
|
-
const { errorCount, fatalErrorCount, warningCount } = countErrors(results);
|
443
|
+
if (await printResults(engine, resultsToPrint, options.format, options.outputFile, resultsMeta)) {
|
320
444
|
|
321
|
-
|
322
|
-
options.maxWarnings >= 0 && warningCount > options.maxWarnings;
|
445
|
+
// Errors and warnings from the original unfiltered results should determine the exit code
|
323
446
|
const shouldExitForFatalErrors =
|
324
|
-
options.exitOnFatalError && fatalErrorCount > 0;
|
447
|
+
options.exitOnFatalError && resultCounts.fatalErrorCount > 0;
|
325
448
|
|
326
|
-
if (!errorCount && tooManyWarnings) {
|
449
|
+
if (!resultCounts.errorCount && tooManyWarnings) {
|
327
450
|
log.error(
|
328
451
|
"ESLint found too many warnings (maximum: %s).",
|
329
452
|
options.maxWarnings
|
@@ -334,7 +457,7 @@ const cli = {
|
|
334
457
|
return 2;
|
335
458
|
}
|
336
459
|
|
337
|
-
return (errorCount || tooManyWarnings) ? 1 : 0;
|
460
|
+
return (resultCounts.errorCount || tooManyWarnings) ? 1 : 0;
|
338
461
|
}
|
339
462
|
|
340
463
|
return 2;
|