eslint 9.0.0-beta.0 → 9.0.0-beta.2
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 +19 -7
- package/lib/config/rule-validator.js +15 -2
- package/lib/eslint/eslint.js +8 -1
- package/lib/linter/linter.js +121 -110
- package/lib/rules/complexity.js +13 -0
- package/lib/rules/no-constant-binary-expression.js +2 -3
- package/lib/rules/no-extend-native.js +1 -2
- package/lib/rules/no-misleading-character-class.js +110 -63
- package/lib/rules/no-restricted-imports.js +183 -47
- package/lib/rules/no-unused-vars.js +14 -1
- package/lib/rules/use-isnan.js +33 -4
- package/lib/rules/utils/ast-utils.js +9 -0
- package/lib/rules/utils/char-source.js +240 -0
- package/package.json +5 -5
package/README.md
CHANGED
@@ -103,7 +103,7 @@ We are now at or near 100% compatibility with JSCS. If you try ESLint and believ
|
|
103
103
|
|
104
104
|
### Does Prettier replace ESLint?
|
105
105
|
|
106
|
-
No, ESLint and Prettier have
|
106
|
+
No, ESLint and Prettier have different jobs: ESLint is a linter (looking for problematic patterns) and Prettier is a code formatter. Using both tools is common, refer to [Prettier's documentation](https://prettier.io/docs/en/install#eslint-and-other-linters) to learn how to configure them to work well with each other.
|
107
107
|
|
108
108
|
### Why can't ESLint find my plugins?
|
109
109
|
|
@@ -127,6 +127,18 @@ In other cases (including if rules need to warn on more or fewer cases due to ne
|
|
127
127
|
|
128
128
|
Once a language feature has been adopted into the ECMAScript standard (stage 4 according to the [TC39 process](https://tc39.github.io/process-document/)), we will accept issues and pull requests related to the new feature, subject to our [contributing guidelines](https://eslint.org/docs/latest/contribute). Until then, please use the appropriate parser and plugin(s) for your experimental feature.
|
129
129
|
|
130
|
+
### Which Node.js versions does ESLint support?
|
131
|
+
|
132
|
+
ESLint updates the supported Node.js versions with each major release of ESLint. At that time, ESLint's supported Node.js versions are updated to be:
|
133
|
+
|
134
|
+
1. The most recent maintenance release of Node.js
|
135
|
+
1. The lowest minor version of the Node.js LTS release that includes the features the ESLint team wants to use.
|
136
|
+
1. The Node.js Current release
|
137
|
+
|
138
|
+
ESLint is also expected to work with Node.js versions released after the Node.js Current release.
|
139
|
+
|
140
|
+
Refer to the [Quick Start Guide](https://eslint.org/docs/latest/use/getting-started#prerequisites) for the officially supported Node.js versions for a given ESLint release.
|
141
|
+
|
130
142
|
### Where to ask for help?
|
131
143
|
|
132
144
|
Open a [discussion](https://github.com/eslint/eslint/discussions) or stop by our [Discord server](https://eslint.org/chat).
|
@@ -213,6 +225,11 @@ The people who manage releases, review feature requests, and meet regularly to e
|
|
213
225
|
Nicholas C. Zakas
|
214
226
|
</a>
|
215
227
|
</td><td align="center" valign="top" width="11%">
|
228
|
+
<a href="https://github.com/fasttime">
|
229
|
+
<img src="https://github.com/fasttime.png?s=75" width="75" height="75" alt="Francesco Trotta's Avatar"><br />
|
230
|
+
Francesco Trotta
|
231
|
+
</a>
|
232
|
+
</td><td align="center" valign="top" width="11%">
|
216
233
|
<a href="https://github.com/mdjermanovic">
|
217
234
|
<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75" alt="Milos Djermanovic's Avatar"><br />
|
218
235
|
Milos Djermanovic
|
@@ -250,11 +267,6 @@ Bryan Mishkin
|
|
250
267
|
Josh Goldberg ✨
|
251
268
|
</a>
|
252
269
|
</td><td align="center" valign="top" width="11%">
|
253
|
-
<a href="https://github.com/fasttime">
|
254
|
-
<img src="https://github.com/fasttime.png?s=75" width="75" height="75" alt="Francesco Trotta's Avatar"><br />
|
255
|
-
Francesco Trotta
|
256
|
-
</a>
|
257
|
-
</td><td align="center" valign="top" width="11%">
|
258
270
|
<a href="https://github.com/Tanujkanti4441">
|
259
271
|
<img src="https://github.com/Tanujkanti4441.png?s=75" width="75" height="75" alt="Tanuj Kanti's Avatar"><br />
|
260
272
|
Tanuj Kanti
|
@@ -294,7 +306,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
294
306
|
<p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <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>
|
295
307
|
<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>
|
296
308
|
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/eb04ddc/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>
|
297
|
-
<p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" 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://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" 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>
|
309
|
+
<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://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" 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://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" 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>
|
298
310
|
<!--sponsorsend-->
|
299
311
|
|
300
312
|
## Technology Sponsors
|
@@ -167,9 +167,22 @@ class RuleValidator {
|
|
167
167
|
validateRule(ruleOptions.slice(1));
|
168
168
|
|
169
169
|
if (validateRule.errors) {
|
170
|
-
throw new Error(`Key "rules": Key "${ruleId}"
|
170
|
+
throw new Error(`Key "rules": Key "${ruleId}":\n${
|
171
171
|
validateRule.errors.map(
|
172
|
-
error =>
|
172
|
+
error => {
|
173
|
+
if (
|
174
|
+
error.keyword === "additionalProperties" &&
|
175
|
+
error.schema === false &&
|
176
|
+
typeof error.parentSchema?.properties === "object" &&
|
177
|
+
typeof error.params?.additionalProperty === "string"
|
178
|
+
) {
|
179
|
+
const expectedProperties = Object.keys(error.parentSchema.properties).map(property => `"${property}"`);
|
180
|
+
|
181
|
+
return `\tValue ${JSON.stringify(error.data)} ${error.message}.\n\t\tUnexpected property "${error.params.additionalProperty}". Expected properties: ${expectedProperties.join(", ")}.\n`;
|
182
|
+
}
|
183
|
+
|
184
|
+
return `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`;
|
185
|
+
}
|
173
186
|
).join("")
|
174
187
|
}`);
|
175
188
|
}
|
package/lib/eslint/eslint.js
CHANGED
@@ -838,6 +838,7 @@ class ESLint {
|
|
838
838
|
configs,
|
839
839
|
errorOnUnmatchedPattern
|
840
840
|
});
|
841
|
+
const controller = new AbortController();
|
841
842
|
|
842
843
|
debug(`${filePaths.length} files found in: ${Date.now() - startTime}ms`);
|
843
844
|
|
@@ -906,9 +907,12 @@ class ESLint {
|
|
906
907
|
fixer = message => shouldMessageBeFixed(message, config, fixTypesSet) && originalFix(message);
|
907
908
|
}
|
908
909
|
|
909
|
-
return fs.readFile(filePath, "utf8")
|
910
|
+
return fs.readFile(filePath, { encoding: "utf8", signal: controller.signal })
|
910
911
|
.then(text => {
|
911
912
|
|
913
|
+
// fail immediately if an error occurred in another file
|
914
|
+
controller.signal.throwIfAborted();
|
915
|
+
|
912
916
|
// do the linting
|
913
917
|
const result = verifyText({
|
914
918
|
text,
|
@@ -932,6 +936,9 @@ class ESLint {
|
|
932
936
|
}
|
933
937
|
|
934
938
|
return result;
|
939
|
+
}).catch(error => {
|
940
|
+
controller.abort(error);
|
941
|
+
throw error;
|
935
942
|
});
|
936
943
|
|
937
944
|
})
|
package/lib/linter/linter.js
CHANGED
@@ -43,7 +43,7 @@ const
|
|
43
43
|
const { getRuleFromConfig } = require("../config/flat-config-helpers");
|
44
44
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
45
45
|
const { RuleValidator } = require("../config/rule-validator");
|
46
|
-
const {
|
46
|
+
const { assertIsRuleSeverity } = require("../config/flat-config-schema");
|
47
47
|
const { normalizeSeverityToString } = require("../shared/severity");
|
48
48
|
const debug = require("debug")("eslint:linter");
|
49
49
|
const MAX_AUTOFIX_PASSES = 10;
|
@@ -326,10 +326,11 @@ function createDisableDirectives(options) {
|
|
326
326
|
* @param {SourceCode} sourceCode The SourceCode object to get comments from.
|
327
327
|
* @param {function(string): {create: Function}} ruleMapper A map from rule IDs to defined rules
|
328
328
|
* @param {string|null} warnInlineConfig If a string then it should warn directive comments as disabled. The string value is the config name what the setting came from.
|
329
|
+
* @param {ConfigData} config Provided config.
|
329
330
|
* @returns {{configuredRules: Object, enabledGlobals: {value:string,comment:Token}[], exportedVariables: Object, problems: LintMessage[], disableDirectives: DisableDirective[]}}
|
330
331
|
* A collection of the directive comments that were found, along with any problems that occurred when parsing
|
331
332
|
*/
|
332
|
-
function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
|
333
|
+
function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config) {
|
333
334
|
const configuredRules = {};
|
334
335
|
const enabledGlobals = Object.create(null);
|
335
336
|
const exportedVariables = {};
|
@@ -438,8 +439,58 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
|
|
438
439
|
return;
|
439
440
|
}
|
440
441
|
|
442
|
+
if (Object.hasOwn(configuredRules, name)) {
|
443
|
+
problems.push(createLintingProblem({
|
444
|
+
message: `Rule "${name}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
|
445
|
+
loc: comment.loc
|
446
|
+
}));
|
447
|
+
return;
|
448
|
+
}
|
449
|
+
|
450
|
+
let ruleOptions = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
|
451
|
+
|
452
|
+
/*
|
453
|
+
* If the rule was already configured, inline rule configuration that
|
454
|
+
* only has severity should retain options from the config and just override the severity.
|
455
|
+
*
|
456
|
+
* Example:
|
457
|
+
*
|
458
|
+
* {
|
459
|
+
* rules: {
|
460
|
+
* curly: ["error", "multi"]
|
461
|
+
* }
|
462
|
+
* }
|
463
|
+
*
|
464
|
+
* /* eslint curly: ["warn"] * /
|
465
|
+
*
|
466
|
+
* Results in:
|
467
|
+
*
|
468
|
+
* curly: ["warn", "multi"]
|
469
|
+
*/
|
470
|
+
if (
|
471
|
+
|
472
|
+
/*
|
473
|
+
* If inline config for the rule has only severity
|
474
|
+
*/
|
475
|
+
ruleOptions.length === 1 &&
|
476
|
+
|
477
|
+
/*
|
478
|
+
* And the rule was already configured
|
479
|
+
*/
|
480
|
+
config.rules && Object.hasOwn(config.rules, name)
|
481
|
+
) {
|
482
|
+
|
483
|
+
/*
|
484
|
+
* Then use severity from the inline config and options from the provided config
|
485
|
+
*/
|
486
|
+
ruleOptions = [
|
487
|
+
ruleOptions[0], // severity from the inline config
|
488
|
+
...Array.isArray(config.rules[name]) ? config.rules[name].slice(1) : [] // options from the provided config
|
489
|
+
];
|
490
|
+
}
|
491
|
+
|
441
492
|
try {
|
442
|
-
validator.validateRuleOptions(rule, name,
|
493
|
+
validator.validateRuleOptions(rule, name, ruleOptions);
|
443
494
|
} catch (err) {
|
444
495
|
|
445
496
|
/*
|
@@ -460,7 +511,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
|
|
460
511
|
return;
|
461
512
|
}
|
462
513
|
|
463
|
-
configuredRules[name] =
|
514
|
+
configuredRules[name] = ruleOptions;
|
464
515
|
});
|
465
516
|
} else {
|
466
517
|
problems.push(parseResult.error);
|
@@ -1322,7 +1373,7 @@ class Linter {
|
|
1322
1373
|
|
1323
1374
|
const sourceCode = slots.lastSourceCode;
|
1324
1375
|
const commentDirectives = options.allowInlineConfig
|
1325
|
-
? getDirectiveComments(sourceCode, ruleId => getRule(slots, ruleId), options.warnInlineConfig)
|
1376
|
+
? getDirectiveComments(sourceCode, ruleId => getRule(slots, ruleId), options.warnInlineConfig, config)
|
1326
1377
|
: { configuredRules: {}, enabledGlobals: {}, exportedVariables: {}, problems: [], disableDirectives: [] };
|
1327
1378
|
|
1328
1379
|
// augment global scope with declared global variables
|
@@ -1332,56 +1383,8 @@ class Linter {
|
|
1332
1383
|
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1333
1384
|
);
|
1334
1385
|
|
1335
|
-
/*
|
1336
|
-
* Now we determine the final configurations for rules.
|
1337
|
-
* First, let all inline rule configurations override those from the config.
|
1338
|
-
* Then, check for a special case: if a rule is configured in both places,
|
1339
|
-
* inline rule configuration that only has severity should retain options from
|
1340
|
-
* the config and just override the severity.
|
1341
|
-
*
|
1342
|
-
* Example:
|
1343
|
-
*
|
1344
|
-
* {
|
1345
|
-
* rules: {
|
1346
|
-
* curly: ["error", "multi"]
|
1347
|
-
* }
|
1348
|
-
* }
|
1349
|
-
*
|
1350
|
-
* /* eslint curly: ["warn"] * /
|
1351
|
-
*
|
1352
|
-
* Results in:
|
1353
|
-
*
|
1354
|
-
* curly: ["warn", "multi"]
|
1355
|
-
*/
|
1356
1386
|
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
1357
1387
|
|
1358
|
-
if (config.rules) {
|
1359
|
-
for (const [ruleId, ruleInlineConfig] of Object.entries(commentDirectives.configuredRules)) {
|
1360
|
-
if (
|
1361
|
-
|
1362
|
-
/*
|
1363
|
-
* If inline config for the rule has only severity
|
1364
|
-
*/
|
1365
|
-
(!Array.isArray(ruleInlineConfig) || ruleInlineConfig.length === 1) &&
|
1366
|
-
|
1367
|
-
/*
|
1368
|
-
* And provided config for the rule has options
|
1369
|
-
*/
|
1370
|
-
Object.hasOwn(config.rules, ruleId) &&
|
1371
|
-
(Array.isArray(config.rules[ruleId]) && config.rules[ruleId].length > 1)
|
1372
|
-
) {
|
1373
|
-
|
1374
|
-
/*
|
1375
|
-
* Then use severity from the inline config and options from the provided config
|
1376
|
-
*/
|
1377
|
-
configuredRules[ruleId] = [
|
1378
|
-
Array.isArray(ruleInlineConfig) ? ruleInlineConfig[0] : ruleInlineConfig, // severity from the inline config
|
1379
|
-
...config.rules[ruleId].slice(1) // options from the provided config
|
1380
|
-
];
|
1381
|
-
}
|
1382
|
-
}
|
1383
|
-
}
|
1384
|
-
|
1385
1388
|
let lintingProblems;
|
1386
1389
|
|
1387
1390
|
try {
|
@@ -1711,19 +1714,77 @@ class Linter {
|
|
1711
1714
|
return;
|
1712
1715
|
}
|
1713
1716
|
|
1717
|
+
if (Object.hasOwn(mergedInlineConfig.rules, ruleId)) {
|
1718
|
+
inlineConfigProblems.push(createLintingProblem({
|
1719
|
+
message: `Rule "${ruleId}" is already configured by another configuration comment in the preceding code. This configuration is ignored.`,
|
1720
|
+
loc: node.loc
|
1721
|
+
}));
|
1722
|
+
return;
|
1723
|
+
}
|
1724
|
+
|
1714
1725
|
try {
|
1715
1726
|
|
1716
|
-
|
1727
|
+
let ruleOptions = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
|
1717
1728
|
|
1718
|
-
assertIsRuleOptions(ruleId, ruleValue);
|
1719
1729
|
assertIsRuleSeverity(ruleId, ruleOptions[0]);
|
1720
1730
|
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1731
|
+
/*
|
1732
|
+
* If the rule was already configured, inline rule configuration that
|
1733
|
+
* only has severity should retain options from the config and just override the severity.
|
1734
|
+
*
|
1735
|
+
* Example:
|
1736
|
+
*
|
1737
|
+
* {
|
1738
|
+
* rules: {
|
1739
|
+
* curly: ["error", "multi"]
|
1740
|
+
* }
|
1741
|
+
* }
|
1742
|
+
*
|
1743
|
+
* /* eslint curly: ["warn"] * /
|
1744
|
+
*
|
1745
|
+
* Results in:
|
1746
|
+
*
|
1747
|
+
* curly: ["warn", "multi"]
|
1748
|
+
*/
|
1749
|
+
|
1750
|
+
let shouldValidateOptions = true;
|
1751
|
+
|
1752
|
+
if (
|
1753
|
+
|
1754
|
+
/*
|
1755
|
+
* If inline config for the rule has only severity
|
1756
|
+
*/
|
1757
|
+
ruleOptions.length === 1 &&
|
1758
|
+
|
1759
|
+
/*
|
1760
|
+
* And the rule was already configured
|
1761
|
+
*/
|
1762
|
+
config.rules && Object.hasOwn(config.rules, ruleId)
|
1763
|
+
) {
|
1764
|
+
|
1765
|
+
/*
|
1766
|
+
* Then use severity from the inline config and options from the provided config
|
1767
|
+
*/
|
1768
|
+
ruleOptions = [
|
1769
|
+
ruleOptions[0], // severity from the inline config
|
1770
|
+
...config.rules[ruleId].slice(1) // options from the provided config
|
1771
|
+
];
|
1772
|
+
|
1773
|
+
// if the rule was enabled, the options have already been validated
|
1774
|
+
if (config.rules[ruleId][0] > 0) {
|
1775
|
+
shouldValidateOptions = false;
|
1725
1776
|
}
|
1726
|
-
}
|
1777
|
+
}
|
1778
|
+
|
1779
|
+
if (shouldValidateOptions) {
|
1780
|
+
ruleValidator.validate({
|
1781
|
+
plugins: config.plugins,
|
1782
|
+
rules: {
|
1783
|
+
[ruleId]: ruleOptions
|
1784
|
+
}
|
1785
|
+
});
|
1786
|
+
}
|
1787
|
+
|
1727
1788
|
mergedInlineConfig.rules[ruleId] = ruleOptions;
|
1728
1789
|
} catch (err) {
|
1729
1790
|
|
@@ -1763,58 +1824,8 @@ class Linter {
|
|
1763
1824
|
)
|
1764
1825
|
: { problems: [], disableDirectives: [] };
|
1765
1826
|
|
1766
|
-
/*
|
1767
|
-
* Now we determine the final configurations for rules.
|
1768
|
-
* First, let all inline rule configurations override those from the config.
|
1769
|
-
* Then, check for a special case: if a rule is configured in both places,
|
1770
|
-
* inline rule configuration that only has severity should retain options from
|
1771
|
-
* the config and just override the severity.
|
1772
|
-
*
|
1773
|
-
* Example:
|
1774
|
-
*
|
1775
|
-
* {
|
1776
|
-
* rules: {
|
1777
|
-
* curly: ["error", "multi"]
|
1778
|
-
* }
|
1779
|
-
* }
|
1780
|
-
*
|
1781
|
-
* /* eslint curly: ["warn"] * /
|
1782
|
-
*
|
1783
|
-
* Results in:
|
1784
|
-
*
|
1785
|
-
* curly: ["warn", "multi"]
|
1786
|
-
*
|
1787
|
-
* At this point, all rule configurations are normalized to arrays.
|
1788
|
-
*/
|
1789
1827
|
const configuredRules = Object.assign({}, config.rules, mergedInlineConfig.rules);
|
1790
1828
|
|
1791
|
-
if (config.rules) {
|
1792
|
-
for (const [ruleId, ruleInlineConfig] of Object.entries(mergedInlineConfig.rules)) {
|
1793
|
-
if (
|
1794
|
-
|
1795
|
-
/*
|
1796
|
-
* If inline config for the rule has only severity
|
1797
|
-
*/
|
1798
|
-
ruleInlineConfig.length === 1 &&
|
1799
|
-
|
1800
|
-
/*
|
1801
|
-
* And provided config for the rule has options
|
1802
|
-
*/
|
1803
|
-
Object.hasOwn(config.rules, ruleId) &&
|
1804
|
-
config.rules[ruleId].length > 1
|
1805
|
-
) {
|
1806
|
-
|
1807
|
-
/*
|
1808
|
-
* Then use severity from the inline config and options from the provided config
|
1809
|
-
*/
|
1810
|
-
configuredRules[ruleId] = [
|
1811
|
-
ruleInlineConfig[0], // severity from the inline config
|
1812
|
-
...config.rules[ruleId].slice(1) // options from the provided config
|
1813
|
-
];
|
1814
|
-
}
|
1815
|
-
}
|
1816
|
-
}
|
1817
|
-
|
1818
1829
|
let lintingProblems;
|
1819
1830
|
|
1820
1831
|
sourceCode.finalize();
|
package/lib/rules/complexity.js
CHANGED
@@ -109,6 +109,7 @@ module.exports = {
|
|
109
109
|
IfStatement: increaseComplexity,
|
110
110
|
WhileStatement: increaseComplexity,
|
111
111
|
DoWhileStatement: increaseComplexity,
|
112
|
+
AssignmentPattern: increaseComplexity,
|
112
113
|
|
113
114
|
// Avoid `default`
|
114
115
|
"SwitchCase[test]": increaseComplexity,
|
@@ -120,6 +121,18 @@ module.exports = {
|
|
120
121
|
}
|
121
122
|
},
|
122
123
|
|
124
|
+
MemberExpression(node) {
|
125
|
+
if (node.optional === true) {
|
126
|
+
increaseComplexity();
|
127
|
+
}
|
128
|
+
},
|
129
|
+
|
130
|
+
CallExpression(node) {
|
131
|
+
if (node.optional === true) {
|
132
|
+
increaseComplexity();
|
133
|
+
}
|
134
|
+
},
|
135
|
+
|
123
136
|
onCodePathEnd(codePath, node) {
|
124
137
|
const complexity = complexities.pop();
|
125
138
|
|
@@ -5,8 +5,7 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
-
const
|
9
|
-
const { isNullLiteral, isConstant, isReferenceToGlobalVariable, isLogicalAssignmentOperator } = require("./utils/ast-utils");
|
8
|
+
const { isNullLiteral, isConstant, isReferenceToGlobalVariable, isLogicalAssignmentOperator, ECMASCRIPT_GLOBALS } = require("./utils/ast-utils");
|
10
9
|
|
11
10
|
const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|", "^", "&", "**", "<<", ">>", ">>>"]);
|
12
11
|
|
@@ -376,7 +375,7 @@ function isAlwaysNew(scope, node) {
|
|
376
375
|
* Catching these is especially useful for primitive constructors
|
377
376
|
* which return boxed values, a surprising gotcha' in JavaScript.
|
378
377
|
*/
|
379
|
-
return Object.hasOwn(
|
378
|
+
return Object.hasOwn(ECMASCRIPT_GLOBALS, node.callee.name) &&
|
380
379
|
isReferenceToGlobalVariable(scope, node.callee);
|
381
380
|
}
|
382
381
|
case "Literal":
|
@@ -10,7 +10,6 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const astUtils = require("./utils/ast-utils");
|
13
|
-
const globals = require("globals");
|
14
13
|
|
15
14
|
//------------------------------------------------------------------------------
|
16
15
|
// Rule Definition
|
@@ -54,7 +53,7 @@ module.exports = {
|
|
54
53
|
const sourceCode = context.sourceCode;
|
55
54
|
const exceptions = new Set(config.exceptions || []);
|
56
55
|
const modifiedBuiltins = new Set(
|
57
|
-
Object.keys(
|
56
|
+
Object.keys(astUtils.ECMASCRIPT_GLOBALS)
|
58
57
|
.filter(builtin => builtin[0].toUpperCase() === builtin[0])
|
59
58
|
.filter(builtin => !exceptions.has(builtin))
|
60
59
|
);
|