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
@@ -16,7 +16,6 @@ const findUp = require("find-up");
|
|
16
16
|
const { version } = require("../../package.json");
|
17
17
|
const { Linter } = require("../linter");
|
18
18
|
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
19
|
-
const { gitignoreToMinimatch } = require("@humanwhocodes/gitignore-to-minimatch");
|
20
19
|
const {
|
21
20
|
Legacy: {
|
22
21
|
ConfigOps: {
|
@@ -28,7 +27,6 @@ const {
|
|
28
27
|
} = require("@eslint/eslintrc");
|
29
28
|
|
30
29
|
const {
|
31
|
-
fileExists,
|
32
30
|
findFiles,
|
33
31
|
getCacheFile,
|
34
32
|
|
@@ -59,6 +57,7 @@ const LintResultCache = require("../cli-engine/lint-result-cache");
|
|
59
57
|
/** @typedef {import("../shared/types").LintMessage} LintMessage */
|
60
58
|
/** @typedef {import("../shared/types").ParserOptions} ParserOptions */
|
61
59
|
/** @typedef {import("../shared/types").Plugin} Plugin */
|
60
|
+
/** @typedef {import("../shared/types").ResultsMeta} ResultsMeta */
|
62
61
|
/** @typedef {import("../shared/types").RuleConf} RuleConf */
|
63
62
|
/** @typedef {import("../shared/types").Rule} Rule */
|
64
63
|
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
|
@@ -73,13 +72,11 @@ const LintResultCache = require("../cli-engine/lint-result-cache");
|
|
73
72
|
* @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
|
74
73
|
* @property {string} [cwd] The value to use for the current working directory.
|
75
74
|
* @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
|
76
|
-
* @property {string[]} [extensions] An array of file extensions to check.
|
77
75
|
* @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
|
78
76
|
* @property {string[]} [fixTypes] Array of rule types to apply fixes for.
|
79
77
|
* @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
|
80
|
-
* @property {boolean} [ignore] False disables
|
81
|
-
* @property {string} [
|
82
|
-
* @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to .eslintignore.
|
78
|
+
* @property {boolean} [ignore] False disables all ignore patterns except for the default ones.
|
79
|
+
* @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to config ignores.
|
83
80
|
* @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
|
84
81
|
* @property {boolean|string} [overrideConfigFile] Searches for default config file when falsy;
|
85
82
|
* doesn't do any config file lookup when `true`; considered to be a config filename
|
@@ -96,6 +93,7 @@ const FLAT_CONFIG_FILENAME = "eslint.config.js";
|
|
96
93
|
const debug = require("debug")("eslint:flat-eslint");
|
97
94
|
const removedFormatters = new Set(["table", "codeframe"]);
|
98
95
|
const privateMembers = new WeakMap();
|
96
|
+
const importedConfigFileModificationTime = new Map();
|
99
97
|
|
100
98
|
/**
|
101
99
|
* It will calculate the error and warning count for collection of messages per file
|
@@ -152,30 +150,6 @@ function calculateStatsPerRun(results) {
|
|
152
150
|
});
|
153
151
|
}
|
154
152
|
|
155
|
-
/**
|
156
|
-
* Loads global ignore patterns from an ignore file (usually .eslintignore).
|
157
|
-
* @param {string} filePath The filename to load.
|
158
|
-
* @returns {ignore} A function encapsulating the ignore patterns.
|
159
|
-
* @throws {Error} If the file cannot be read.
|
160
|
-
* @private
|
161
|
-
*/
|
162
|
-
async function loadIgnoreFilePatterns(filePath) {
|
163
|
-
debug(`Loading ignore file: ${filePath}`);
|
164
|
-
|
165
|
-
try {
|
166
|
-
const ignoreFileText = await fs.readFile(filePath, { encoding: "utf8" });
|
167
|
-
|
168
|
-
return ignoreFileText
|
169
|
-
.split(/\r?\n/gu)
|
170
|
-
.filter(line => line.trim() !== "" && !line.startsWith("#"));
|
171
|
-
|
172
|
-
} catch (e) {
|
173
|
-
debug(`Error reading ignore file: ${filePath}`);
|
174
|
-
e.message = `Cannot read ignore file: ${filePath}\nError: ${e.message}`;
|
175
|
-
throw e;
|
176
|
-
}
|
177
|
-
}
|
178
|
-
|
179
153
|
/**
|
180
154
|
* Create rulesMeta object.
|
181
155
|
* @param {Map<string,Rule>} rules a map of rules from which to generate the object.
|
@@ -188,6 +162,16 @@ function createRulesMeta(rules) {
|
|
188
162
|
}, {});
|
189
163
|
}
|
190
164
|
|
165
|
+
/**
|
166
|
+
* Return the absolute path of a file named `"__placeholder__.js"` in a given directory.
|
167
|
+
* This is used as a replacement for a missing file path.
|
168
|
+
* @param {string} cwd An absolute directory path.
|
169
|
+
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
|
170
|
+
*/
|
171
|
+
function getPlaceholderPath(cwd) {
|
172
|
+
return path.join(cwd, "__placeholder__.js");
|
173
|
+
}
|
174
|
+
|
191
175
|
/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
|
192
176
|
const usedDeprecatedRulesCache = new WeakMap();
|
193
177
|
|
@@ -204,7 +188,7 @@ function getOrFindUsedDeprecatedRules(eslint, maybeFilePath) {
|
|
204
188
|
} = privateMembers.get(eslint);
|
205
189
|
const filePath = path.isAbsolute(maybeFilePath)
|
206
190
|
? maybeFilePath
|
207
|
-
:
|
191
|
+
: getPlaceholderPath(cwd);
|
208
192
|
const config = configs.getConfig(filePath);
|
209
193
|
|
210
194
|
// Most files use the same config, so cache it.
|
@@ -289,24 +273,51 @@ function findFlatConfigFile(cwd) {
|
|
289
273
|
/**
|
290
274
|
* Load the config array from the given filename.
|
291
275
|
* @param {string} filePath The filename to load from.
|
292
|
-
* @
|
293
|
-
* @param {string} options.basePath The base path for the config array.
|
294
|
-
* @param {boolean} options.shouldIgnore Whether to honor ignore patterns.
|
295
|
-
* @returns {Promise<FlatConfigArray>} The config array loaded from the config file.
|
276
|
+
* @returns {Promise<any>} The config loaded from the config file.
|
296
277
|
*/
|
297
|
-
async function loadFlatConfigFile(filePath
|
278
|
+
async function loadFlatConfigFile(filePath) {
|
298
279
|
debug(`Loading config from ${filePath}`);
|
299
280
|
|
300
281
|
const fileURL = pathToFileURL(filePath);
|
301
282
|
|
302
283
|
debug(`Config file URL is ${fileURL}`);
|
303
284
|
|
304
|
-
const
|
285
|
+
const mtime = (await fs.stat(filePath)).mtime.getTime();
|
305
286
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
287
|
+
/*
|
288
|
+
* Append a query with the config file's modification time (`mtime`) in order
|
289
|
+
* to import the current version of the config file. Without the query, `import()` would
|
290
|
+
* cache the config file module by the pathname only, and then always return
|
291
|
+
* the same version (the one that was actual when the module was imported for the first time).
|
292
|
+
*
|
293
|
+
* This ensures that the config file module is loaded and executed again
|
294
|
+
* if it has been changed since the last time it was imported.
|
295
|
+
* If it hasn't been changed, `import()` will just return the cached version.
|
296
|
+
*
|
297
|
+
* Note that we should not overuse queries (e.g., by appending the current time
|
298
|
+
* to always reload the config file module) as that could cause memory leaks
|
299
|
+
* because entries are never removed from the import cache.
|
300
|
+
*/
|
301
|
+
fileURL.searchParams.append("mtime", mtime);
|
302
|
+
|
303
|
+
/*
|
304
|
+
* With queries, we can bypass the import cache. However, when import-ing a CJS module,
|
305
|
+
* Node.js uses the require infrastructure under the hood. That includes the require cache,
|
306
|
+
* which caches the config file module by its file path (queries have no effect).
|
307
|
+
* Therefore, we also need to clear the require cache before importing the config file module.
|
308
|
+
* In order to get the same behavior with ESM and CJS config files, in particular - to reload
|
309
|
+
* the config file only if it has been changed, we track file modification times and clear
|
310
|
+
* the require cache only if the file has been changed.
|
311
|
+
*/
|
312
|
+
if (importedConfigFileModificationTime.get(filePath) !== mtime) {
|
313
|
+
delete require.cache[filePath];
|
314
|
+
}
|
315
|
+
|
316
|
+
const config = (await import(fileURL)).default;
|
317
|
+
|
318
|
+
importedConfigFileModificationTime.set(filePath, mtime);
|
319
|
+
|
320
|
+
return config;
|
310
321
|
}
|
311
322
|
|
312
323
|
/**
|
@@ -317,12 +328,11 @@ async function loadFlatConfigFile(filePath, { basePath, shouldIgnore }) {
|
|
317
328
|
*/
|
318
329
|
async function calculateConfigArray(eslint, {
|
319
330
|
cwd,
|
331
|
+
baseConfig,
|
320
332
|
overrideConfig,
|
321
333
|
configFile,
|
322
334
|
ignore: shouldIgnore,
|
323
|
-
|
324
|
-
ignorePatterns,
|
325
|
-
extensions
|
335
|
+
ignorePatterns
|
326
336
|
}) {
|
327
337
|
|
328
338
|
// check for cached instance
|
@@ -350,45 +360,24 @@ async function calculateConfigArray(eslint, {
|
|
350
360
|
basePath = path.resolve(path.dirname(configFilePath));
|
351
361
|
}
|
352
362
|
|
353
|
-
// load config array
|
354
|
-
let configs;
|
355
363
|
|
364
|
+
const configs = new FlatConfigArray(baseConfig || [], { basePath, shouldIgnore });
|
365
|
+
|
366
|
+
// load config file
|
356
367
|
if (configFilePath) {
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
368
|
+
const fileConfig = await loadFlatConfigFile(configFilePath);
|
369
|
+
|
370
|
+
if (Array.isArray(fileConfig)) {
|
371
|
+
configs.push(...fileConfig);
|
372
|
+
} else {
|
373
|
+
configs.push(fileConfig);
|
374
|
+
}
|
363
375
|
}
|
364
376
|
|
365
377
|
// add in any configured defaults
|
366
378
|
configs.push(...slots.defaultConfigs);
|
367
379
|
|
368
|
-
// if there are any extensions, create configs for them for easier matching
|
369
|
-
if (extensions && extensions.length) {
|
370
|
-
configs.push({
|
371
|
-
files: extensions.map(ext => `**/*${ext}`)
|
372
|
-
});
|
373
|
-
}
|
374
|
-
|
375
380
|
let allIgnorePatterns = [];
|
376
|
-
let ignoreFilePath;
|
377
|
-
|
378
|
-
// load ignore file if necessary
|
379
|
-
if (shouldIgnore) {
|
380
|
-
if (ignorePath) {
|
381
|
-
ignoreFilePath = path.resolve(cwd, ignorePath);
|
382
|
-
allIgnorePatterns = await loadIgnoreFilePatterns(ignoreFilePath);
|
383
|
-
} else {
|
384
|
-
ignoreFilePath = path.resolve(cwd, ".eslintignore");
|
385
|
-
|
386
|
-
// no error if .eslintignore doesn't exist`
|
387
|
-
if (fileExists(ignoreFilePath)) {
|
388
|
-
allIgnorePatterns = await loadIgnoreFilePatterns(ignoreFilePath);
|
389
|
-
}
|
390
|
-
}
|
391
|
-
}
|
392
381
|
|
393
382
|
// append command line ignore patterns
|
394
383
|
if (ignorePatterns) {
|
@@ -414,17 +403,6 @@ async function calculateConfigArray(eslint, {
|
|
414
403
|
const negated = pattern.startsWith("!");
|
415
404
|
const basePattern = negated ? pattern.slice(1) : pattern;
|
416
405
|
|
417
|
-
/*
|
418
|
-
* Ignore patterns are considered relative to a directory
|
419
|
-
* when the pattern contains a slash in a position other
|
420
|
-
* than the last character. If that's the case, we need to
|
421
|
-
* add the relative ignore path to the current pattern to
|
422
|
-
* get the correct behavior. Otherwise, no change is needed.
|
423
|
-
*/
|
424
|
-
if (!basePattern.includes("/") || basePattern.endsWith("/")) {
|
425
|
-
return pattern;
|
426
|
-
}
|
427
|
-
|
428
406
|
return (negated ? "!" : "") +
|
429
407
|
path.posix.join(relativeIgnorePath, basePattern);
|
430
408
|
});
|
@@ -437,7 +415,7 @@ async function calculateConfigArray(eslint, {
|
|
437
415
|
* so they can override default ignores.
|
438
416
|
*/
|
439
417
|
configs.push({
|
440
|
-
ignores: allIgnorePatterns
|
418
|
+
ignores: allIgnorePatterns
|
441
419
|
});
|
442
420
|
}
|
443
421
|
|
@@ -490,7 +468,7 @@ function verifyText({
|
|
490
468
|
* `config.extractConfig(filePath)` requires an absolute path, but `linter`
|
491
469
|
* doesn't know CWD, so it gives `linter` an absolute path always.
|
492
470
|
*/
|
493
|
-
const filePathToVerify = filePath === "<text>" ?
|
471
|
+
const filePathToVerify = filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
|
494
472
|
const { fixed, messages, output } = linter.verifyAndFix(
|
495
473
|
text,
|
496
474
|
configs,
|
@@ -515,6 +493,7 @@ function verifyText({
|
|
515
493
|
const result = {
|
516
494
|
filePath: filePath === "<text>" ? filePath : path.resolve(filePath),
|
517
495
|
messages,
|
496
|
+
suppressedMessages: linter.getSuppressedMessages(),
|
518
497
|
...calculateStatsPerFile(messages)
|
519
498
|
};
|
520
499
|
|
@@ -586,6 +565,14 @@ function *iterateRuleDeprecationWarnings(configs) {
|
|
586
565
|
}
|
587
566
|
}
|
588
567
|
|
568
|
+
/**
|
569
|
+
* Creates an error to be thrown when an array of results passed to `getRulesMetaForResults` was not created by the current engine.
|
570
|
+
* @returns {TypeError} An error object.
|
571
|
+
*/
|
572
|
+
function createExtraneousResultsError() {
|
573
|
+
return new TypeError("Results object was not created from this ESLint instance.");
|
574
|
+
}
|
575
|
+
|
589
576
|
//-----------------------------------------------------------------------------
|
590
577
|
// Main API
|
591
578
|
//-----------------------------------------------------------------------------
|
@@ -689,11 +676,13 @@ class FlatESLint {
|
|
689
676
|
|
690
677
|
results.forEach(result => {
|
691
678
|
const filteredMessages = result.messages.filter(isErrorMessage);
|
679
|
+
const filteredSuppressedMessages = result.suppressedMessages.filter(isErrorMessage);
|
692
680
|
|
693
681
|
if (filteredMessages.length > 0) {
|
694
682
|
filtered.push({
|
695
683
|
...result,
|
696
684
|
messages: filteredMessages,
|
685
|
+
suppressedMessages: filteredSuppressedMessages,
|
697
686
|
errorCount: filteredMessages.length,
|
698
687
|
warningCount: 0,
|
699
688
|
fixableErrorCount: result.fixableErrorCount,
|
@@ -714,14 +703,16 @@ class FlatESLint {
|
|
714
703
|
*/
|
715
704
|
getRulesMetaForResults(results) {
|
716
705
|
|
717
|
-
const resultRules = new Map();
|
718
|
-
|
719
706
|
// short-circuit simple case
|
720
707
|
if (results.length === 0) {
|
721
|
-
return
|
708
|
+
return {};
|
722
709
|
}
|
723
710
|
|
724
|
-
const
|
711
|
+
const resultRules = new Map();
|
712
|
+
const {
|
713
|
+
configs,
|
714
|
+
options: { cwd }
|
715
|
+
} = privateMembers.get(this);
|
725
716
|
|
726
717
|
/*
|
727
718
|
* We can only accurately return rules meta information for linting results if the
|
@@ -730,7 +721,7 @@ class FlatESLint {
|
|
730
721
|
* to let the user know we can't do anything here.
|
731
722
|
*/
|
732
723
|
if (!configs) {
|
733
|
-
throw
|
724
|
+
throw createExtraneousResultsError();
|
734
725
|
}
|
735
726
|
|
736
727
|
for (const result of results) {
|
@@ -739,18 +730,26 @@ class FlatESLint {
|
|
739
730
|
* Normalize filename for <text>.
|
740
731
|
*/
|
741
732
|
const filePath = result.filePath === "<text>"
|
742
|
-
?
|
733
|
+
? getPlaceholderPath(cwd) : result.filePath;
|
734
|
+
const allMessages = result.messages.concat(result.suppressedMessages);
|
743
735
|
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
const config = configs.getConfig(filePath);
|
736
|
+
for (const { ruleId } of allMessages) {
|
737
|
+
if (!ruleId) {
|
738
|
+
continue;
|
739
|
+
}
|
749
740
|
|
750
|
-
|
741
|
+
/*
|
742
|
+
* All of the plugin and rule information is contained within the
|
743
|
+
* calculated config for the given file.
|
744
|
+
*/
|
745
|
+
const config = configs.getConfig(filePath);
|
746
|
+
|
747
|
+
if (!config) {
|
748
|
+
throw createExtraneousResultsError();
|
749
|
+
}
|
751
750
|
const rule = getRuleFromConfig(ruleId, config);
|
752
751
|
|
753
|
-
// ensure the rule exists
|
752
|
+
// ensure the rule exists
|
754
753
|
if (!rule) {
|
755
754
|
throw new TypeError(`Could not find the rule "${ruleId}".`);
|
756
755
|
}
|
@@ -786,8 +785,8 @@ class FlatESLint {
|
|
786
785
|
fix,
|
787
786
|
fixTypes,
|
788
787
|
reportUnusedDisableDirectives,
|
789
|
-
|
790
|
-
|
788
|
+
globInputPaths,
|
789
|
+
errorOnUnmatchedPattern
|
791
790
|
} = eslintOptions;
|
792
791
|
const startTime = Date.now();
|
793
792
|
const usedConfigs = [];
|
@@ -812,9 +811,9 @@ class FlatESLint {
|
|
812
811
|
const filePaths = await findFiles({
|
813
812
|
patterns: typeof patterns === "string" ? [patterns] : patterns,
|
814
813
|
cwd,
|
815
|
-
extensions,
|
816
814
|
globInputPaths,
|
817
|
-
configs
|
815
|
+
configs,
|
816
|
+
errorOnUnmatchedPattern
|
818
817
|
});
|
819
818
|
|
820
819
|
debug(`${filePaths.length} files found in: ${Date.now() - startTime}ms`);
|
@@ -877,7 +876,7 @@ class FlatESLint {
|
|
877
876
|
}
|
878
877
|
|
879
878
|
|
880
|
-
// set up fixer for
|
879
|
+
// set up fixer for fixTypes if necessary
|
881
880
|
let fixer = fix;
|
882
881
|
|
883
882
|
if (fix && fixTypesSet) {
|
@@ -1053,7 +1052,7 @@ class FlatESLint {
|
|
1053
1052
|
* The following values are allowed:
|
1054
1053
|
* - `undefined` ... Load `stylish` builtin formatter.
|
1055
1054
|
* - A builtin formatter name ... Load the builtin formatter.
|
1056
|
-
* - A
|
1055
|
+
* - A third-party formatter name:
|
1057
1056
|
* - `foo` → `eslint-formatter-foo`
|
1058
1057
|
* - `@foo` → `@foo/eslint-formatter`
|
1059
1058
|
* - `@foo/bar` → `@foo/eslint-formatter-bar`
|
@@ -1085,7 +1084,7 @@ class FlatESLint {
|
|
1085
1084
|
const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
|
1086
1085
|
|
1087
1086
|
// TODO: This is pretty dirty...would be nice to clean up at some point.
|
1088
|
-
formatterPath = ModuleResolver.resolve(npmFormat,
|
1087
|
+
formatterPath = ModuleResolver.resolve(npmFormat, getPlaceholderPath(cwd));
|
1089
1088
|
} catch {
|
1090
1089
|
formatterPath = path.resolve(__dirname, "../", "cli-engine", "formatters", `${normalizedFormatName}.js`);
|
1091
1090
|
}
|
@@ -1119,14 +1118,17 @@ class FlatESLint {
|
|
1119
1118
|
/**
|
1120
1119
|
* The main formatter method.
|
1121
1120
|
* @param {LintResults[]} results The lint results to format.
|
1121
|
+
* @param {ResultsMeta} resultsMeta Warning count and max threshold.
|
1122
1122
|
* @returns {string} The formatted lint results.
|
1123
1123
|
*/
|
1124
|
-
format(results) {
|
1124
|
+
format(results, resultsMeta) {
|
1125
1125
|
let rulesMeta = null;
|
1126
1126
|
|
1127
1127
|
results.sort(compareResultsByFilePath);
|
1128
1128
|
|
1129
1129
|
return formatter(results, {
|
1130
|
+
...resultsMeta,
|
1131
|
+
cwd,
|
1130
1132
|
get rulesMeta() {
|
1131
1133
|
if (!rulesMeta) {
|
1132
1134
|
rulesMeta = eslint.getRulesMetaForResults(results);
|
@@ -1175,5 +1177,6 @@ class FlatESLint {
|
|
1175
1177
|
//------------------------------------------------------------------------------
|
1176
1178
|
|
1177
1179
|
module.exports = {
|
1178
|
-
FlatESLint
|
1180
|
+
FlatESLint,
|
1181
|
+
findFlatConfigFile
|
1179
1182
|
};
|
@@ -59,7 +59,7 @@ function getContinueContext(state, label) {
|
|
59
59
|
context = context.upper;
|
60
60
|
}
|
61
61
|
|
62
|
-
/*
|
62
|
+
/* c8 ignore next */
|
63
63
|
return null;
|
64
64
|
}
|
65
65
|
|
@@ -79,7 +79,7 @@ function getBreakContext(state, label) {
|
|
79
79
|
context = context.upper;
|
80
80
|
}
|
81
81
|
|
82
|
-
/*
|
82
|
+
/* c8 ignore next */
|
83
83
|
return null;
|
84
84
|
}
|
85
85
|
|
@@ -433,7 +433,7 @@ class CodePathState {
|
|
433
433
|
*/
|
434
434
|
return context;
|
435
435
|
|
436
|
-
/*
|
436
|
+
/* c8 ignore next */
|
437
437
|
default:
|
438
438
|
throw new Error("unreachable");
|
439
439
|
}
|
@@ -1030,7 +1030,7 @@ class CodePathState {
|
|
1030
1030
|
};
|
1031
1031
|
break;
|
1032
1032
|
|
1033
|
-
/*
|
1033
|
+
/* c8 ignore next */
|
1034
1034
|
default:
|
1035
1035
|
throw new Error(`unknown type: "${type}"`);
|
1036
1036
|
}
|
@@ -1095,7 +1095,7 @@ class CodePathState {
|
|
1095
1095
|
);
|
1096
1096
|
break;
|
1097
1097
|
|
1098
|
-
/*
|
1098
|
+
/* c8 ignore next */
|
1099
1099
|
default:
|
1100
1100
|
throw new Error("unreachable");
|
1101
1101
|
}
|
@@ -1392,11 +1392,12 @@ class CodePathState {
|
|
1392
1392
|
|
1393
1393
|
const context = getBreakContext(this, label);
|
1394
1394
|
|
1395
|
-
|
1395
|
+
|
1396
1396
|
if (context) {
|
1397
1397
|
context.brokenForkContext.add(forkContext.head);
|
1398
1398
|
}
|
1399
1399
|
|
1400
|
+
/* c8 ignore next */
|
1400
1401
|
forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
|
1401
1402
|
}
|
1402
1403
|
|
@@ -1417,7 +1418,6 @@ class CodePathState {
|
|
1417
1418
|
|
1418
1419
|
const context = getContinueContext(this, label);
|
1419
1420
|
|
1420
|
-
/* istanbul ignore else: foolproof (syntax error) */
|
1421
1421
|
if (context) {
|
1422
1422
|
if (context.continueDestSegments) {
|
1423
1423
|
makeLooped(this, forkContext.head, context.continueDestSegments);
|
@@ -20,7 +20,7 @@ const debug = require("debug")("eslint:code-path");
|
|
20
20
|
* @param {CodePathSegment} segment A segment to get.
|
21
21
|
* @returns {string} Id of the segment.
|
22
22
|
*/
|
23
|
-
/*
|
23
|
+
/* c8 ignore next */
|
24
24
|
function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc -- Ignoring
|
25
25
|
return segment.id + (segment.reachable ? "" : "!");
|
26
26
|
}
|
@@ -67,7 +67,7 @@ module.exports = {
|
|
67
67
|
* @param {boolean} leaving A flag whether or not it's leaving
|
68
68
|
* @returns {void}
|
69
69
|
*/
|
70
|
-
dumpState: !debug.enabled ? debug : /*
|
70
|
+
dumpState: !debug.enabled ? debug : /* c8 ignore next */ function(node, state, leaving) {
|
71
71
|
for (let i = 0; i < state.currentSegments.length; ++i) {
|
72
72
|
const segInternal = state.currentSegments[i].internal;
|
73
73
|
|
@@ -98,7 +98,7 @@ module.exports = {
|
|
98
98
|
* @see http://www.graphviz.org
|
99
99
|
* @see http://www.webgraphviz.com
|
100
100
|
*/
|
101
|
-
dumpDot: !debug.enabled ? debug : /*
|
101
|
+
dumpDot: !debug.enabled ? debug : /* c8 ignore next */ function(codePath) {
|
102
102
|
let text =
|
103
103
|
"\n" +
|
104
104
|
"digraph {\n" +
|
@@ -131,8 +131,7 @@ module.exports = class ConfigCommentParser {
|
|
131
131
|
|
132
132
|
const items = {};
|
133
133
|
|
134
|
-
|
135
|
-
string.replace(/\s*,\s*/gu, ",").split(/,+/u).forEach(name => {
|
134
|
+
string.split(",").forEach(name => {
|
136
135
|
const trimmedName = name.trim();
|
137
136
|
|
138
137
|
if (trimmedName) {
|
package/lib/linter/linter.js
CHANGED
@@ -18,6 +18,9 @@ const
|
|
18
18
|
merge = require("lodash.merge"),
|
19
19
|
pkg = require("../../package.json"),
|
20
20
|
astUtils = require("../shared/ast-utils"),
|
21
|
+
{
|
22
|
+
directivesPattern
|
23
|
+
} = require("../shared/directives"),
|
21
24
|
{
|
22
25
|
Legacy: {
|
23
26
|
ConfigOps,
|
@@ -213,6 +216,7 @@ function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, ena
|
|
213
216
|
|
214
217
|
if (variable) {
|
215
218
|
variable.eslintUsed = true;
|
219
|
+
variable.eslintExported = true;
|
216
220
|
}
|
217
221
|
});
|
218
222
|
|
@@ -376,7 +380,7 @@ function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
|
|
376
380
|
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
|
377
381
|
const { directivePart, justificationPart } = extractDirectiveComment(comment.value);
|
378
382
|
|
379
|
-
const match =
|
383
|
+
const match = directivesPattern.exec(directivePart);
|
380
384
|
|
381
385
|
if (!match) {
|
382
386
|
return;
|
@@ -1601,12 +1605,18 @@ class Linter {
|
|
1601
1605
|
languageOptions.ecmaVersion
|
1602
1606
|
);
|
1603
1607
|
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1608
|
+
/*
|
1609
|
+
* add configured globals and language globals
|
1610
|
+
*
|
1611
|
+
* using Object.assign instead of object spread for performance reasons
|
1612
|
+
* https://github.com/eslint/eslint/issues/16302
|
1613
|
+
*/
|
1614
|
+
const configuredGlobals = Object.assign(
|
1615
|
+
{},
|
1616
|
+
getGlobalsForEcmaVersion(languageOptions.ecmaVersion),
|
1617
|
+
languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0,
|
1618
|
+
languageOptions.globals
|
1619
|
+
);
|
1610
1620
|
|
1611
1621
|
// double check that there is a parser to avoid mysterious error messages
|
1612
1622
|
if (!languageOptions.parser) {
|
package/lib/linter/timing.js
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
// Helpers
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
/*
|
12
|
+
/* c8 ignore next */
|
13
13
|
/**
|
14
14
|
* Align the string to left
|
15
15
|
* @param {string} str string to evaluate
|
@@ -22,7 +22,7 @@ function alignLeft(str, len, ch) {
|
|
22
22
|
return str + new Array(len - str.length + 1).join(ch || " ");
|
23
23
|
}
|
24
24
|
|
25
|
-
/*
|
25
|
+
/* c8 ignore next */
|
26
26
|
/**
|
27
27
|
* Align the string to right
|
28
28
|
* @param {string} str string to evaluate
|
@@ -64,7 +64,7 @@ function getListSize() {
|
|
64
64
|
return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE;
|
65
65
|
}
|
66
66
|
|
67
|
-
/*
|
67
|
+
/* c8 ignore next */
|
68
68
|
/**
|
69
69
|
* display the data
|
70
70
|
* @param {Object} data Data object to be displayed
|
@@ -119,7 +119,7 @@ function display(data) {
|
|
119
119
|
console.log(table.join("\n")); // eslint-disable-line no-console -- Debugging function
|
120
120
|
}
|
121
121
|
|
122
|
-
/*
|
122
|
+
/* c8 ignore next */
|
123
123
|
module.exports = (function() {
|
124
124
|
|
125
125
|
const data = Object.create(null);
|