eslint 9.3.0 → 9.5.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 +2 -2
- package/lib/api.js +1 -1
- package/lib/cli.js +2 -2
- package/lib/config/default-config.js +5 -0
- package/lib/config/flat-config-array.js +72 -9
- package/lib/config/flat-config-schema.js +46 -62
- package/lib/eslint/eslint-helpers.js +33 -23
- package/lib/eslint/eslint.js +15 -20
- package/lib/languages/js/index.js +247 -0
- package/lib/{source-code → languages/js/source-code}/source-code.js +38 -18
- package/lib/languages/js/validate-language-options.js +181 -0
- package/lib/linter/apply-disable-directives.js +8 -3
- package/lib/linter/linter.js +122 -121
- package/lib/linter/report-translator.js +14 -7
- package/lib/linter/vfile.js +104 -0
- package/lib/rule-tester/rule-tester.js +6 -3
- package/lib/rules/func-style.js +4 -4
- package/lib/rules/no-constructor-return.js +1 -1
- package/lib/rules/no-loop-func.js +161 -129
- package/lib/rules/no-sparse-arrays.js +26 -3
- package/messages/all-matched-files-ignored.js +21 -0
- package/package.json +11 -11
- /package/lib/{source-code → languages/js/source-code}/index.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/backward-token-comment-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/backward-token-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/cursors.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/decorative-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/filter-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/forward-token-comment-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/forward-token-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/index.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/limit-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/padded-token-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/skip-cursor.js +0 -0
- /package/lib/{source-code → languages/js/source-code}/token-store/utils.js +0 -0
package/README.md
CHANGED
@@ -289,13 +289,13 @@ Percy Ma
|
|
289
289
|
|
290
290
|
## Sponsors
|
291
291
|
|
292
|
-
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://
|
292
|
+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
|
293
293
|
|
294
294
|
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
295
295
|
<!--sponsorsstart-->
|
296
296
|
<h3>Platinum Sponsors</h3>
|
297
297
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
298
|
-
<p><a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
|
298
|
+
<p><a href="#"><img src="https://images.opencollective.com/guest-bf377e88/avatar.png" alt="Eli Schleifer" height="96"></a> <a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
|
299
299
|
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" 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?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3>
|
300
300
|
<p><a href="https://www.notion.so"><img src="https://images.opencollective.com/notion/bf3b117/logo.png" alt="notion" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" 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.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://usenextbase.com"><img src="https://avatars.githubusercontent.com/u/145838380?v=4" alt="Nextbase Starter Kit" height="32"></a></p>
|
301
301
|
<!--sponsorsend-->
|
package/lib/api.js
CHANGED
@@ -13,7 +13,7 @@ const { ESLint, shouldUseFlatConfig } = require("./eslint/eslint");
|
|
13
13
|
const { LegacyESLint } = require("./eslint/legacy-eslint");
|
14
14
|
const { Linter } = require("./linter");
|
15
15
|
const { RuleTester } = require("./rule-tester");
|
16
|
-
const { SourceCode } = require("./source-code");
|
16
|
+
const { SourceCode } = require("./languages/js/source-code");
|
17
17
|
|
18
18
|
//-----------------------------------------------------------------------------
|
19
19
|
// Functions
|
package/lib/cli.js
CHANGED
@@ -448,14 +448,14 @@ const cli = {
|
|
448
448
|
|
449
449
|
if (options.inspectConfig) {
|
450
450
|
|
451
|
-
log.info("You can also run this command directly using 'npx @eslint/config-inspector' in the same directory as your configuration file.");
|
451
|
+
log.info("You can also run this command directly using 'npx @eslint/config-inspector@latest' in the same directory as your configuration file.");
|
452
452
|
|
453
453
|
try {
|
454
454
|
const flatOptions = await translateOptions(options, "flat");
|
455
455
|
const spawn = require("cross-spawn");
|
456
456
|
const flags = await cli.calculateInspectConfigFlags(flatOptions.overrideConfigFile);
|
457
457
|
|
458
|
-
spawn.sync("npx", ["@eslint/config-inspector", ...flags], { encoding: "utf8", stdio: "inherit" });
|
458
|
+
spawn.sync("npx", ["@eslint/config-inspector@latest", ...flags], { encoding: "utf8", stdio: "inherit" });
|
459
459
|
} catch (error) {
|
460
460
|
log.error(error);
|
461
461
|
return 2;
|
@@ -20,6 +20,10 @@ exports.defaultConfig = [
|
|
20
20
|
plugins: {
|
21
21
|
"@": {
|
22
22
|
|
23
|
+
languages: {
|
24
|
+
js: require("../languages/js")
|
25
|
+
},
|
26
|
+
|
23
27
|
/*
|
24
28
|
* Because we try to delay loading rules until absolutely
|
25
29
|
* necessary, a proxy allows us to hook into the lazy-loading
|
@@ -37,6 +41,7 @@ exports.defaultConfig = [
|
|
37
41
|
})
|
38
42
|
}
|
39
43
|
},
|
44
|
+
language: "@/js",
|
40
45
|
languageOptions: {
|
41
46
|
sourceType: "module",
|
42
47
|
ecmaVersion: "latest",
|
@@ -9,8 +9,8 @@
|
|
9
9
|
// Requirements
|
10
10
|
//-----------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const { ConfigArray, ConfigArraySymbol } = require("@
|
13
|
-
const { flatConfigSchema } = require("./flat-config-schema");
|
12
|
+
const { ConfigArray, ConfigArraySymbol } = require("@eslint/config-array");
|
13
|
+
const { flatConfigSchema, hasMethod } = require("./flat-config-schema");
|
14
14
|
const { RuleValidator } = require("./rule-validator");
|
15
15
|
const { defaultConfig } = require("./default-config");
|
16
16
|
|
@@ -123,6 +123,43 @@ function wrapConfigErrorWithDetails(error, originalLength, baseLength) {
|
|
123
123
|
);
|
124
124
|
}
|
125
125
|
|
126
|
+
/**
|
127
|
+
* Converts a languageOptions object to a JSON representation.
|
128
|
+
* @param {Record<string, any>} languageOptions The options to create a JSON
|
129
|
+
* representation of.
|
130
|
+
* @param {string} objectKey The key of the object being converted.
|
131
|
+
* @returns {Record<string, any>} The JSON representation of the languageOptions.
|
132
|
+
* @throws {TypeError} If a function is found in the languageOptions.
|
133
|
+
*/
|
134
|
+
function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
|
135
|
+
|
136
|
+
const result = {};
|
137
|
+
|
138
|
+
for (const [key, value] of Object.entries(languageOptions)) {
|
139
|
+
if (value) {
|
140
|
+
if (typeof value === "object") {
|
141
|
+
const name = getObjectId(value);
|
142
|
+
|
143
|
+
if (name && hasMethod(value)) {
|
144
|
+
result[key] = name;
|
145
|
+
} else {
|
146
|
+
result[key] = languageOptionsToJSON(value, key);
|
147
|
+
}
|
148
|
+
continue;
|
149
|
+
}
|
150
|
+
|
151
|
+
if (typeof value === "function") {
|
152
|
+
throw new TypeError(`Cannot serialize key "${key}" in ${objectKey}: Function values are not supported.`);
|
153
|
+
}
|
154
|
+
|
155
|
+
}
|
156
|
+
|
157
|
+
result[key] = value;
|
158
|
+
}
|
159
|
+
|
160
|
+
return result;
|
161
|
+
}
|
162
|
+
|
126
163
|
const originalBaseConfig = Symbol("originalBaseConfig");
|
127
164
|
const originalLength = Symbol("originalLength");
|
128
165
|
const baseLength = Symbol("baseLength");
|
@@ -269,10 +306,11 @@ class FlatConfigArray extends ConfigArray {
|
|
269
306
|
*/
|
270
307
|
[ConfigArraySymbol.finalizeConfig](config) {
|
271
308
|
|
272
|
-
const { plugins, languageOptions, processor } = config;
|
273
|
-
let parserName, processorName;
|
309
|
+
const { plugins, language, languageOptions, processor } = config;
|
310
|
+
let parserName, processorName, languageName;
|
274
311
|
let invalidParser = false,
|
275
|
-
invalidProcessor = false
|
312
|
+
invalidProcessor = false,
|
313
|
+
invalidLanguage = false;
|
276
314
|
|
277
315
|
// Check parser value
|
278
316
|
if (languageOptions && languageOptions.parser) {
|
@@ -290,6 +328,29 @@ class FlatConfigArray extends ConfigArray {
|
|
290
328
|
}
|
291
329
|
}
|
292
330
|
|
331
|
+
// Check language value
|
332
|
+
if (language) {
|
333
|
+
if (typeof language === "string") {
|
334
|
+
const { pluginName, objectName: localLanguageName } = splitPluginIdentifier(language);
|
335
|
+
|
336
|
+
languageName = language;
|
337
|
+
|
338
|
+
if (!plugins || !plugins[pluginName] || !plugins[pluginName].languages || !plugins[pluginName].languages[localLanguageName]) {
|
339
|
+
throw new TypeError(`Key "language": Could not find "${localLanguageName}" in plugin "${pluginName}".`);
|
340
|
+
}
|
341
|
+
|
342
|
+
config.language = plugins[pluginName].languages[localLanguageName];
|
343
|
+
} else {
|
344
|
+
invalidLanguage = true;
|
345
|
+
}
|
346
|
+
|
347
|
+
try {
|
348
|
+
config.language.validateLanguageOptions(config.languageOptions);
|
349
|
+
} catch (error) {
|
350
|
+
throw new TypeError(`Key "languageOptions": ${error.message}`, { cause: error });
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
293
354
|
// Check processor value
|
294
355
|
if (processor) {
|
295
356
|
if (typeof processor === "string") {
|
@@ -329,6 +390,10 @@ class FlatConfigArray extends ConfigArray {
|
|
329
390
|
throw new Error("Could not serialize processor object (missing 'meta' object).");
|
330
391
|
}
|
331
392
|
|
393
|
+
if (invalidLanguage) {
|
394
|
+
throw new Error("Caching is not supported when language is an object.");
|
395
|
+
}
|
396
|
+
|
332
397
|
return {
|
333
398
|
...this,
|
334
399
|
plugins: Object.entries(plugins).map(([namespace, plugin]) => {
|
@@ -341,10 +406,8 @@ class FlatConfigArray extends ConfigArray {
|
|
341
406
|
|
342
407
|
return `${namespace}:${pluginId}`;
|
343
408
|
}),
|
344
|
-
|
345
|
-
|
346
|
-
parser: parserName
|
347
|
-
},
|
409
|
+
language: languageName,
|
410
|
+
languageOptions: languageOptionsToJSON(languageOptions),
|
348
411
|
processor: processorName
|
349
412
|
};
|
350
413
|
}
|
@@ -33,12 +33,6 @@ const ruleSeverities = new Map([
|
|
33
33
|
[2, 2], ["error", 2]
|
34
34
|
]);
|
35
35
|
|
36
|
-
const globalVariablesValues = new Set([
|
37
|
-
true, "true", "writable", "writeable",
|
38
|
-
false, "false", "readonly", "readable", null,
|
39
|
-
"off"
|
40
|
-
]);
|
41
|
-
|
42
36
|
/**
|
43
37
|
* Check if a value is a non-null object.
|
44
38
|
* @param {any} value The value to check.
|
@@ -143,6 +137,23 @@ function normalizeRuleOptions(ruleOptions) {
|
|
143
137
|
return structuredClone(finalOptions);
|
144
138
|
}
|
145
139
|
|
140
|
+
/**
|
141
|
+
* Determines if an object has any methods.
|
142
|
+
* @param {Object} object The object to check.
|
143
|
+
* @returns {boolean} `true` if the object has any methods.
|
144
|
+
*/
|
145
|
+
function hasMethod(object) {
|
146
|
+
|
147
|
+
for (const key of Object.keys(object)) {
|
148
|
+
|
149
|
+
if (typeof object[key] === "function") {
|
150
|
+
return true;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
return false;
|
155
|
+
}
|
156
|
+
|
146
157
|
//-----------------------------------------------------------------------------
|
147
158
|
// Assertions
|
148
159
|
//-----------------------------------------------------------------------------
|
@@ -301,47 +312,48 @@ const deepObjectAssignSchema = {
|
|
301
312
|
validate: "object"
|
302
313
|
};
|
303
314
|
|
315
|
+
|
304
316
|
//-----------------------------------------------------------------------------
|
305
317
|
// High-Level Schemas
|
306
318
|
//-----------------------------------------------------------------------------
|
307
319
|
|
308
320
|
/** @type {ObjectPropertySchema} */
|
309
|
-
const
|
310
|
-
merge
|
311
|
-
validate(value) {
|
321
|
+
const languageOptionsSchema = {
|
322
|
+
merge(first = {}, second = {}) {
|
312
323
|
|
313
|
-
|
324
|
+
const result = deepMerge(first, second);
|
314
325
|
|
315
|
-
for (const key of Object.
|
326
|
+
for (const [key, value] of Object.entries(result)) {
|
316
327
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
328
|
+
/*
|
329
|
+
* Special case: Because the `parser` property is an object, it should
|
330
|
+
* not be deep merged. Instead, it should be replaced if it exists in
|
331
|
+
* the second object. To make this more generic, we just check for
|
332
|
+
* objects with methods and replace them if they exist in the second
|
333
|
+
* object.
|
334
|
+
*/
|
335
|
+
if (isNonArrayObject(value)) {
|
336
|
+
if (hasMethod(value)) {
|
337
|
+
result[key] = second[key] ?? first[key];
|
338
|
+
continue;
|
339
|
+
}
|
321
340
|
|
322
|
-
|
323
|
-
|
341
|
+
// for other objects, make sure we aren't reusing the same object
|
342
|
+
result[key] = { ...result[key] };
|
343
|
+
continue;
|
324
344
|
}
|
325
345
|
|
326
|
-
if (!globalVariablesValues.has(value[key])) {
|
327
|
-
throw new TypeError(`Key "${key}": Expected "readonly", "writable", or "off".`);
|
328
|
-
}
|
329
346
|
}
|
330
|
-
|
347
|
+
|
348
|
+
return result;
|
349
|
+
},
|
350
|
+
validate: "object"
|
331
351
|
};
|
332
352
|
|
333
353
|
/** @type {ObjectPropertySchema} */
|
334
|
-
const
|
354
|
+
const languageSchema = {
|
335
355
|
merge: "replace",
|
336
|
-
validate
|
337
|
-
|
338
|
-
if (!value || typeof value !== "object" ||
|
339
|
-
(typeof value.parse !== "function" && typeof value.parseForESLint !== "function")
|
340
|
-
) {
|
341
|
-
throw new TypeError("Expected object with parse() or parseForESLint() method.");
|
342
|
-
}
|
343
|
-
|
344
|
-
}
|
356
|
+
validate: assertIsPluginMemberName
|
345
357
|
};
|
346
358
|
|
347
359
|
/** @type {ObjectPropertySchema} */
|
@@ -501,28 +513,6 @@ const rulesSchema = {
|
|
501
513
|
}
|
502
514
|
};
|
503
515
|
|
504
|
-
/** @type {ObjectPropertySchema} */
|
505
|
-
const ecmaVersionSchema = {
|
506
|
-
merge: "replace",
|
507
|
-
validate(value) {
|
508
|
-
if (typeof value === "number" || value === "latest") {
|
509
|
-
return;
|
510
|
-
}
|
511
|
-
|
512
|
-
throw new TypeError("Expected a number or \"latest\".");
|
513
|
-
}
|
514
|
-
};
|
515
|
-
|
516
|
-
/** @type {ObjectPropertySchema} */
|
517
|
-
const sourceTypeSchema = {
|
518
|
-
merge: "replace",
|
519
|
-
validate(value) {
|
520
|
-
if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) {
|
521
|
-
throw new TypeError("Expected \"script\", \"module\", or \"commonjs\".");
|
522
|
-
}
|
523
|
-
}
|
524
|
-
};
|
525
|
-
|
526
516
|
/**
|
527
517
|
* Creates a schema that always throws an error. Useful for warning
|
528
518
|
* about eslintrc-style keys.
|
@@ -568,15 +558,8 @@ const flatConfigSchema = {
|
|
568
558
|
reportUnusedDisableDirectives: disableDirectiveSeveritySchema
|
569
559
|
}
|
570
560
|
},
|
571
|
-
|
572
|
-
|
573
|
-
ecmaVersion: ecmaVersionSchema,
|
574
|
-
sourceType: sourceTypeSchema,
|
575
|
-
globals: globalsSchema,
|
576
|
-
parser: parserSchema,
|
577
|
-
parserOptions: deepObjectAssignSchema
|
578
|
-
}
|
579
|
-
},
|
561
|
+
language: languageSchema,
|
562
|
+
languageOptions: languageOptionsSchema,
|
580
563
|
processor: processorSchema,
|
581
564
|
plugins: pluginsSchema,
|
582
565
|
rules: rulesSchema
|
@@ -588,5 +571,6 @@ const flatConfigSchema = {
|
|
588
571
|
|
589
572
|
module.exports = {
|
590
573
|
flatConfigSchema,
|
574
|
+
hasMethod,
|
591
575
|
assertIsRuleSeverity
|
592
576
|
};
|
@@ -91,7 +91,7 @@ class AllFilesIgnoredError extends Error {
|
|
91
91
|
*/
|
92
92
|
constructor(pattern) {
|
93
93
|
super(`All files matched by '${pattern}' are ignored.`);
|
94
|
-
this.messageTemplate = "all-files-ignored";
|
94
|
+
this.messageTemplate = "all-matched-files-ignored";
|
95
95
|
this.messageData = { pattern };
|
96
96
|
}
|
97
97
|
}
|
@@ -335,15 +335,15 @@ async function globSearch({
|
|
335
335
|
|
336
336
|
/*
|
337
337
|
* We updated the unmatched patterns set only if the path
|
338
|
-
* matches and the file
|
339
|
-
*
|
338
|
+
* matches and the file has a config. If the file has no
|
339
|
+
* config, that means there wasn't a match for the
|
340
340
|
* pattern so it should not be removed.
|
341
341
|
*
|
342
|
-
* Performance note:
|
342
|
+
* Performance note: `getConfig()` aggressively caches
|
343
343
|
* results so there is no performance penalty for calling
|
344
|
-
* it
|
344
|
+
* it multiple times with the same argument.
|
345
345
|
*/
|
346
|
-
if (pathMatches &&
|
346
|
+
if (pathMatches && configs.getConfig(entry.path)) {
|
347
347
|
unmatchedPatterns.delete(matcher.pattern);
|
348
348
|
}
|
349
349
|
|
@@ -351,7 +351,7 @@ async function globSearch({
|
|
351
351
|
}, false)
|
352
352
|
: matchers.some(matcher => matcher.match(relativePath));
|
353
353
|
|
354
|
-
return matchesPattern &&
|
354
|
+
return matchesPattern && configs.getConfig(entry.path) !== void 0;
|
355
355
|
})
|
356
356
|
},
|
357
357
|
(error, entries) => {
|
@@ -494,7 +494,7 @@ async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) {
|
|
494
494
|
|
495
495
|
}
|
496
496
|
|
497
|
-
return
|
497
|
+
return filePaths;
|
498
498
|
|
499
499
|
}
|
500
500
|
|
@@ -543,10 +543,7 @@ async function findFiles({
|
|
543
543
|
|
544
544
|
// files are added directly to the list
|
545
545
|
if (stat.isFile()) {
|
546
|
-
results.push(
|
547
|
-
filePath,
|
548
|
-
ignored: configs.isFileIgnored(filePath)
|
549
|
-
});
|
546
|
+
results.push(filePath);
|
550
547
|
}
|
551
548
|
|
552
549
|
// directories need extensions attached
|
@@ -604,11 +601,10 @@ async function findFiles({
|
|
604
601
|
});
|
605
602
|
|
606
603
|
return [
|
607
|
-
...
|
608
|
-
|
609
|
-
filePath
|
610
|
-
|
611
|
-
}))
|
604
|
+
...new Set([
|
605
|
+
...results,
|
606
|
+
...globbyResults.map(filePath => path.resolve(filePath))
|
607
|
+
])
|
612
608
|
];
|
613
609
|
}
|
614
610
|
|
@@ -630,17 +626,31 @@ function isErrorMessage(message) {
|
|
630
626
|
* Returns result with warning by ignore settings
|
631
627
|
* @param {string} filePath File path of checked code
|
632
628
|
* @param {string} baseDir Absolute path of base directory
|
629
|
+
* @param {"ignored"|"external"|"unconfigured"} configStatus A status that determines why the file is ignored
|
633
630
|
* @returns {LintResult} Result with single warning
|
634
631
|
* @private
|
635
632
|
*/
|
636
|
-
function createIgnoreResult(filePath, baseDir) {
|
633
|
+
function createIgnoreResult(filePath, baseDir, configStatus) {
|
637
634
|
let message;
|
638
|
-
const isInNodeModules = baseDir && path.dirname(path.relative(baseDir, filePath)).split(path.sep).includes("node_modules");
|
639
635
|
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
636
|
+
switch (configStatus) {
|
637
|
+
case "external":
|
638
|
+
message = "File ignored because outside of base path.";
|
639
|
+
break;
|
640
|
+
case "unconfigured":
|
641
|
+
message = "File ignored because no matching configuration was supplied.";
|
642
|
+
break;
|
643
|
+
default:
|
644
|
+
{
|
645
|
+
const isInNodeModules = baseDir && path.dirname(path.relative(baseDir, filePath)).split(path.sep).includes("node_modules");
|
646
|
+
|
647
|
+
if (isInNodeModules) {
|
648
|
+
message = "File ignored by default because it is located under the node_modules directory. Use ignore pattern \"!**/node_modules/\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning.";
|
649
|
+
} else {
|
650
|
+
message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning.";
|
651
|
+
}
|
652
|
+
}
|
653
|
+
break;
|
644
654
|
}
|
645
655
|
|
646
656
|
return {
|
package/lib/eslint/eslint.js
CHANGED
@@ -68,7 +68,7 @@ const { Retrier } = require("@humanwhocodes/retry");
|
|
68
68
|
* The options with which to configure the ESLint instance.
|
69
69
|
* @typedef {Object} ESLintOptions
|
70
70
|
* @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
|
71
|
-
* @property {ConfigData} [baseConfig] Base config
|
71
|
+
* @property {ConfigData|Array<ConfigData>} [baseConfig] Base config, extended by all configs used with this instance
|
72
72
|
* @property {boolean} [cache] Enable result caching.
|
73
73
|
* @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
|
74
74
|
* @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
|
@@ -79,7 +79,7 @@ const { Retrier } = require("@humanwhocodes/retry");
|
|
79
79
|
* @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
80
|
* @property {boolean} [ignore] False disables all ignore patterns except for the default ones.
|
81
81
|
* @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to config ignores. These patterns are relative to `cwd`.
|
82
|
-
* @property {ConfigData} [overrideConfig] Override config
|
82
|
+
* @property {ConfigData|Array<ConfigData>} [overrideConfig] Override config, overrides all configs used with this instance
|
83
83
|
* @property {boolean|string} [overrideConfigFile] Searches for default config file when falsy;
|
84
84
|
* doesn't do any config file lookup when `true`; considered to be a config filename
|
85
85
|
* when a string.
|
@@ -509,7 +509,7 @@ function verifyText({
|
|
509
509
|
* @returns {boolean} `true` if the linter should adopt the code block.
|
510
510
|
*/
|
511
511
|
filterCodeBlock(blockFilename) {
|
512
|
-
return configs.
|
512
|
+
return configs.getConfig(blockFilename) !== void 0;
|
513
513
|
}
|
514
514
|
}
|
515
515
|
);
|
@@ -865,28 +865,21 @@ class ESLint {
|
|
865
865
|
*/
|
866
866
|
const results = await Promise.all(
|
867
867
|
|
868
|
-
filePaths.map(
|
869
|
-
|
870
|
-
/*
|
871
|
-
* If a filename was entered that matches an ignore
|
872
|
-
* pattern, then notify the user.
|
873
|
-
*/
|
874
|
-
if (ignored) {
|
875
|
-
if (warnIgnored) {
|
876
|
-
return createIgnoreResult(filePath, cwd);
|
877
|
-
}
|
878
|
-
|
879
|
-
return void 0;
|
880
|
-
}
|
868
|
+
filePaths.map(filePath => {
|
881
869
|
|
882
870
|
const config = configs.getConfig(filePath);
|
883
871
|
|
884
872
|
/*
|
885
|
-
*
|
886
|
-
*
|
887
|
-
* and we just silently ignore the file.
|
873
|
+
* If a filename was entered that cannot be matched
|
874
|
+
* to a config, then notify the user.
|
888
875
|
*/
|
889
876
|
if (!config) {
|
877
|
+
if (warnIgnored) {
|
878
|
+
const configStatus = configs.getConfigStatus(filePath);
|
879
|
+
|
880
|
+
return createIgnoreResult(filePath, cwd, configStatus);
|
881
|
+
}
|
882
|
+
|
890
883
|
return void 0;
|
891
884
|
}
|
892
885
|
|
@@ -1038,7 +1031,9 @@ class ESLint {
|
|
1038
1031
|
const shouldWarnIgnored = typeof warnIgnored === "boolean" ? warnIgnored : constructorWarnIgnored;
|
1039
1032
|
|
1040
1033
|
if (shouldWarnIgnored) {
|
1041
|
-
|
1034
|
+
const configStatus = configs.getConfigStatus(resolvedFilename);
|
1035
|
+
|
1036
|
+
results.push(createIgnoreResult(resolvedFilename, cwd, configStatus));
|
1042
1037
|
}
|
1043
1038
|
} else {
|
1044
1039
|
|