eslint 9.14.0 → 9.15.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 +1 -1
- package/lib/cli-engine/formatters/stylish.js +3 -3
- package/lib/cli-engine/lint-result-cache.js +1 -1
- package/lib/config/config.js +40 -24
- package/lib/eslint/eslint-helpers.js +9 -13
- package/lib/languages/js/index.js +76 -0
- package/lib/languages/js/source-code/token-store/index.js +1 -1
- package/lib/linter/code-path-analysis/code-path-analyzer.js +1 -1
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/linter.js +36 -35
- package/lib/linter/report-translator.js +1 -1
- package/lib/rule-tester/rule-tester.js +1 -1
- package/lib/rules/accessor-pairs.js +10 -7
- package/lib/rules/array-callback-return.js +10 -8
- package/lib/rules/arrow-body-style.js +3 -1
- package/lib/rules/camelcase.js +18 -12
- package/lib/rules/class-methods-use-this.js +9 -5
- package/lib/rules/complexity.js +9 -5
- package/lib/rules/consistent-return.js +4 -4
- package/lib/rules/consistent-this.js +3 -7
- package/lib/rules/curly.js +3 -140
- package/lib/rules/default-case.js +3 -1
- package/lib/rules/dot-notation.js +9 -6
- package/lib/rules/func-names.js +3 -3
- package/lib/rules/func-style.js +10 -8
- package/lib/rules/getter-return.js +5 -5
- package/lib/rules/grouped-accessor-pairs.js +3 -1
- package/lib/rules/id-denylist.js +2 -1
- package/lib/rules/id-length.js +10 -6
- package/lib/rules/id-match.js +13 -16
- package/lib/rules/new-cap.js +15 -34
- package/lib/rules/no-bitwise.js +4 -5
- package/lib/rules/no-cond-assign.js +3 -3
- package/lib/rules/no-console.js +3 -2
- package/lib/rules/no-constant-condition.js +5 -4
- package/lib/rules/no-duplicate-imports.js +5 -4
- package/lib/rules/no-else-return.js +4 -5
- package/lib/rules/no-empty-function.js +4 -4
- package/lib/rules/no-empty-pattern.js +4 -4
- package/lib/rules/no-empty.js +6 -5
- package/lib/rules/no-eval.js +4 -5
- package/lib/rules/no-extend-native.js +3 -3
- package/lib/rules/no-extra-boolean-cast.js +3 -3
- package/lib/rules/no-fallthrough.js +12 -15
- package/lib/rules/no-global-assign.js +3 -2
- package/lib/rules/no-implicit-coercion.js +13 -24
- package/lib/rules/no-implicit-globals.js +4 -4
- package/lib/rules/no-inline-comments.js +4 -6
- package/lib/rules/no-inner-declarations.js +4 -2
- package/lib/rules/no-invalid-regexp.js +5 -4
- package/lib/rules/no-invalid-this.js +4 -4
- package/lib/rules/no-irregular-whitespace.js +24 -22
- package/lib/rules/no-labels.js +8 -7
- package/lib/rules/no-lonely-if.js +8 -2
- package/lib/rules/no-multi-assign.js +5 -10
- package/lib/rules/no-plusplus.js +4 -9
- package/lib/rules/no-promise-executor-return.js +4 -6
- package/lib/rules/no-redeclare.js +5 -8
- package/lib/rules/no-return-assign.js +3 -1
- package/lib/rules/no-self-assign.js +4 -3
- package/lib/rules/no-sequences.js +7 -7
- package/lib/rules/no-shadow.js +18 -14
- package/lib/rules/no-undef.js +4 -4
- package/lib/rules/no-underscore-dangle.js +31 -28
- package/lib/rules/no-unneeded-ternary.js +4 -4
- package/lib/rules/no-unreachable-loop.js +4 -2
- package/lib/rules/no-unsafe-negation.js +4 -4
- package/lib/rules/no-unsafe-optional-chaining.js +4 -4
- package/lib/rules/no-unused-expressions.js +17 -13
- package/lib/rules/no-use-before-define.js +14 -13
- package/lib/rules/no-useless-computed-key.js +9 -3
- package/lib/rules/no-useless-rename.js +7 -8
- package/lib/rules/no-void.js +4 -4
- package/lib/rules/no-warning-comments.js +9 -7
- package/lib/rules/operator-assignment.js +4 -2
- package/lib/rules/prefer-arrow-callback.js +5 -8
- package/lib/rules/prefer-const.js +5 -3
- package/lib/rules/prefer-promise-reject-errors.js +5 -3
- package/lib/rules/prefer-regex-literals.js +4 -3
- package/lib/rules/radix.js +3 -1
- package/lib/rules/require-atomic-updates.js +4 -3
- package/lib/rules/sort-imports.js +20 -16
- package/lib/rules/sort-keys.js +13 -16
- package/lib/rules/sort-vars.js +4 -4
- package/lib/rules/strict.js +3 -2
- package/lib/rules/unicode-bom.js +4 -2
- package/lib/rules/use-isnan.js +7 -4
- package/lib/rules/utils/ast-utils.js +141 -0
- package/lib/rules/valid-typeof.js +3 -2
- package/lib/rules/yoda.js +9 -12
- package/lib/shared/assert.js +22 -0
- package/lib/shared/deep-merge-arrays.js +60 -0
- package/lib/shared/text-table.js +67 -0
- package/lib/shared/types.js +1 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/rules/ecmascript-6.d.ts +36 -16
- package/lib/types/rules/stylistic-issues.d.ts +3 -0
- package/package.json +10 -11
package/README.md
CHANGED
@@ -300,7 +300,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
|
300
300
|
<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>
|
301
301
|
<p><a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3>
|
302
302
|
<p><a href="https://www.serptriumph.com/"><img src="https://images.opencollective.com/serp-triumph5/fea3074/logo.png" alt="SERP Triumph" height="64"></a> <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>
|
303
|
-
<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://www.wordhint.net/"><img src="https://images.opencollective.com/wordhint/be86813/avatar.png" alt="WordHint" 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.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340?v=4" alt="GitBook" 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></p>
|
303
|
+
<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://www.wordhint.net/"><img src="https://images.opencollective.com/wordhint/be86813/avatar.png" alt="WordHint" 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.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340?v=4" alt="GitBook" 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></p>
|
304
304
|
<h3>Technology Sponsors</h3>
|
305
305
|
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.
|
306
306
|
<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>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
const chalk = require("chalk"),
|
8
8
|
util = require("node:util"),
|
9
|
-
table = require("text-table");
|
9
|
+
table = require("../../shared/text-table");
|
10
10
|
|
11
11
|
//------------------------------------------------------------------------------
|
12
12
|
// Helpers
|
@@ -62,8 +62,8 @@ module.exports = function(results) {
|
|
62
62
|
|
63
63
|
return [
|
64
64
|
"",
|
65
|
-
message.line || 0,
|
66
|
-
message.column || 0,
|
65
|
+
String(message.line || 0),
|
66
|
+
String(message.column || 0),
|
67
67
|
messageType,
|
68
68
|
message.message.replace(/([^ ])\.$/u, "$1"),
|
69
69
|
chalk.dim(message.ruleId || "")
|
@@ -8,11 +8,11 @@
|
|
8
8
|
// Requirements
|
9
9
|
//-----------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const assert = require("node:assert");
|
12
11
|
const fs = require("node:fs");
|
13
12
|
const fileEntryCache = require("file-entry-cache");
|
14
13
|
const stringify = require("json-stable-stringify-without-jsonify");
|
15
14
|
const pkg = require("../../package.json");
|
15
|
+
const assert = require("../shared/assert");
|
16
16
|
const hash = require("./hash");
|
17
17
|
|
18
18
|
const debug = require("debug")("eslint:lint-result-cache");
|
package/lib/config/config.js
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
// Requirements
|
10
10
|
//-----------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const {
|
12
|
+
const { deepMergeArrays } = require("../shared/deep-merge-arrays");
|
13
|
+
const { getRuleFromConfig } = require("./flat-config-helpers");
|
13
14
|
const { flatConfigSchema, hasMethod } = require("./flat-config-schema");
|
15
|
+
const { RuleValidator } = require("./rule-validator");
|
14
16
|
const { ObjectSchema } = require("@eslint/config-array");
|
15
17
|
|
16
18
|
//-----------------------------------------------------------------------------
|
@@ -119,28 +121,6 @@ function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
|
|
119
121
|
return result;
|
120
122
|
}
|
121
123
|
|
122
|
-
/**
|
123
|
-
* Normalizes the rules configuration. Ensure that each rule config is
|
124
|
-
* an array and that the severity is a number. This function modifies the
|
125
|
-
* rulesConfig.
|
126
|
-
* @param {Record<string, any>} rulesConfig The rules configuration to normalize.
|
127
|
-
* @returns {void}
|
128
|
-
*/
|
129
|
-
function normalizeRulesConfig(rulesConfig) {
|
130
|
-
|
131
|
-
for (const [ruleId, ruleConfig] of Object.entries(rulesConfig)) {
|
132
|
-
|
133
|
-
// ensure rule config is an array
|
134
|
-
if (!Array.isArray(ruleConfig)) {
|
135
|
-
rulesConfig[ruleId] = [ruleConfig];
|
136
|
-
}
|
137
|
-
|
138
|
-
// normalize severity
|
139
|
-
rulesConfig[ruleId][0] = severities.get(rulesConfig[ruleId][0]);
|
140
|
-
}
|
141
|
-
|
142
|
-
}
|
143
|
-
|
144
124
|
|
145
125
|
//-----------------------------------------------------------------------------
|
146
126
|
// Exports
|
@@ -215,6 +195,11 @@ class Config {
|
|
215
195
|
throw new TypeError(`Key "languageOptions": ${error.message}`, { cause: error });
|
216
196
|
}
|
217
197
|
|
198
|
+
// Normalize language options if necessary
|
199
|
+
if (this.language.normalizeLanguageOptions) {
|
200
|
+
this.languageOptions = this.language.normalizeLanguageOptions(this.languageOptions);
|
201
|
+
}
|
202
|
+
|
218
203
|
// Check processor value
|
219
204
|
if (processor) {
|
220
205
|
this.processor = processor;
|
@@ -239,7 +224,7 @@ class Config {
|
|
239
224
|
|
240
225
|
// Process the rules
|
241
226
|
if (this.rules) {
|
242
|
-
normalizeRulesConfig(
|
227
|
+
this.#normalizeRulesConfig();
|
243
228
|
ruleValidator.validate(this);
|
244
229
|
}
|
245
230
|
}
|
@@ -276,6 +261,37 @@ class Config {
|
|
276
261
|
processor: this.#processorName
|
277
262
|
};
|
278
263
|
}
|
264
|
+
|
265
|
+
/**
|
266
|
+
* Normalizes the rules configuration. Ensures that each rule config is
|
267
|
+
* an array and that the severity is a number. Applies meta.defaultOptions.
|
268
|
+
* This function modifies `this.rules`.
|
269
|
+
* @returns {void}
|
270
|
+
*/
|
271
|
+
#normalizeRulesConfig() {
|
272
|
+
for (const [ruleId, originalConfig] of Object.entries(this.rules)) {
|
273
|
+
|
274
|
+
// ensure rule config is an array
|
275
|
+
let ruleConfig = Array.isArray(originalConfig)
|
276
|
+
? originalConfig
|
277
|
+
: [originalConfig];
|
278
|
+
|
279
|
+
// normalize severity
|
280
|
+
ruleConfig[0] = severities.get(ruleConfig[0]);
|
281
|
+
|
282
|
+
const rule = getRuleFromConfig(ruleId, this);
|
283
|
+
|
284
|
+
// apply meta.defaultOptions
|
285
|
+
const slicedOptions = ruleConfig.slice(1);
|
286
|
+
const mergedOptions = deepMergeArrays(rule?.meta?.defaultOptions, slicedOptions);
|
287
|
+
|
288
|
+
if (mergedOptions.length) {
|
289
|
+
ruleConfig = [ruleConfig[0], ...mergedOptions];
|
290
|
+
}
|
291
|
+
|
292
|
+
this.rules[ruleId] = ruleConfig;
|
293
|
+
}
|
294
|
+
}
|
279
295
|
}
|
280
296
|
|
281
297
|
module.exports = { Config };
|
@@ -155,16 +155,14 @@ function isGlobPattern(pattern) {
|
|
155
155
|
* Used primarily to help with useful error messages.
|
156
156
|
* @param {Object} options The options for the function.
|
157
157
|
* @param {string} options.basePath The directory to search.
|
158
|
-
* @param {string} options.pattern
|
158
|
+
* @param {string} options.pattern An absolute path glob pattern to match.
|
159
159
|
* @returns {Promise<boolean>} True if there is a glob match, false if not.
|
160
160
|
*/
|
161
161
|
async function globMatch({ basePath, pattern }) {
|
162
162
|
|
163
163
|
let found = false;
|
164
164
|
const { hfs } = await import("@humanfs/node");
|
165
|
-
const patternToUse = path.
|
166
|
-
? normalizeToPosix(path.relative(basePath, pattern))
|
167
|
-
: pattern;
|
165
|
+
const patternToUse = normalizeToPosix(path.relative(basePath, pattern));
|
168
166
|
|
169
167
|
const matcher = new Minimatch(patternToUse, MINIMATCH_OPTIONS);
|
170
168
|
|
@@ -202,7 +200,7 @@ async function globMatch({ basePath, pattern }) {
|
|
202
200
|
* ESLint.
|
203
201
|
* @param {Object} options The options for this function.
|
204
202
|
* @param {string} options.basePath The directory to search.
|
205
|
-
* @param {Array<string>} options.patterns An array of glob patterns
|
203
|
+
* @param {Array<string>} options.patterns An array of absolute path glob patterns
|
206
204
|
* to match.
|
207
205
|
* @param {Array<string>} options.rawPatterns An array of glob patterns
|
208
206
|
* as the user inputted them. Used for errors.
|
@@ -241,9 +239,7 @@ async function globSearch({
|
|
241
239
|
*/
|
242
240
|
const relativeToPatterns = new Map();
|
243
241
|
const matchers = patterns.map((pattern, i) => {
|
244
|
-
const patternToUse = path.
|
245
|
-
? normalizeToPosix(path.relative(basePath, pattern))
|
246
|
-
: pattern;
|
242
|
+
const patternToUse = normalizeToPosix(path.relative(basePath, pattern));
|
247
243
|
|
248
244
|
relativeToPatterns.set(patternToUse, patterns[i]);
|
249
245
|
|
@@ -353,7 +349,7 @@ async function globSearch({
|
|
353
349
|
* that were used in the original search.
|
354
350
|
* @param {Array<string>} options.rawPatterns An array of glob patterns
|
355
351
|
* as the user inputted them. Used for errors.
|
356
|
-
* @param {Array<string>} options.unmatchedPatterns A non-empty array of glob patterns
|
352
|
+
* @param {Array<string>} options.unmatchedPatterns A non-empty array of absolute path glob patterns
|
357
353
|
* that were unmatched in the original search.
|
358
354
|
* @returns {void} Always throws an error.
|
359
355
|
* @throws {NoFilesFoundError} If the first unmatched pattern
|
@@ -388,7 +384,7 @@ async function throwErrorForUnmatchedPatterns({
|
|
388
384
|
* Performs multiple glob searches in parallel.
|
389
385
|
* @param {Object} options The options for this function.
|
390
386
|
* @param {Map<string,GlobSearch>} options.searches
|
391
|
-
*
|
387
|
+
* A map of absolute path glob patterns to match.
|
392
388
|
* @param {ConfigLoader|LegacyConfigLoader} options.configLoader The config loader to use for
|
393
389
|
* determining what to ignore.
|
394
390
|
* @param {boolean} options.errorOnUnmatchedPattern Determines if an
|
@@ -597,7 +593,7 @@ async function findFiles({
|
|
597
593
|
return [
|
598
594
|
...new Set([
|
599
595
|
...results,
|
600
|
-
...globbyResults
|
596
|
+
...globbyResults
|
601
597
|
])
|
602
598
|
];
|
603
599
|
}
|
@@ -618,7 +614,7 @@ function isErrorMessage(message) {
|
|
618
614
|
|
619
615
|
/**
|
620
616
|
* Returns result with warning by ignore settings
|
621
|
-
* @param {string} filePath
|
617
|
+
* @param {string} filePath Absolute file path of checked code
|
622
618
|
* @param {string} baseDir Absolute path of base directory
|
623
619
|
* @param {"ignored"|"external"|"unconfigured"} configStatus A status that determines why the file is ignored
|
624
620
|
* @returns {LintResult} Result with single warning
|
@@ -648,7 +644,7 @@ function createIgnoreResult(filePath, baseDir, configStatus) {
|
|
648
644
|
}
|
649
645
|
|
650
646
|
return {
|
651
|
-
filePath
|
647
|
+
filePath,
|
652
648
|
messages: [
|
653
649
|
{
|
654
650
|
ruleId: null,
|
@@ -16,6 +16,7 @@ const espree = require("espree");
|
|
16
16
|
const eslintScope = require("eslint-scope");
|
17
17
|
const evk = require("eslint-visitor-keys");
|
18
18
|
const { validateLanguageOptions } = require("./validate-language-options");
|
19
|
+
const { LATEST_ECMA_VERSION } = require("../../../conf/ecma-version");
|
19
20
|
|
20
21
|
//-----------------------------------------------------------------------------
|
21
22
|
// Type Definitions
|
@@ -31,6 +32,7 @@ const { validateLanguageOptions } = require("./validate-language-options");
|
|
31
32
|
|
32
33
|
const debug = createDebug("eslint:languages:js");
|
33
34
|
const DEFAULT_ECMA_VERSION = 5;
|
35
|
+
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
34
36
|
|
35
37
|
/**
|
36
38
|
* Analyze scope of the given AST.
|
@@ -55,6 +57,47 @@ function analyzeScope(ast, languageOptions, visitorKeys) {
|
|
55
57
|
});
|
56
58
|
}
|
57
59
|
|
60
|
+
/**
|
61
|
+
* Determines if a given object is Espree.
|
62
|
+
* @param {Object} parser The parser to check.
|
63
|
+
* @returns {boolean} True if the parser is Espree or false if not.
|
64
|
+
*/
|
65
|
+
function isEspree(parser) {
|
66
|
+
return !!(parser === espree || parser[parserSymbol] === espree);
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Normalize ECMAScript version from the initial config into languageOptions (year)
|
71
|
+
* format.
|
72
|
+
* @param {any} [ecmaVersion] ECMAScript version from the initial config
|
73
|
+
* @returns {number} normalized ECMAScript version
|
74
|
+
*/
|
75
|
+
function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
76
|
+
|
77
|
+
switch (ecmaVersion) {
|
78
|
+
case 3:
|
79
|
+
return 3;
|
80
|
+
|
81
|
+
// void 0 = no ecmaVersion specified so use the default
|
82
|
+
case 5:
|
83
|
+
case void 0:
|
84
|
+
return 5;
|
85
|
+
|
86
|
+
default:
|
87
|
+
if (typeof ecmaVersion === "number") {
|
88
|
+
return ecmaVersion >= 2015 ? ecmaVersion : ecmaVersion + 2009;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
/*
|
93
|
+
* We default to the latest supported ecmaVersion for everything else.
|
94
|
+
* Remember, this is for languageOptions.ecmaVersion, which sets the version
|
95
|
+
* that is used for a number of processes inside of ESLint. It's normally
|
96
|
+
* safe to assume people want the latest unless otherwise specified.
|
97
|
+
*/
|
98
|
+
return LATEST_ECMA_VERSION;
|
99
|
+
}
|
100
|
+
|
58
101
|
//-----------------------------------------------------------------------------
|
59
102
|
// Exports
|
60
103
|
//-----------------------------------------------------------------------------
|
@@ -79,6 +122,39 @@ module.exports = {
|
|
79
122
|
|
80
123
|
validateLanguageOptions,
|
81
124
|
|
125
|
+
/**
|
126
|
+
* Normalizes the language options.
|
127
|
+
* @param {Object} languageOptions The language options to normalize.
|
128
|
+
* @returns {Object} The normalized language options.
|
129
|
+
*/
|
130
|
+
normalizeLanguageOptions(languageOptions) {
|
131
|
+
|
132
|
+
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
|
133
|
+
languageOptions.ecmaVersion
|
134
|
+
);
|
135
|
+
|
136
|
+
// Espree expects this information to be passed in
|
137
|
+
if (isEspree(languageOptions.parser)) {
|
138
|
+
const parserOptions = languageOptions.parserOptions;
|
139
|
+
|
140
|
+
if (languageOptions.sourceType) {
|
141
|
+
|
142
|
+
parserOptions.sourceType = languageOptions.sourceType;
|
143
|
+
|
144
|
+
if (
|
145
|
+
parserOptions.sourceType === "module" &&
|
146
|
+
parserOptions.ecmaFeatures &&
|
147
|
+
parserOptions.ecmaFeatures.globalReturn
|
148
|
+
) {
|
149
|
+
parserOptions.ecmaFeatures.globalReturn = false;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
return languageOptions;
|
155
|
+
|
156
|
+
},
|
157
|
+
|
82
158
|
/**
|
83
159
|
* Determines if a given node matches a given selector class.
|
84
160
|
* @param {string} className The class name to check.
|
@@ -8,8 +8,8 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const assert = require("node:assert");
|
12
11
|
const { isCommentToken } = require("@eslint-community/eslint-utils");
|
12
|
+
const assert = require("../../../../shared/assert");
|
13
13
|
const cursors = require("./cursors");
|
14
14
|
const ForwardTokenCursor = require("./forward-token-cursor");
|
15
15
|
const PaddedTokenCursor = require("./padded-token-cursor");
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const assert = require("
|
12
|
+
const assert = require("../../shared/assert"),
|
13
13
|
{ breakableTypePattern } = require("../../shared/ast-utils"),
|
14
14
|
CodePath = require("./code-path"),
|
15
15
|
CodePathSegment = require("./code-path-segment"),
|
@@ -13,7 +13,7 @@
|
|
13
13
|
// Requirements
|
14
14
|
//------------------------------------------------------------------------------
|
15
15
|
|
16
|
-
const assert = require("
|
16
|
+
const assert = require("../../shared/assert"),
|
17
17
|
CodePathSegment = require("./code-path-segment");
|
18
18
|
|
19
19
|
//------------------------------------------------------------------------------
|
package/lib/linter/linter.js
CHANGED
@@ -41,6 +41,7 @@ const { startTime, endTime } = require("../shared/stats");
|
|
41
41
|
const { RuleValidator } = require("../config/rule-validator");
|
42
42
|
const { assertIsRuleSeverity } = require("../config/flat-config-schema");
|
43
43
|
const { normalizeSeverityToString } = require("../shared/severity");
|
44
|
+
const { deepMergeArrays } = require("../shared/deep-merge-arrays");
|
44
45
|
const jslang = require("../languages/js");
|
45
46
|
const { activeFlags, inactiveFlags } = require("../shared/flags");
|
46
47
|
const debug = require("debug")("eslint:linter");
|
@@ -892,14 +893,14 @@ function storeTime(time, timeOpts, slots) {
|
|
892
893
|
/**
|
893
894
|
* Get the options for a rule (not including severity), if any
|
894
895
|
* @param {RuleConfig} ruleConfig rule configuration
|
896
|
+
* @param {Object|undefined} defaultOptions rule.meta.defaultOptions
|
895
897
|
* @returns {Array} of rule options, empty Array if none
|
896
898
|
*/
|
897
|
-
function getRuleOptions(ruleConfig) {
|
899
|
+
function getRuleOptions(ruleConfig, defaultOptions) {
|
898
900
|
if (Array.isArray(ruleConfig)) {
|
899
|
-
return ruleConfig.slice(1);
|
901
|
+
return deepMergeArrays(defaultOptions, ruleConfig.slice(1));
|
900
902
|
}
|
901
|
-
return [];
|
902
|
-
|
903
|
+
return defaultOptions ?? [];
|
903
904
|
}
|
904
905
|
|
905
906
|
/**
|
@@ -957,6 +958,7 @@ function createRuleListeners(rule, ruleContext) {
|
|
957
958
|
* @param {LanguageOptions} languageOptions The options for parsing the code.
|
958
959
|
* @param {Object} settings The settings that were enabled in the config
|
959
960
|
* @param {string} filename The reported filename of the code
|
961
|
+
* @param {boolean} applyDefaultOptions If true, apply rules' meta.defaultOptions in computing their config options.
|
960
962
|
* @param {boolean} disableFixes If true, it doesn't make `fix` properties.
|
961
963
|
* @param {string | undefined} cwd cwd of the cli
|
962
964
|
* @param {string} physicalFilename The full path of the file on disk without any code block information
|
@@ -967,9 +969,21 @@ function createRuleListeners(rule, ruleContext) {
|
|
967
969
|
* @throws {Error} If traversal into a node fails.
|
968
970
|
*/
|
969
971
|
function runRules(
|
970
|
-
sourceCode,
|
971
|
-
|
972
|
-
|
972
|
+
sourceCode,
|
973
|
+
configuredRules,
|
974
|
+
ruleMapper,
|
975
|
+
parserName,
|
976
|
+
language,
|
977
|
+
languageOptions,
|
978
|
+
settings,
|
979
|
+
filename,
|
980
|
+
applyDefaultOptions,
|
981
|
+
disableFixes,
|
982
|
+
cwd,
|
983
|
+
physicalFilename,
|
984
|
+
ruleFilter,
|
985
|
+
stats,
|
986
|
+
slots
|
973
987
|
) {
|
974
988
|
const emitter = createEmitter();
|
975
989
|
|
@@ -1022,7 +1036,7 @@ function runRules(
|
|
1022
1036
|
Object.create(sharedTraversalContext),
|
1023
1037
|
{
|
1024
1038
|
id: ruleId,
|
1025
|
-
options: getRuleOptions(configuredRules[ruleId]),
|
1039
|
+
options: getRuleOptions(configuredRules[ruleId], applyDefaultOptions ? rule.meta?.defaultOptions : void 0),
|
1026
1040
|
report(...args) {
|
1027
1041
|
|
1028
1042
|
/*
|
@@ -1419,6 +1433,7 @@ class Linter {
|
|
1419
1433
|
languageOptions,
|
1420
1434
|
settings,
|
1421
1435
|
options.filename,
|
1436
|
+
true,
|
1422
1437
|
options.disableFixes,
|
1423
1438
|
slots.cwd,
|
1424
1439
|
providedOptions.physicalFilename,
|
@@ -1640,34 +1655,8 @@ class Linter {
|
|
1640
1655
|
|
1641
1656
|
const slots = internalSlotsMap.get(this);
|
1642
1657
|
const config = providedConfig || {};
|
1658
|
+
const { settings = {}, languageOptions } = config;
|
1643
1659
|
const options = normalizeVerifyOptions(providedOptions, config);
|
1644
|
-
const languageOptions = config.languageOptions;
|
1645
|
-
|
1646
|
-
if (config.language === jslang) {
|
1647
|
-
languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
|
1648
|
-
languageOptions.ecmaVersion
|
1649
|
-
);
|
1650
|
-
|
1651
|
-
// Espree expects this information to be passed in
|
1652
|
-
if (isEspree(languageOptions.parser)) {
|
1653
|
-
const parserOptions = languageOptions.parserOptions;
|
1654
|
-
|
1655
|
-
if (languageOptions.sourceType) {
|
1656
|
-
|
1657
|
-
parserOptions.sourceType = languageOptions.sourceType;
|
1658
|
-
|
1659
|
-
if (
|
1660
|
-
parserOptions.sourceType === "module" &&
|
1661
|
-
parserOptions.ecmaFeatures &&
|
1662
|
-
parserOptions.ecmaFeatures.globalReturn
|
1663
|
-
) {
|
1664
|
-
parserOptions.ecmaFeatures.globalReturn = false;
|
1665
|
-
}
|
1666
|
-
}
|
1667
|
-
}
|
1668
|
-
}
|
1669
|
-
|
1670
|
-
const settings = config.settings || {};
|
1671
1660
|
|
1672
1661
|
if (!slots.lastSourceCode) {
|
1673
1662
|
let t;
|
@@ -1848,6 +1837,17 @@ class Linter {
|
|
1848
1837
|
if (config.rules[ruleId][0] > 0) {
|
1849
1838
|
shouldValidateOptions = false;
|
1850
1839
|
}
|
1840
|
+
} else {
|
1841
|
+
|
1842
|
+
/**
|
1843
|
+
* Since we know the user provided options, apply defaults on top of them
|
1844
|
+
*/
|
1845
|
+
const slicedOptions = ruleOptions.slice(1);
|
1846
|
+
const mergedOptions = deepMergeArrays(rule.meta?.defaultOptions, slicedOptions);
|
1847
|
+
|
1848
|
+
if (mergedOptions.length) {
|
1849
|
+
ruleOptions = [ruleOptions[0], ...mergedOptions];
|
1850
|
+
}
|
1851
1851
|
}
|
1852
1852
|
|
1853
1853
|
if (shouldValidateOptions) {
|
@@ -1917,6 +1917,7 @@ class Linter {
|
|
1917
1917
|
languageOptions,
|
1918
1918
|
settings,
|
1919
1919
|
options.filename,
|
1920
|
+
false,
|
1920
1921
|
options.disableFixes,
|
1921
1922
|
slots.cwd,
|
1922
1923
|
providedOptions.physicalFilename,
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const assert = require("
|
12
|
+
const assert = require("../shared/assert");
|
13
13
|
const { RuleFixer } = require("./rule-fixer");
|
14
14
|
const { interpolate } = require("./interpolate");
|
15
15
|
|
@@ -653,7 +653,7 @@ class RuleTester {
|
|
653
653
|
};
|
654
654
|
|
655
655
|
if (item.filename) {
|
656
|
-
flatConfigArrayOptions.basePath = path.parse(item.filename).root;
|
656
|
+
flatConfigArrayOptions.basePath = path.parse(item.filename).root || void 0;
|
657
657
|
}
|
658
658
|
|
659
659
|
const configs = new FlatConfigArray(testerConfig, flatConfigArrayOptions);
|
@@ -139,6 +139,12 @@ module.exports = {
|
|
139
139
|
meta: {
|
140
140
|
type: "suggestion",
|
141
141
|
|
142
|
+
defaultOptions: [{
|
143
|
+
enforceForClassMembers: true,
|
144
|
+
getWithoutSet: false,
|
145
|
+
setWithoutGet: true
|
146
|
+
}],
|
147
|
+
|
142
148
|
docs: {
|
143
149
|
description: "Enforce getter and setter pairs in objects and classes",
|
144
150
|
recommended: false,
|
@@ -149,16 +155,13 @@ module.exports = {
|
|
149
155
|
type: "object",
|
150
156
|
properties: {
|
151
157
|
getWithoutSet: {
|
152
|
-
type: "boolean"
|
153
|
-
default: false
|
158
|
+
type: "boolean"
|
154
159
|
},
|
155
160
|
setWithoutGet: {
|
156
|
-
type: "boolean"
|
157
|
-
default: true
|
161
|
+
type: "boolean"
|
158
162
|
},
|
159
163
|
enforceForClassMembers: {
|
160
|
-
type: "boolean"
|
161
|
-
default: true
|
164
|
+
type: "boolean"
|
162
165
|
}
|
163
166
|
},
|
164
167
|
additionalProperties: false
|
@@ -174,7 +177,7 @@ module.exports = {
|
|
174
177
|
}
|
175
178
|
},
|
176
179
|
create(context) {
|
177
|
-
const config = context.options
|
180
|
+
const [config] = context.options;
|
178
181
|
const checkGetWithoutSet = config.getWithoutSet === true;
|
179
182
|
const checkSetWithoutGet = config.setWithoutGet !== false;
|
180
183
|
const enforceForClassMembers = config.enforceForClassMembers !== false;
|
@@ -215,6 +215,12 @@ module.exports = {
|
|
215
215
|
meta: {
|
216
216
|
type: "problem",
|
217
217
|
|
218
|
+
defaultOptions: [{
|
219
|
+
allowImplicit: false,
|
220
|
+
checkForEach: false,
|
221
|
+
allowVoid: false
|
222
|
+
}],
|
223
|
+
|
218
224
|
docs: {
|
219
225
|
description: "Enforce `return` statements in callbacks of array methods",
|
220
226
|
recommended: false,
|
@@ -229,16 +235,13 @@ module.exports = {
|
|
229
235
|
type: "object",
|
230
236
|
properties: {
|
231
237
|
allowImplicit: {
|
232
|
-
type: "boolean"
|
233
|
-
default: false
|
238
|
+
type: "boolean"
|
234
239
|
},
|
235
240
|
checkForEach: {
|
236
|
-
type: "boolean"
|
237
|
-
default: false
|
241
|
+
type: "boolean"
|
238
242
|
},
|
239
243
|
allowVoid: {
|
240
|
-
type: "boolean"
|
241
|
-
default: false
|
244
|
+
type: "boolean"
|
242
245
|
}
|
243
246
|
},
|
244
247
|
additionalProperties: false
|
@@ -256,8 +259,7 @@ module.exports = {
|
|
256
259
|
},
|
257
260
|
|
258
261
|
create(context) {
|
259
|
-
|
260
|
-
const options = context.options[0] || { allowImplicit: false, checkForEach: false, allowVoid: false };
|
262
|
+
const [options] = context.options;
|
261
263
|
const sourceCode = context.sourceCode;
|
262
264
|
|
263
265
|
let funcInfo = {
|
@@ -19,6 +19,8 @@ module.exports = {
|
|
19
19
|
meta: {
|
20
20
|
type: "suggestion",
|
21
21
|
|
22
|
+
defaultOptions: ["as-needed"],
|
23
|
+
|
22
24
|
docs: {
|
23
25
|
description: "Require braces around arrow function bodies",
|
24
26
|
recommended: false,
|
@@ -71,7 +73,7 @@ module.exports = {
|
|
71
73
|
create(context) {
|
72
74
|
const options = context.options;
|
73
75
|
const always = options[0] === "always";
|
74
|
-
const asNeeded =
|
76
|
+
const asNeeded = options[0] === "as-needed";
|
75
77
|
const never = options[0] === "never";
|
76
78
|
const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral;
|
77
79
|
const sourceCode = context.sourceCode;
|