eslint 8.15.0 → 8.18.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 -7
- package/bin/eslint.js +1 -1
- package/lib/cli-engine/cli-engine.js +2 -4
- package/lib/cli-engine/lint-result-cache.js +1 -1
- package/lib/eslint/eslint.js +3 -3
- package/lib/linter/code-path-analysis/code-path-segment.js +1 -1
- package/lib/linter/code-path-analysis/code-path-state.js +1 -1
- package/lib/linter/code-path-analysis/code-path.js +1 -1
- package/lib/linter/linter.js +1 -1
- package/lib/linter/timing.js +2 -1
- package/lib/rules/accessor-pairs.js +4 -4
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/capitalized-comments.js +1 -1
- package/lib/rules/consistent-this.js +1 -1
- package/lib/rules/dot-notation.js +2 -2
- package/lib/rules/function-paren-newline.js +8 -5
- package/lib/rules/global-require.js +3 -3
- package/lib/rules/indent-legacy.js +2 -2
- package/lib/rules/indent.js +45 -13
- package/lib/rules/jsx-quotes.js +1 -1
- package/lib/rules/lines-around-comment.js +3 -3
- package/lib/rules/max-lines.js +2 -2
- package/lib/rules/max-statements.js +1 -1
- package/lib/rules/newline-before-return.js +1 -1
- package/lib/rules/no-bitwise.js +2 -2
- package/lib/rules/no-console.js +1 -1
- package/lib/rules/no-constant-binary-expression.js +3 -3
- package/lib/rules/no-control-regex.js +23 -10
- package/lib/rules/no-empty-function.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +3 -3
- package/lib/rules/no-extra-semi.js +1 -1
- package/lib/rules/no-global-assign.js +1 -1
- package/lib/rules/no-implicit-coercion.js +8 -8
- package/lib/rules/no-loop-func.js +1 -1
- package/lib/rules/no-magic-numbers.js +3 -3
- package/lib/rules/no-misleading-character-class.js +90 -17
- package/lib/rules/no-mixed-operators.js +1 -1
- package/lib/rules/no-mixed-requires.js +1 -1
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-native-reassign.js +1 -1
- package/lib/rules/no-new-object.js +1 -1
- package/lib/rules/no-new-wrappers.js +1 -1
- package/lib/rules/no-octal.js +2 -2
- package/lib/rules/no-prototype-builtins.js +3 -3
- package/lib/rules/no-shadow.js +5 -5
- package/lib/rules/no-sparse-arrays.js +1 -1
- package/lib/rules/no-underscore-dangle.js +1 -1
- package/lib/rules/no-unused-expressions.js +1 -1
- package/lib/rules/no-unused-vars.js +5 -5
- package/lib/rules/no-use-before-define.js +15 -2
- package/lib/rules/operator-assignment.js +2 -2
- package/lib/rules/prefer-const.js +1 -1
- package/lib/rules/prefer-reflect.js +2 -2
- package/lib/rules/prefer-regex-literals.js +3 -3
- package/lib/rules/quote-props.js +2 -2
- package/lib/rules/quotes.js +1 -1
- package/lib/rules/spaced-comment.js +1 -1
- package/lib/rules/valid-jsdoc.js +1 -1
- package/lib/rules/valid-typeof.js +4 -4
- package/lib/rules/yoda.js +1 -1
- package/lib/shared/deprecation-warnings.js +1 -8
- package/lib/shared/types.js +1 -1
- package/package.json +23 -6
package/README.md
CHANGED
@@ -261,11 +261,6 @@ Brett Zamir
|
|
261
261
|
Bryan Mishkin
|
262
262
|
</a>
|
263
263
|
</td><td align="center" valign="top" width="11%">
|
264
|
-
<a href="https://github.com/mysticatea">
|
265
|
-
<img src="https://github.com/mysticatea.png?s=75" width="75" height="75"><br />
|
266
|
-
Toru Nagashima
|
267
|
-
</a>
|
268
|
-
</td><td align="center" valign="top" width="11%">
|
269
264
|
<a href="https://github.com/SaraSoueidan">
|
270
265
|
<img src="https://github.com/SaraSoueidan.png?s=75" width="75" height="75"><br />
|
271
266
|
Sara Soueidan
|
@@ -297,9 +292,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
297
292
|
<!--sponsorsstart-->
|
298
293
|
<h3>Platinum Sponsors</h3>
|
299
294
|
<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>
|
300
|
-
<p><a href="https://
|
295
|
+
<p><a href="https://www.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> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a></p><h3>Silver Sponsors</h3>
|
301
296
|
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
|
302
|
-
<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" 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://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" 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://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a></p>
|
297
|
+
<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" 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://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" 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://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" 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://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p>
|
303
298
|
<!--sponsorsend-->
|
304
299
|
|
305
300
|
## <a name="technology-sponsors"></a>Technology Sponsors
|
package/bin/eslint.js
CHANGED
@@ -69,7 +69,7 @@ function getErrorMessage(error) {
|
|
69
69
|
// Lazy loading because this is used only if an error happened.
|
70
70
|
const util = require("util");
|
71
71
|
|
72
|
-
// Foolproof --
|
72
|
+
// Foolproof -- third-party module might throw non-object.
|
73
73
|
if (typeof error !== "object" || error === null) {
|
74
74
|
return String(error);
|
75
75
|
}
|
@@ -366,9 +366,7 @@ function *iterateRuleDeprecationWarnings(usedConfigArrays) {
|
|
366
366
|
|
367
367
|
// Flatten used configs.
|
368
368
|
/** @type {ExtractedConfig[]} */
|
369
|
-
const configs =
|
370
|
-
...usedConfigArrays.map(getUsedExtractedConfigs)
|
371
|
-
);
|
369
|
+
const configs = usedConfigArrays.flatMap(getUsedExtractedConfigs);
|
372
370
|
|
373
371
|
// Traverse rule configs.
|
374
372
|
for (const config of configs) {
|
@@ -1023,7 +1021,7 @@ class CLIEngine {
|
|
1023
1021
|
let formatterPath;
|
1024
1022
|
|
1025
1023
|
// if there's a slash, then it's a file (TODO: this check seems dubious for scoped npm packages)
|
1026
|
-
if (!namespace && normalizedFormatName.
|
1024
|
+
if (!namespace && normalizedFormatName.includes("/")) {
|
1027
1025
|
formatterPath = path.resolve(cwd, normalizedFormatName);
|
1028
1026
|
} else {
|
1029
1027
|
try {
|
@@ -36,7 +36,7 @@ const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${valid
|
|
36
36
|
*/
|
37
37
|
function isValidCacheStrategy(cacheStrategy) {
|
38
38
|
return (
|
39
|
-
validCacheStrategies.
|
39
|
+
validCacheStrategies.includes(cacheStrategy)
|
40
40
|
);
|
41
41
|
}
|
42
42
|
|
package/lib/eslint/eslint.js
CHANGED
@@ -104,9 +104,9 @@ function isNonEmptyString(x) {
|
|
104
104
|
}
|
105
105
|
|
106
106
|
/**
|
107
|
-
* Check if a given value is an array of non-empty
|
107
|
+
* Check if a given value is an array of non-empty strings or not.
|
108
108
|
* @param {any} x The value to check.
|
109
|
-
* @returns {boolean} `true` if `x` is an array of non-empty
|
109
|
+
* @returns {boolean} `true` if `x` is an array of non-empty strings.
|
110
110
|
*/
|
111
111
|
function isArrayOfNonEmptyString(x) {
|
112
112
|
return Array.isArray(x) && x.every(isNonEmptyString);
|
@@ -599,7 +599,7 @@ class ESLint {
|
|
599
599
|
* The following values are allowed:
|
600
600
|
* - `undefined` ... Load `stylish` builtin formatter.
|
601
601
|
* - A builtin formatter name ... Load the builtin formatter.
|
602
|
-
* - A
|
602
|
+
* - A third-party formatter name:
|
603
603
|
* - `foo` → `eslint-formatter-foo`
|
604
604
|
* - `@foo` → `@foo/eslint-formatter`
|
605
605
|
* - `@foo/bar` → `@foo/eslint-formatter-bar`
|
@@ -100,7 +100,7 @@ class CodePathSegment {
|
|
100
100
|
* @returns {boolean} `true` if the segment is coming from the end of a loop.
|
101
101
|
*/
|
102
102
|
isLoopedPrevSegment(segment) {
|
103
|
-
return this.internal.loopedPrevSegments.
|
103
|
+
return this.internal.loopedPrevSegments.includes(segment);
|
104
104
|
}
|
105
105
|
|
106
106
|
/**
|
@@ -212,7 +212,7 @@ class CodePath {
|
|
212
212
|
}
|
213
213
|
|
214
214
|
// Reset the flag of skipping if all branches have been skipped.
|
215
|
-
if (skippedSegment && segment.prevSegments.
|
215
|
+
if (skippedSegment && segment.prevSegments.includes(skippedSegment)) {
|
216
216
|
skippedSegment = null;
|
217
217
|
}
|
218
218
|
visited[segment.id] = true;
|
package/lib/linter/linter.js
CHANGED
@@ -1101,7 +1101,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
|
|
1101
1101
|
)
|
1102
1102
|
);
|
1103
1103
|
|
1104
|
-
const ruleListeners = createRuleListeners(rule, ruleContext);
|
1104
|
+
const ruleListeners = timing.enabled ? timing.time(ruleId, createRuleListeners)(rule, ruleContext) : createRuleListeners(rule, ruleContext);
|
1105
1105
|
|
1106
1106
|
/**
|
1107
1107
|
* Include `ruleId` in error logs
|
package/lib/linter/timing.js
CHANGED
@@ -138,10 +138,11 @@ module.exports = (function() {
|
|
138
138
|
|
139
139
|
return function(...args) {
|
140
140
|
let t = process.hrtime();
|
141
|
+
const result = fn(...args);
|
141
142
|
|
142
|
-
fn(...args);
|
143
143
|
t = process.hrtime(t);
|
144
144
|
data[key] += t[0] * 1e3 + t[1] / 1e6;
|
145
|
+
return result;
|
145
146
|
};
|
146
147
|
}
|
147
148
|
|
@@ -299,12 +299,12 @@ module.exports = {
|
|
299
299
|
* @private
|
300
300
|
*/
|
301
301
|
function checkPropertyDescriptor(node) {
|
302
|
-
const namesToCheck = node.properties
|
302
|
+
const namesToCheck = new Set(node.properties
|
303
303
|
.filter(p => p.type === "Property" && p.kind === "init" && !p.computed)
|
304
|
-
.map(({ key }) => key.name);
|
304
|
+
.map(({ key }) => key.name));
|
305
305
|
|
306
|
-
const hasGetter = namesToCheck.
|
307
|
-
const hasSetter = namesToCheck.
|
306
|
+
const hasGetter = namesToCheck.has("get");
|
307
|
+
const hasSetter = namesToCheck.has("set");
|
308
308
|
|
309
309
|
if (checkSetWithoutGet && hasSetter && !hasGetter) {
|
310
310
|
report(node, "missingGetter");
|
@@ -53,7 +53,7 @@ module.exports = {
|
|
53
53
|
if (!node.parent) {
|
54
54
|
return null;
|
55
55
|
}
|
56
|
-
if (types.
|
56
|
+
if (!types.includes(node.parent.type)) {
|
57
57
|
return findClosestParentOfType(node.parent, types);
|
58
58
|
}
|
59
59
|
return node.parent;
|
@@ -87,7 +87,7 @@ module.exports = {
|
|
87
87
|
* @returns {boolean} Whether or not this function matches our callback name.
|
88
88
|
*/
|
89
89
|
function isCallback(node) {
|
90
|
-
return containsOnlyIdentifiers(node.callee) && callbacks.
|
90
|
+
return containsOnlyIdentifiers(node.callee) && callbacks.includes(sourceCode.getText(node.callee));
|
91
91
|
}
|
92
92
|
|
93
93
|
/**
|
@@ -65,7 +65,7 @@ module.exports = {
|
|
65
65
|
function checkAssignment(node, name, value) {
|
66
66
|
const isThis = value.type === "ThisExpression";
|
67
67
|
|
68
|
-
if (aliases.
|
68
|
+
if (aliases.includes(name)) {
|
69
69
|
if (!isThis || node.operator && node.operator !== "=") {
|
70
70
|
reportBadAssignment(node, name);
|
71
71
|
}
|
@@ -76,7 +76,7 @@ module.exports = {
|
|
76
76
|
function checkComputedProperty(node, value) {
|
77
77
|
if (
|
78
78
|
validIdentifier.test(value) &&
|
79
|
-
(allowKeywords || keywords.
|
79
|
+
(allowKeywords || !keywords.includes(String(value))) &&
|
80
80
|
!(allowPattern && allowPattern.test(value))
|
81
81
|
) {
|
82
82
|
const formattedValue = node.property.type === "Literal" ? JSON.stringify(value) : `\`${value}\``;
|
@@ -142,7 +142,7 @@ module.exports = {
|
|
142
142
|
!allowKeywords &&
|
143
143
|
!node.computed &&
|
144
144
|
node.property.type === "Identifier" &&
|
145
|
-
keywords.
|
145
|
+
keywords.includes(String(node.property.name))
|
146
146
|
) {
|
147
147
|
context.report({
|
148
148
|
node: node.property,
|
@@ -183,7 +183,7 @@ module.exports = {
|
|
183
183
|
/**
|
184
184
|
* Gets the left paren and right paren tokens of a node.
|
185
185
|
* @param {ASTNode} node The node with parens
|
186
|
-
* @throws {TypeError}
|
186
|
+
* @throws {TypeError} Unexpected node type.
|
187
187
|
* @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token.
|
188
188
|
* Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression
|
189
189
|
* with a single parameter)
|
@@ -191,10 +191,13 @@ module.exports = {
|
|
191
191
|
function getParenTokens(node) {
|
192
192
|
switch (node.type) {
|
193
193
|
case "NewExpression":
|
194
|
-
if (!node.arguments.length &&
|
195
|
-
|
196
|
-
|
197
|
-
|
194
|
+
if (!node.arguments.length &&
|
195
|
+
!(
|
196
|
+
astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) &&
|
197
|
+
astUtils.isClosingParenToken(sourceCode.getLastToken(node)) &&
|
198
|
+
node.callee.range[1] < node.range[1]
|
199
|
+
)
|
200
|
+
) {
|
198
201
|
|
199
202
|
// If the NewExpression does not have parens (e.g. `new Foo`), return null.
|
200
203
|
return null;
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
-
const ACCEPTABLE_PARENTS = [
|
9
|
+
const ACCEPTABLE_PARENTS = new Set([
|
10
10
|
"AssignmentExpression",
|
11
11
|
"VariableDeclarator",
|
12
12
|
"MemberExpression",
|
@@ -16,7 +16,7 @@ const ACCEPTABLE_PARENTS = [
|
|
16
16
|
"Program",
|
17
17
|
"VariableDeclaration",
|
18
18
|
"ChainExpression"
|
19
|
-
];
|
19
|
+
]);
|
20
20
|
|
21
21
|
/**
|
22
22
|
* Finds the eslint-scope reference in the given scope.
|
@@ -75,7 +75,7 @@ module.exports = {
|
|
75
75
|
const currentScope = context.getScope();
|
76
76
|
|
77
77
|
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
|
78
|
-
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.
|
78
|
+
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.has(parent.type));
|
79
79
|
|
80
80
|
if (!isGoodRequire) {
|
81
81
|
context.report({ node, messageId: "unexpected" });
|
@@ -753,7 +753,7 @@ module.exports = {
|
|
753
753
|
if (typeof options.CallExpression.arguments === "number") {
|
754
754
|
nodeIndent += options.CallExpression.arguments * indentSize;
|
755
755
|
} else if (options.CallExpression.arguments === "first") {
|
756
|
-
if (parent.arguments.
|
756
|
+
if (parent.arguments.includes(node)) {
|
757
757
|
nodeIndent = parent.arguments[0].loc.start.column;
|
758
758
|
}
|
759
759
|
} else {
|
@@ -840,7 +840,7 @@ module.exports = {
|
|
840
840
|
"IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration", "TryStatement"
|
841
841
|
];
|
842
842
|
|
843
|
-
if (node.parent && statementsWithProperties.
|
843
|
+
if (node.parent && statementsWithProperties.includes(node.parent.type) && isNodeBodyBlock(node)) {
|
844
844
|
indent = getNodeIndent(node.parent).goodChar;
|
845
845
|
} else if (node.parent && node.parent.type === "CatchClause") {
|
846
846
|
indent = getNodeIndent(node.parent.parent).goodChar;
|
package/lib/rules/indent.js
CHANGED
@@ -796,7 +796,7 @@ module.exports = {
|
|
796
796
|
let statement = node.parent && node.parent.parent;
|
797
797
|
|
798
798
|
while (
|
799
|
-
statement.type === "UnaryExpression" && ["!", "~", "+", "-"].
|
799
|
+
statement.type === "UnaryExpression" && ["!", "~", "+", "-"].includes(statement.operator) ||
|
800
800
|
statement.type === "AssignmentExpression" ||
|
801
801
|
statement.type === "LogicalExpression" ||
|
802
802
|
statement.type === "SequenceExpression" ||
|
@@ -916,18 +916,6 @@ module.exports = {
|
|
916
916
|
}
|
917
917
|
|
918
918
|
offsets.setDesiredOffsets([firstBodyToken.range[0], lastBodyToken.range[1]], lastParentToken, 1);
|
919
|
-
|
920
|
-
/*
|
921
|
-
* For blockless nodes with semicolon-first style, don't indent the semicolon.
|
922
|
-
* e.g.
|
923
|
-
* if (foo) bar()
|
924
|
-
* ; [1, 2, 3].map(foo)
|
925
|
-
*/
|
926
|
-
const lastToken = sourceCode.getLastToken(node);
|
927
|
-
|
928
|
-
if (node.type !== "EmptyStatement" && astUtils.isSemicolonToken(lastToken)) {
|
929
|
-
offsets.setDesiredOffset(lastToken, lastParentToken, 0);
|
930
|
-
}
|
931
919
|
}
|
932
920
|
}
|
933
921
|
|
@@ -1271,6 +1259,50 @@ module.exports = {
|
|
1271
1259
|
}
|
1272
1260
|
},
|
1273
1261
|
|
1262
|
+
/*
|
1263
|
+
* For blockless nodes with semicolon-first style, don't indent the semicolon.
|
1264
|
+
* e.g.
|
1265
|
+
* if (foo)
|
1266
|
+
* bar()
|
1267
|
+
* ; [1, 2, 3].map(foo)
|
1268
|
+
*
|
1269
|
+
* Traversal into the node sets indentation of the semicolon, so we need to override it on exit.
|
1270
|
+
*/
|
1271
|
+
":matches(DoWhileStatement, ForStatement, ForInStatement, ForOfStatement, IfStatement, WhileStatement):exit"(node) {
|
1272
|
+
let nodesToCheck;
|
1273
|
+
|
1274
|
+
if (node.type === "IfStatement") {
|
1275
|
+
nodesToCheck = [node.consequent];
|
1276
|
+
if (node.alternate) {
|
1277
|
+
nodesToCheck.push(node.alternate);
|
1278
|
+
}
|
1279
|
+
} else {
|
1280
|
+
nodesToCheck = [node.body];
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
for (const nodeToCheck of nodesToCheck) {
|
1284
|
+
const lastToken = sourceCode.getLastToken(nodeToCheck);
|
1285
|
+
|
1286
|
+
if (astUtils.isSemicolonToken(lastToken)) {
|
1287
|
+
const tokenBeforeLast = sourceCode.getTokenBefore(lastToken);
|
1288
|
+
const tokenAfterLast = sourceCode.getTokenAfter(lastToken);
|
1289
|
+
|
1290
|
+
// override indentation of `;` only if its line looks like a semicolon-first style line
|
1291
|
+
if (
|
1292
|
+
!astUtils.isTokenOnSameLine(tokenBeforeLast, lastToken) &&
|
1293
|
+
tokenAfterLast &&
|
1294
|
+
astUtils.isTokenOnSameLine(lastToken, tokenAfterLast)
|
1295
|
+
) {
|
1296
|
+
offsets.setDesiredOffset(
|
1297
|
+
lastToken,
|
1298
|
+
sourceCode.getFirstToken(node),
|
1299
|
+
0
|
1300
|
+
);
|
1301
|
+
}
|
1302
|
+
}
|
1303
|
+
}
|
1304
|
+
},
|
1305
|
+
|
1274
1306
|
ImportDeclaration(node) {
|
1275
1307
|
if (node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) {
|
1276
1308
|
const openingCurly = sourceCode.getFirstToken(node, astUtils.isOpeningBraceToken);
|
package/lib/rules/jsx-quotes.js
CHANGED
@@ -70,7 +70,7 @@ module.exports = {
|
|
70
70
|
* @public
|
71
71
|
*/
|
72
72
|
function usesExpectedQuotes(node) {
|
73
|
-
return node.value.
|
73
|
+
return node.value.includes(setting.quote) || astUtils.isSurroundedBy(node.raw, setting.quote);
|
74
74
|
}
|
75
75
|
|
76
76
|
return {
|
@@ -141,7 +141,7 @@ module.exports = {
|
|
141
141
|
comments = sourceCode.getAllComments(),
|
142
142
|
commentLines = getCommentLineNums(comments),
|
143
143
|
emptyLines = getEmptyLineNums(lines),
|
144
|
-
commentAndEmptyLines = commentLines.concat(emptyLines);
|
144
|
+
commentAndEmptyLines = new Set(commentLines.concat(emptyLines));
|
145
145
|
|
146
146
|
/**
|
147
147
|
* Returns whether or not comments are on lines starting with or ending with code
|
@@ -393,7 +393,7 @@ module.exports = {
|
|
393
393
|
const nextTokenOrComment = sourceCode.getTokenAfter(token, { includeComments: true });
|
394
394
|
|
395
395
|
// check for newline before
|
396
|
-
if (!exceptionStartAllowed && before && !commentAndEmptyLines.
|
396
|
+
if (!exceptionStartAllowed && before && !commentAndEmptyLines.has(prevLineNum) &&
|
397
397
|
!(astUtils.isCommentToken(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, token))) {
|
398
398
|
const lineStart = token.range[0] - token.loc.start.column;
|
399
399
|
const range = [lineStart, lineStart];
|
@@ -408,7 +408,7 @@ module.exports = {
|
|
408
408
|
}
|
409
409
|
|
410
410
|
// check for newline after
|
411
|
-
if (!exceptionEndAllowed && after && !commentAndEmptyLines.
|
411
|
+
if (!exceptionEndAllowed && after && !commentAndEmptyLines.has(nextLineNum) &&
|
412
412
|
!(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
|
413
413
|
context.report({
|
414
414
|
node: token,
|
package/lib/rules/max-lines.js
CHANGED
@@ -159,10 +159,10 @@ module.exports = {
|
|
159
159
|
if (skipComments) {
|
160
160
|
const comments = sourceCode.getAllComments();
|
161
161
|
|
162
|
-
const commentLines = comments.flatMap(getLinesWithoutCode);
|
162
|
+
const commentLines = new Set(comments.flatMap(getLinesWithoutCode));
|
163
163
|
|
164
164
|
lines = lines.filter(
|
165
|
-
l => !commentLines.
|
165
|
+
l => !commentLines.has(l.lineNumber)
|
166
166
|
);
|
167
167
|
}
|
168
168
|
|
@@ -126,7 +126,7 @@ module.exports = {
|
|
126
126
|
|
127
127
|
/*
|
128
128
|
* This rule does not apply to class static blocks, but we have to track them so
|
129
|
-
* that
|
129
|
+
* that statements in them do not count as statements in the enclosing function.
|
130
130
|
*/
|
131
131
|
if (node.type === "StaticBlock") {
|
132
132
|
return;
|
package/lib/rules/no-bitwise.js
CHANGED
@@ -76,7 +76,7 @@ module.exports = {
|
|
76
76
|
* @returns {boolean} Whether or not the node has a bitwise operator.
|
77
77
|
*/
|
78
78
|
function hasBitwiseOperator(node) {
|
79
|
-
return BITWISE_OPERATORS.
|
79
|
+
return BITWISE_OPERATORS.includes(node.operator);
|
80
80
|
}
|
81
81
|
|
82
82
|
/**
|
@@ -85,7 +85,7 @@ module.exports = {
|
|
85
85
|
* @returns {boolean} Whether or not the node has a bitwise operator.
|
86
86
|
*/
|
87
87
|
function allowedOperator(node) {
|
88
|
-
return allowed.
|
88
|
+
return allowed.includes(node.operator);
|
89
89
|
}
|
90
90
|
|
91
91
|
/**
|
package/lib/rules/no-console.js
CHANGED
@@ -120,7 +120,7 @@ function isStaticBoolean(scope, node) {
|
|
120
120
|
|
121
121
|
/**
|
122
122
|
* Test if an AST node will always give the same result when compared to a
|
123
|
-
*
|
123
|
+
* boolean value. Note that comparison to boolean values is different than
|
124
124
|
* truthiness.
|
125
125
|
* https://262.ecma-international.org/5.1/#sec-11.9.3
|
126
126
|
*
|
@@ -238,7 +238,7 @@ function hasConstantLooseBooleanComparison(scope, node) {
|
|
238
238
|
|
239
239
|
/**
|
240
240
|
* Test if an AST node will always give the same result when _strictly_ compared
|
241
|
-
* to a
|
241
|
+
* to a boolean value. This can happen if the expression can never be boolean, or
|
242
242
|
* if it is always the same boolean value.
|
243
243
|
* @param {Scope} scope The scope in which the node was found.
|
244
244
|
* @param {ASTNode} node The node to test
|
@@ -488,7 +488,7 @@ module.exports = {
|
|
488
488
|
}
|
489
489
|
|
490
490
|
/*
|
491
|
-
* In theory we could handle short
|
491
|
+
* In theory we could handle short-circuiting assignment operators,
|
492
492
|
* for some constant values, but that would require walking the
|
493
493
|
* scope to find the value of the variable being assigned. This is
|
494
494
|
* dependant on https://github.com/eslint/eslint/issues/13776
|
@@ -30,10 +30,12 @@ const collector = new (class {
|
|
30
30
|
}
|
31
31
|
}
|
32
32
|
|
33
|
-
collectControlChars(regexpStr) {
|
33
|
+
collectControlChars(regexpStr, flags) {
|
34
|
+
const uFlag = typeof flags === "string" && flags.includes("u");
|
35
|
+
|
34
36
|
try {
|
35
37
|
this._source = regexpStr;
|
36
|
-
this._validator.validatePattern(regexpStr); // Call onCharacter hook
|
38
|
+
this._validator.validatePattern(regexpStr, void 0, void 0, uFlag); // Call onCharacter hook
|
37
39
|
} catch {
|
38
40
|
|
39
41
|
// Ignore syntax errors in RegExp.
|
@@ -68,13 +70,15 @@ module.exports = {
|
|
68
70
|
|
69
71
|
/**
|
70
72
|
* Get the regex expression
|
71
|
-
* @param {ASTNode} node node to evaluate
|
72
|
-
* @returns {
|
73
|
+
* @param {ASTNode} node `Literal` node to evaluate
|
74
|
+
* @returns {{ pattern: string, flags: string | null } | null} Regex if found (the given node is either a regex literal
|
75
|
+
* or a string literal that is the pattern argument of a RegExp constructor call). Otherwise `null`. If flags cannot be determined,
|
76
|
+
* the `flags` property will be `null`.
|
73
77
|
* @private
|
74
78
|
*/
|
75
|
-
function
|
79
|
+
function getRegExp(node) {
|
76
80
|
if (node.regex) {
|
77
|
-
return node.regex
|
81
|
+
return node.regex;
|
78
82
|
}
|
79
83
|
if (typeof node.value === "string" &&
|
80
84
|
(node.parent.type === "NewExpression" || node.parent.type === "CallExpression") &&
|
@@ -82,7 +86,15 @@ module.exports = {
|
|
82
86
|
node.parent.callee.name === "RegExp" &&
|
83
87
|
node.parent.arguments[0] === node
|
84
88
|
) {
|
85
|
-
|
89
|
+
const pattern = node.value;
|
90
|
+
const flags =
|
91
|
+
node.parent.arguments.length > 1 &&
|
92
|
+
node.parent.arguments[1].type === "Literal" &&
|
93
|
+
typeof node.parent.arguments[1].value === "string"
|
94
|
+
? node.parent.arguments[1].value
|
95
|
+
: null;
|
96
|
+
|
97
|
+
return { pattern, flags };
|
86
98
|
}
|
87
99
|
|
88
100
|
return null;
|
@@ -90,10 +102,11 @@ module.exports = {
|
|
90
102
|
|
91
103
|
return {
|
92
104
|
Literal(node) {
|
93
|
-
const
|
105
|
+
const regExp = getRegExp(node);
|
94
106
|
|
95
|
-
if (
|
96
|
-
const
|
107
|
+
if (regExp) {
|
108
|
+
const { pattern, flags } = regExp;
|
109
|
+
const controlCharacters = collector.collectControlChars(pattern, flags);
|
97
110
|
|
98
111
|
if (controlCharacters.length > 0) {
|
99
112
|
context.report({
|
@@ -51,13 +51,13 @@ module.exports = {
|
|
51
51
|
const sourceCode = context.getSourceCode();
|
52
52
|
|
53
53
|
// Node types which have a test which will coerce values to booleans.
|
54
|
-
const BOOLEAN_NODE_TYPES = [
|
54
|
+
const BOOLEAN_NODE_TYPES = new Set([
|
55
55
|
"IfStatement",
|
56
56
|
"DoWhileStatement",
|
57
57
|
"WhileStatement",
|
58
58
|
"ConditionalExpression",
|
59
59
|
"ForStatement"
|
60
|
-
];
|
60
|
+
]);
|
61
61
|
|
62
62
|
/**
|
63
63
|
* Check if a node is a Boolean function or constructor.
|
@@ -95,7 +95,7 @@ module.exports = {
|
|
95
95
|
(isBooleanFunctionOrConstructorCall(node.parent) &&
|
96
96
|
node === node.parent.arguments[0]) ||
|
97
97
|
|
98
|
-
(BOOLEAN_NODE_TYPES.
|
98
|
+
(BOOLEAN_NODE_TYPES.has(node.parent.type) &&
|
99
99
|
node === node.parent.test) ||
|
100
100
|
|
101
101
|
// !<bool>
|
@@ -78,7 +78,7 @@ module.exports = {
|
|
78
78
|
* @returns {void}
|
79
79
|
*/
|
80
80
|
function checkVariable(variable) {
|
81
|
-
if (variable.writeable === false && exceptions.
|
81
|
+
if (variable.writeable === false && !exceptions.includes(variable.name)) {
|
82
82
|
variable.references.forEach(checkReference);
|
83
83
|
}
|
84
84
|
}
|