eslint 8.34.0 → 8.37.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 +11 -12
- package/conf/rule-type-list.json +2 -2
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/file-enumerator.js +8 -6
- package/lib/config/default-config.js +1 -4
- package/lib/config/flat-config-array.js +77 -17
- package/lib/config/flat-config-schema.js +4 -18
- package/lib/eslint/eslint-helpers.js +3 -3
- package/lib/linter/linter.js +5 -30
- package/lib/rule-tester/flat-rule-tester.js +1 -1
- package/lib/rule-tester/rule-tester.js +1 -1
- package/lib/rules/camelcase.js +3 -2
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/global-require.js +3 -1
- package/lib/rules/handle-callback-err.js +2 -1
- package/lib/rules/id-blacklist.js +3 -2
- package/lib/rules/id-denylist.js +3 -2
- package/lib/rules/id-match.js +3 -2
- package/lib/rules/lines-around-comment.js +11 -0
- package/lib/rules/logical-assignment-operators.js +4 -4
- package/lib/rules/multiline-comment-style.js +42 -3
- package/lib/rules/no-alert.js +3 -1
- package/lib/rules/no-catch-shadow.js +3 -1
- package/lib/rules/no-console.js +3 -2
- package/lib/rules/no-constant-binary-expression.js +36 -27
- package/lib/rules/no-constant-condition.js +3 -2
- package/lib/rules/no-control-regex.js +1 -1
- package/lib/rules/no-else-return.js +13 -12
- package/lib/rules/no-eval.js +5 -5
- package/lib/rules/no-extend-native.js +3 -2
- package/lib/rules/no-extra-boolean-cast.js +1 -1
- package/lib/rules/no-extra-parens.js +1 -1
- package/lib/rules/no-global-assign.js +3 -2
- package/lib/rules/no-implicit-globals.js +3 -2
- package/lib/rules/no-implied-eval.js +5 -4
- package/lib/rules/no-import-assign.js +4 -2
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-invalid-this.js +2 -2
- package/lib/rules/no-label-var.js +2 -1
- package/lib/rules/no-lone-blocks.js +3 -2
- package/lib/rules/no-loop-func.js +3 -1
- package/lib/rules/no-misleading-character-class.js +12 -41
- package/lib/rules/no-native-reassign.js +3 -2
- package/lib/rules/no-new-func.js +7 -6
- package/lib/rules/no-new-native-nonconstructor.js +8 -6
- package/lib/rules/no-new-object.js +4 -1
- package/lib/rules/no-new-symbol.js +8 -6
- package/lib/rules/no-obj-calls.js +8 -6
- package/lib/rules/no-promise-executor-return.js +3 -2
- package/lib/rules/no-redeclare.js +3 -3
- package/lib/rules/no-regex-spaces.js +4 -2
- package/lib/rules/no-restricted-globals.js +4 -2
- package/lib/rules/no-setter-return.js +3 -2
- package/lib/rules/no-shadow.js +3 -2
- package/lib/rules/no-undef-init.js +1 -1
- package/lib/rules/no-undef.js +3 -2
- package/lib/rules/no-undefined.js +4 -2
- package/lib/rules/no-unmodified-loop-condition.js +2 -2
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/no-use-before-define.js +3 -2
- package/lib/rules/no-useless-backreference.js +9 -7
- package/lib/rules/no-useless-return.js +1 -1
- package/lib/rules/object-shorthand.js +3 -2
- package/lib/rules/prefer-arrow-callback.js +1 -1
- package/lib/rules/prefer-exponentiation-operator.js +5 -5
- package/lib/rules/prefer-named-capture-group.js +8 -8
- package/lib/rules/prefer-object-has-own.js +4 -2
- package/lib/rules/prefer-object-spread.js +12 -12
- package/lib/rules/prefer-regex-literals.js +26 -27
- package/lib/rules/prefer-rest-params.js +5 -2
- package/lib/rules/radix.js +11 -11
- package/lib/rules/require-atomic-updates.js +2 -2
- package/lib/rules/require-unicode-regexp.js +63 -7
- package/lib/rules/symbol-description.js +7 -5
- package/lib/rules/utils/regular-expressions.js +42 -0
- package/lib/rules/valid-typeof.js +3 -3
- package/lib/rules/wrap-iife.js +1 -1
- package/lib/source-code/source-code.js +52 -1
- package/lib/source-code/token-store/index.js +1 -1
- package/lib/source-code/token-store/utils.js +14 -4
- package/messages/no-config-found.js +1 -1
- package/package.json +12 -7
- package/conf/eslint-all.js +0 -31
- package/conf/eslint-recommended.js +0 -76
@@ -61,6 +61,9 @@ module.exports = {
|
|
61
61
|
fixable: "code"
|
62
62
|
},
|
63
63
|
create(context) {
|
64
|
+
|
65
|
+
const sourceCode = context.getSourceCode();
|
66
|
+
|
64
67
|
return {
|
65
68
|
CallExpression(node) {
|
66
69
|
if (!(node.callee.type === "MemberExpression" && node.callee.object.type === "MemberExpression")) {
|
@@ -72,7 +75,7 @@ module.exports = {
|
|
72
75
|
const isObject = hasLeftHandObject(node.callee.object);
|
73
76
|
|
74
77
|
// check `Object` scope
|
75
|
-
const scope =
|
78
|
+
const scope = sourceCode.getScope(node);
|
76
79
|
const variable = astUtils.getVariableByName(scope, "Object");
|
77
80
|
|
78
81
|
if (
|
@@ -85,7 +88,6 @@ module.exports = {
|
|
85
88
|
node,
|
86
89
|
messageId: "useHasOwn",
|
87
90
|
fix(fixer) {
|
88
|
-
const sourceCode = context.getSourceCode();
|
89
91
|
|
90
92
|
if (sourceCode.getCommentsInside(node.callee).length > 0) {
|
91
93
|
return null;
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
-
const { CALL, ReferenceTracker } = require("eslint-utils");
|
9
|
+
const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils");
|
10
10
|
const {
|
11
11
|
isCommaToken,
|
12
12
|
isOpeningParenToken,
|
@@ -265,8 +265,8 @@ module.exports = {
|
|
265
265
|
const sourceCode = context.getSourceCode();
|
266
266
|
|
267
267
|
return {
|
268
|
-
Program() {
|
269
|
-
const scope =
|
268
|
+
Program(node) {
|
269
|
+
const scope = sourceCode.getScope(node);
|
270
270
|
const tracker = new ReferenceTracker(scope);
|
271
271
|
const trackMap = {
|
272
272
|
Object: {
|
@@ -275,22 +275,22 @@ module.exports = {
|
|
275
275
|
};
|
276
276
|
|
277
277
|
// Iterate all calls of `Object.assign` (only of the global variable `Object`).
|
278
|
-
for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
|
278
|
+
for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) {
|
279
279
|
if (
|
280
|
-
|
281
|
-
|
282
|
-
!hasArraySpread(
|
280
|
+
refNode.arguments.length >= 1 &&
|
281
|
+
refNode.arguments[0].type === "ObjectExpression" &&
|
282
|
+
!hasArraySpread(refNode) &&
|
283
283
|
!(
|
284
|
-
|
285
|
-
hasArgumentsWithAccessors(
|
284
|
+
refNode.arguments.length > 1 &&
|
285
|
+
hasArgumentsWithAccessors(refNode)
|
286
286
|
)
|
287
287
|
) {
|
288
|
-
const messageId =
|
288
|
+
const messageId = refNode.arguments.length === 1
|
289
289
|
? "useLiteralMessage"
|
290
290
|
: "useSpreadMessage";
|
291
|
-
const fix = defineFixer(
|
291
|
+
const fix = defineFixer(refNode, sourceCode);
|
292
292
|
|
293
|
-
context.report({ node, messageId, fix });
|
293
|
+
context.report({ node: refNode, messageId, fix });
|
294
294
|
}
|
295
295
|
}
|
296
296
|
}
|
@@ -10,16 +10,15 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const astUtils = require("./utils/ast-utils");
|
13
|
-
const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils");
|
14
|
-
const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp");
|
13
|
+
const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("@eslint-community/eslint-utils");
|
14
|
+
const { RegExpValidator, visitRegExpAST, RegExpParser } = require("@eslint-community/regexpp");
|
15
15
|
const { canTokensBeAdjacent } = require("./utils/ast-utils");
|
16
|
+
const { REGEXPP_LATEST_ECMA_VERSION } = require("./utils/regular-expressions");
|
16
17
|
|
17
18
|
//------------------------------------------------------------------------------
|
18
19
|
// Helpers
|
19
20
|
//------------------------------------------------------------------------------
|
20
21
|
|
21
|
-
const REGEXPP_LATEST_ECMA_VERSION = 2022;
|
22
|
-
|
23
22
|
/**
|
24
23
|
* Determines whether the given node is a string literal.
|
25
24
|
* @param {ASTNode} node Node to check.
|
@@ -163,7 +162,7 @@ module.exports = {
|
|
163
162
|
* @returns {boolean} True if the identifier is a reference to a global variable.
|
164
163
|
*/
|
165
164
|
function isGlobalReference(node) {
|
166
|
-
const scope =
|
165
|
+
const scope = sourceCode.getScope(node);
|
167
166
|
const variable = findVariable(scope, node);
|
168
167
|
|
169
168
|
return variable !== null && variable.scope.type === "global" && variable.defs.length === 0;
|
@@ -375,8 +374,8 @@ module.exports = {
|
|
375
374
|
}
|
376
375
|
|
377
376
|
return {
|
378
|
-
Program() {
|
379
|
-
const scope =
|
377
|
+
Program(node) {
|
378
|
+
const scope = sourceCode.getScope(node);
|
380
379
|
const tracker = new ReferenceTracker(scope);
|
381
380
|
const traceMap = {
|
382
381
|
RegExp: {
|
@@ -385,16 +384,16 @@ module.exports = {
|
|
385
384
|
}
|
386
385
|
};
|
387
386
|
|
388
|
-
for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
|
389
|
-
if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(
|
390
|
-
const regexNode =
|
387
|
+
for (const { node: refNode } of tracker.iterateGlobalReferences(traceMap)) {
|
388
|
+
if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(refNode)) {
|
389
|
+
const regexNode = refNode.arguments[0];
|
391
390
|
|
392
|
-
if (
|
391
|
+
if (refNode.arguments.length === 2) {
|
393
392
|
const suggests = [];
|
394
393
|
|
395
|
-
const argFlags = getStringValue(
|
394
|
+
const argFlags = getStringValue(refNode.arguments[1]) || "";
|
396
395
|
|
397
|
-
if (canFixTo(
|
396
|
+
if (canFixTo(refNode, regexNode.regex.pattern, argFlags)) {
|
398
397
|
suggests.push({
|
399
398
|
messageId: "replaceWithLiteralAndFlags",
|
400
399
|
pattern: regexNode.regex.pattern,
|
@@ -407,7 +406,7 @@ module.exports = {
|
|
407
406
|
|
408
407
|
if (
|
409
408
|
!areFlagsEqual(mergedFlags, argFlags) &&
|
410
|
-
canFixTo(
|
409
|
+
canFixTo(refNode, regexNode.regex.pattern, mergedFlags)
|
411
410
|
) {
|
412
411
|
suggests.push({
|
413
412
|
messageId: "replaceWithIntendedLiteralAndFlags",
|
@@ -417,7 +416,7 @@ module.exports = {
|
|
417
416
|
}
|
418
417
|
|
419
418
|
context.report({
|
420
|
-
node,
|
419
|
+
node: refNode,
|
421
420
|
messageId: "unexpectedRedundantRegExpWithFlags",
|
422
421
|
suggest: suggests.map(({ flags, pattern, messageId }) => ({
|
423
422
|
messageId,
|
@@ -425,42 +424,42 @@ module.exports = {
|
|
425
424
|
flags
|
426
425
|
},
|
427
426
|
fix(fixer) {
|
428
|
-
return fixer.replaceText(
|
427
|
+
return fixer.replaceText(refNode, getSafeOutput(refNode, `/${pattern}/${flags}`));
|
429
428
|
}
|
430
429
|
}))
|
431
430
|
});
|
432
431
|
} else {
|
433
432
|
const outputs = [];
|
434
433
|
|
435
|
-
if (canFixTo(
|
434
|
+
if (canFixTo(refNode, regexNode.regex.pattern, regexNode.regex.flags)) {
|
436
435
|
outputs.push(sourceCode.getText(regexNode));
|
437
436
|
}
|
438
437
|
|
439
438
|
|
440
439
|
context.report({
|
441
|
-
node,
|
440
|
+
node: refNode,
|
442
441
|
messageId: "unexpectedRedundantRegExp",
|
443
442
|
suggest: outputs.map(output => ({
|
444
443
|
messageId: "replaceWithLiteral",
|
445
444
|
fix(fixer) {
|
446
445
|
return fixer.replaceText(
|
447
|
-
|
448
|
-
getSafeOutput(
|
446
|
+
refNode,
|
447
|
+
getSafeOutput(refNode, output)
|
449
448
|
);
|
450
449
|
}
|
451
450
|
}))
|
452
451
|
});
|
453
452
|
}
|
454
|
-
} else if (hasOnlyStaticStringArguments(
|
455
|
-
let regexContent = getStringValue(
|
453
|
+
} else if (hasOnlyStaticStringArguments(refNode)) {
|
454
|
+
let regexContent = getStringValue(refNode.arguments[0]);
|
456
455
|
let noFix = false;
|
457
456
|
let flags;
|
458
457
|
|
459
|
-
if (
|
460
|
-
flags = getStringValue(
|
458
|
+
if (refNode.arguments[1]) {
|
459
|
+
flags = getStringValue(refNode.arguments[1]);
|
461
460
|
}
|
462
461
|
|
463
|
-
if (!canFixTo(
|
462
|
+
if (!canFixTo(refNode, regexContent, flags)) {
|
464
463
|
noFix = true;
|
465
464
|
}
|
466
465
|
|
@@ -494,12 +493,12 @@ module.exports = {
|
|
494
493
|
const newRegExpValue = `/${regexContent || "(?:)"}/${flags || ""}`;
|
495
494
|
|
496
495
|
context.report({
|
497
|
-
node,
|
496
|
+
node: refNode,
|
498
497
|
messageId: "unexpectedRegExp",
|
499
498
|
suggest: noFix ? [] : [{
|
500
499
|
messageId: "replaceWithLiteral",
|
501
500
|
fix(fixer) {
|
502
|
-
return fixer.replaceText(
|
501
|
+
return fixer.replaceText(refNode, getSafeOutput(refNode, newRegExpValue));
|
503
502
|
}
|
504
503
|
}]
|
505
504
|
});
|
@@ -79,6 +79,8 @@ module.exports = {
|
|
79
79
|
|
80
80
|
create(context) {
|
81
81
|
|
82
|
+
const sourceCode = context.getSourceCode();
|
83
|
+
|
82
84
|
/**
|
83
85
|
* Reports a given reference.
|
84
86
|
* @param {eslint-scope.Reference} reference A reference to report.
|
@@ -94,10 +96,11 @@ module.exports = {
|
|
94
96
|
|
95
97
|
/**
|
96
98
|
* Reports references of the implicit `arguments` variable if exist.
|
99
|
+
* @param {ASTNode} node The node representing the function.
|
97
100
|
* @returns {void}
|
98
101
|
*/
|
99
|
-
function checkForArguments() {
|
100
|
-
const argumentsVar = getVariableOfArguments(
|
102
|
+
function checkForArguments(node) {
|
103
|
+
const argumentsVar = getVariableOfArguments(sourceCode.getScope(node));
|
101
104
|
|
102
105
|
if (argumentsVar) {
|
103
106
|
argumentsVar
|
package/lib/rules/radix.js
CHANGED
@@ -104,6 +104,7 @@ module.exports = {
|
|
104
104
|
|
105
105
|
create(context) {
|
106
106
|
const mode = context.options[0] || MODE_ALWAYS;
|
107
|
+
const sourceCode = context.getSourceCode();
|
107
108
|
|
108
109
|
/**
|
109
110
|
* Checks the arguments of a given CallExpression node and reports it if it
|
@@ -131,7 +132,6 @@ module.exports = {
|
|
131
132
|
{
|
132
133
|
messageId: "addRadixParameter10",
|
133
134
|
fix(fixer) {
|
134
|
-
const sourceCode = context.getSourceCode();
|
135
135
|
const tokens = sourceCode.getTokens(node);
|
136
136
|
const lastToken = tokens[tokens.length - 1]; // Parenthesis.
|
137
137
|
const secondToLastToken = tokens[tokens.length - 2]; // May or may not be a comma.
|
@@ -162,18 +162,18 @@ module.exports = {
|
|
162
162
|
}
|
163
163
|
|
164
164
|
return {
|
165
|
-
"Program:exit"() {
|
166
|
-
const scope =
|
165
|
+
"Program:exit"(node) {
|
166
|
+
const scope = sourceCode.getScope(node);
|
167
167
|
let variable;
|
168
168
|
|
169
169
|
// Check `parseInt()`
|
170
170
|
variable = astUtils.getVariableByName(scope, "parseInt");
|
171
171
|
if (variable && !isShadowed(variable)) {
|
172
172
|
variable.references.forEach(reference => {
|
173
|
-
const
|
173
|
+
const idNode = reference.identifier;
|
174
174
|
|
175
|
-
if (astUtils.isCallee(
|
176
|
-
checkArguments(
|
175
|
+
if (astUtils.isCallee(idNode)) {
|
176
|
+
checkArguments(idNode.parent);
|
177
177
|
}
|
178
178
|
});
|
179
179
|
}
|
@@ -182,12 +182,12 @@ module.exports = {
|
|
182
182
|
variable = astUtils.getVariableByName(scope, "Number");
|
183
183
|
if (variable && !isShadowed(variable)) {
|
184
184
|
variable.references.forEach(reference => {
|
185
|
-
const
|
186
|
-
const maybeCallee =
|
187
|
-
?
|
188
|
-
:
|
185
|
+
const parentNode = reference.identifier.parent;
|
186
|
+
const maybeCallee = parentNode.parent.type === "ChainExpression"
|
187
|
+
? parentNode.parent
|
188
|
+
: parentNode;
|
189
189
|
|
190
|
-
if (isParseIntMethod(
|
190
|
+
if (isParseIntMethod(parentNode) && astUtils.isCallee(maybeCallee)) {
|
191
191
|
checkArguments(maybeCallee.parent);
|
192
192
|
}
|
193
193
|
});
|
@@ -204,8 +204,8 @@ module.exports = {
|
|
204
204
|
let stack = null;
|
205
205
|
|
206
206
|
return {
|
207
|
-
onCodePathStart(codePath) {
|
208
|
-
const scope =
|
207
|
+
onCodePathStart(codePath, node) {
|
208
|
+
const scope = sourceCode.getScope(node);
|
209
209
|
const shouldVerify =
|
210
210
|
scope.type === "function" &&
|
211
211
|
(scope.block.async || scope.block.generator);
|
@@ -14,7 +14,9 @@ const {
|
|
14
14
|
CONSTRUCT,
|
15
15
|
ReferenceTracker,
|
16
16
|
getStringIfConstant
|
17
|
-
} = require("eslint-utils");
|
17
|
+
} = require("@eslint-community/eslint-utils");
|
18
|
+
const astUtils = require("./utils/ast-utils.js");
|
19
|
+
const { isValidWithUnicodeFlag } = require("./utils/regular-expressions");
|
18
20
|
|
19
21
|
//------------------------------------------------------------------------------
|
20
22
|
// Rule Definition
|
@@ -31,7 +33,10 @@ module.exports = {
|
|
31
33
|
url: "https://eslint.org/docs/rules/require-unicode-regexp"
|
32
34
|
},
|
33
35
|
|
36
|
+
hasSuggestions: true,
|
37
|
+
|
34
38
|
messages: {
|
39
|
+
addUFlag: "Add the 'u' flag.",
|
35
40
|
requireUFlag: "Use the 'u' flag."
|
36
41
|
},
|
37
42
|
|
@@ -39,28 +44,79 @@ module.exports = {
|
|
39
44
|
},
|
40
45
|
|
41
46
|
create(context) {
|
47
|
+
|
48
|
+
const sourceCode = context.getSourceCode();
|
49
|
+
|
42
50
|
return {
|
43
51
|
"Literal[regex]"(node) {
|
44
52
|
const flags = node.regex.flags || "";
|
45
53
|
|
46
54
|
if (!flags.includes("u")) {
|
47
|
-
context.report({
|
55
|
+
context.report({
|
56
|
+
messageId: "requireUFlag",
|
57
|
+
node,
|
58
|
+
suggest: isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, node.regex.pattern)
|
59
|
+
? [
|
60
|
+
{
|
61
|
+
fix(fixer) {
|
62
|
+
return fixer.insertTextAfter(node, "u");
|
63
|
+
},
|
64
|
+
messageId: "addUFlag"
|
65
|
+
}
|
66
|
+
]
|
67
|
+
: null
|
68
|
+
});
|
48
69
|
}
|
49
70
|
},
|
50
71
|
|
51
|
-
Program() {
|
52
|
-
const scope =
|
72
|
+
Program(node) {
|
73
|
+
const scope = sourceCode.getScope(node);
|
53
74
|
const tracker = new ReferenceTracker(scope);
|
54
75
|
const trackMap = {
|
55
76
|
RegExp: { [CALL]: true, [CONSTRUCT]: true }
|
56
77
|
};
|
57
78
|
|
58
|
-
for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
|
59
|
-
const flagsNode =
|
79
|
+
for (const { node: refNode } of tracker.iterateGlobalReferences(trackMap)) {
|
80
|
+
const [patternNode, flagsNode] = refNode.arguments;
|
81
|
+
const pattern = getStringIfConstant(patternNode, scope);
|
60
82
|
const flags = getStringIfConstant(flagsNode, scope);
|
61
83
|
|
62
84
|
if (!flagsNode || (typeof flags === "string" && !flags.includes("u"))) {
|
63
|
-
context.report({
|
85
|
+
context.report({
|
86
|
+
messageId: "requireUFlag",
|
87
|
+
node: refNode,
|
88
|
+
suggest: typeof pattern === "string" && isValidWithUnicodeFlag(context.languageOptions.ecmaVersion, pattern)
|
89
|
+
? [
|
90
|
+
{
|
91
|
+
fix(fixer) {
|
92
|
+
if (flagsNode) {
|
93
|
+
if ((flagsNode.type === "Literal" && typeof flagsNode.value === "string") || flagsNode.type === "TemplateLiteral") {
|
94
|
+
const flagsNodeText = sourceCode.getText(flagsNode);
|
95
|
+
|
96
|
+
return fixer.replaceText(flagsNode, [
|
97
|
+
flagsNodeText.slice(0, flagsNodeText.length - 1),
|
98
|
+
flagsNodeText.slice(flagsNodeText.length - 1)
|
99
|
+
].join("u"));
|
100
|
+
}
|
101
|
+
|
102
|
+
// We intentionally don't suggest concatenating + "u" to non-literals
|
103
|
+
return null;
|
104
|
+
}
|
105
|
+
|
106
|
+
const penultimateToken = sourceCode.getLastToken(refNode, { skip: 1 }); // skip closing parenthesis
|
107
|
+
|
108
|
+
return fixer.insertTextAfter(
|
109
|
+
penultimateToken,
|
110
|
+
astUtils.isCommaToken(penultimateToken)
|
111
|
+
? ' "u",'
|
112
|
+
: ', "u"'
|
113
|
+
);
|
114
|
+
},
|
115
|
+
messageId: "addUFlag"
|
116
|
+
}
|
117
|
+
]
|
118
|
+
: null
|
119
|
+
});
|
64
120
|
}
|
65
121
|
}
|
66
122
|
}
|
@@ -35,6 +35,8 @@ module.exports = {
|
|
35
35
|
|
36
36
|
create(context) {
|
37
37
|
|
38
|
+
const sourceCode = context.getSourceCode();
|
39
|
+
|
38
40
|
/**
|
39
41
|
* Reports if node does not conform the rule in case rule is set to
|
40
42
|
* report missing description
|
@@ -51,16 +53,16 @@ module.exports = {
|
|
51
53
|
}
|
52
54
|
|
53
55
|
return {
|
54
|
-
"Program:exit"() {
|
55
|
-
const scope =
|
56
|
+
"Program:exit"(node) {
|
57
|
+
const scope = sourceCode.getScope(node);
|
56
58
|
const variable = astUtils.getVariableByName(scope, "Symbol");
|
57
59
|
|
58
60
|
if (variable && variable.defs.length === 0) {
|
59
61
|
variable.references.forEach(reference => {
|
60
|
-
const
|
62
|
+
const idNode = reference.identifier;
|
61
63
|
|
62
|
-
if (astUtils.isCallee(
|
63
|
-
checkArgument(
|
64
|
+
if (astUtils.isCallee(idNode)) {
|
65
|
+
checkArgument(idNode.parent);
|
64
66
|
}
|
65
67
|
});
|
66
68
|
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Common utils for regular expressions.
|
3
|
+
* @author Josh Goldberg
|
4
|
+
* @author Toru Nagashima
|
5
|
+
*/
|
6
|
+
|
7
|
+
"use strict";
|
8
|
+
|
9
|
+
const { RegExpValidator } = require("@eslint-community/regexpp");
|
10
|
+
|
11
|
+
const REGEXPP_LATEST_ECMA_VERSION = 2022;
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Checks if the given regular expression pattern would be valid with the `u` flag.
|
15
|
+
* @param {number} ecmaVersion ECMAScript version to parse in.
|
16
|
+
* @param {string} pattern The regular expression pattern to verify.
|
17
|
+
* @returns {boolean} `true` if the pattern would be valid with the `u` flag.
|
18
|
+
* `false` if the pattern would be invalid with the `u` flag or the configured
|
19
|
+
* ecmaVersion doesn't support the `u` flag.
|
20
|
+
*/
|
21
|
+
function isValidWithUnicodeFlag(ecmaVersion, pattern) {
|
22
|
+
if (ecmaVersion <= 5) { // ecmaVersion <= 5 doesn't support the 'u' flag
|
23
|
+
return false;
|
24
|
+
}
|
25
|
+
|
26
|
+
const validator = new RegExpValidator({
|
27
|
+
ecmaVersion: Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION)
|
28
|
+
});
|
29
|
+
|
30
|
+
try {
|
31
|
+
validator.validatePattern(pattern, void 0, void 0, /* uFlag = */ true);
|
32
|
+
} catch {
|
33
|
+
return false;
|
34
|
+
}
|
35
|
+
|
36
|
+
return true;
|
37
|
+
}
|
38
|
+
|
39
|
+
module.exports = {
|
40
|
+
isValidWithUnicodeFlag,
|
41
|
+
REGEXPP_LATEST_ECMA_VERSION
|
42
|
+
};
|
@@ -44,7 +44,7 @@ module.exports = {
|
|
44
44
|
|
45
45
|
const VALID_TYPES = new Set(["symbol", "undefined", "object", "boolean", "number", "string", "function", "bigint"]),
|
46
46
|
OPERATORS = new Set(["==", "===", "!=", "!=="]);
|
47
|
-
|
47
|
+
const sourceCode = context.getSourceCode();
|
48
48
|
const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;
|
49
49
|
|
50
50
|
let globalScope;
|
@@ -77,8 +77,8 @@ module.exports = {
|
|
77
77
|
|
78
78
|
return {
|
79
79
|
|
80
|
-
Program() {
|
81
|
-
globalScope =
|
80
|
+
Program(node) {
|
81
|
+
globalScope = sourceCode.getScope(node);
|
82
82
|
},
|
83
83
|
|
84
84
|
UnaryExpression(node) {
|
package/lib/rules/wrap-iife.js
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const astUtils = require("./utils/ast-utils");
|
13
|
-
const eslintUtils = require("eslint-utils");
|
13
|
+
const eslintUtils = require("@eslint-community/eslint-utils");
|
14
14
|
|
15
15
|
//----------------------------------------------------------------------
|
16
16
|
// Helpers
|
@@ -9,7 +9,7 @@
|
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
11
|
const
|
12
|
-
{ isCommentToken } = require("eslint-utils"),
|
12
|
+
{ isCommentToken } = require("@eslint-community/eslint-utils"),
|
13
13
|
TokenStore = require("./token-store"),
|
14
14
|
astUtils = require("../shared/ast-utils"),
|
15
15
|
Traverser = require("../shared/traverser");
|
@@ -143,6 +143,8 @@ function isSpaceBetween(sourceCode, first, second, checkInsideOfJSXText) {
|
|
143
143
|
// Public Interface
|
144
144
|
//------------------------------------------------------------------------------
|
145
145
|
|
146
|
+
const caches = Symbol("caches");
|
147
|
+
|
146
148
|
/**
|
147
149
|
* Represents parsed source code.
|
148
150
|
*/
|
@@ -175,6 +177,13 @@ class SourceCode extends TokenStore {
|
|
175
177
|
validate(ast);
|
176
178
|
super(ast.tokens, ast.comments);
|
177
179
|
|
180
|
+
/**
|
181
|
+
* General purpose caching for the class.
|
182
|
+
*/
|
183
|
+
this[caches] = new Map([
|
184
|
+
["scopes", new WeakMap()]
|
185
|
+
]);
|
186
|
+
|
178
187
|
/**
|
179
188
|
* The flag to indicate that the source code has Unicode BOM.
|
180
189
|
* @type {boolean}
|
@@ -588,6 +597,48 @@ class SourceCode extends TokenStore {
|
|
588
597
|
|
589
598
|
return positionIndex;
|
590
599
|
}
|
600
|
+
|
601
|
+
/**
|
602
|
+
* Gets the scope for the given node
|
603
|
+
* @param {ASTNode} currentNode The node to get the scope of
|
604
|
+
* @returns {eslint-scope.Scope} The scope information for this node
|
605
|
+
* @throws {TypeError} If the `currentNode` argument is missing.
|
606
|
+
*/
|
607
|
+
getScope(currentNode) {
|
608
|
+
|
609
|
+
if (!currentNode) {
|
610
|
+
throw new TypeError("Missing required argument: node.");
|
611
|
+
}
|
612
|
+
|
613
|
+
// check cache first
|
614
|
+
const cache = this[caches].get("scopes");
|
615
|
+
const cachedScope = cache.get(currentNode);
|
616
|
+
|
617
|
+
if (cachedScope) {
|
618
|
+
return cachedScope;
|
619
|
+
}
|
620
|
+
|
621
|
+
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
622
|
+
const inner = currentNode.type !== "Program";
|
623
|
+
|
624
|
+
for (let node = currentNode; node; node = node.parent) {
|
625
|
+
const scope = this.scopeManager.acquire(node, inner);
|
626
|
+
|
627
|
+
if (scope) {
|
628
|
+
if (scope.type === "function-expression-name") {
|
629
|
+
cache.set(currentNode, scope.childScopes[0]);
|
630
|
+
return scope.childScopes[0];
|
631
|
+
}
|
632
|
+
|
633
|
+
cache.set(currentNode, scope);
|
634
|
+
return scope;
|
635
|
+
}
|
636
|
+
}
|
637
|
+
|
638
|
+
cache.set(currentNode, this.scopeManager.scopes[0]);
|
639
|
+
return this.scopeManager.scopes[0];
|
640
|
+
}
|
641
|
+
|
591
642
|
}
|
592
643
|
|
593
644
|
module.exports = SourceCode;
|
@@ -9,7 +9,7 @@
|
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
11
|
const assert = require("assert");
|
12
|
-
const { isCommentToken } = require("eslint-utils");
|
12
|
+
const { isCommentToken } = require("@eslint-community/eslint-utils");
|
13
13
|
const cursors = require("./cursors");
|
14
14
|
const ForwardTokenCursor = require("./forward-token-cursor");
|
15
15
|
const PaddedTokenCursor = require("./padded-token-cursor");
|
@@ -49,13 +49,18 @@ exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) {
|
|
49
49
|
}
|
50
50
|
if ((startLoc - 1) in indexMap) {
|
51
51
|
const index = indexMap[startLoc - 1];
|
52
|
-
const token =
|
52
|
+
const token = tokens[index];
|
53
|
+
|
54
|
+
// If the mapped index is out of bounds, the returned cursor index will point after the end of the tokens array.
|
55
|
+
if (!token) {
|
56
|
+
return tokens.length;
|
57
|
+
}
|
53
58
|
|
54
59
|
/*
|
55
60
|
* For the map of "comment's location -> token's index", it points the next token of a comment.
|
56
61
|
* In that case, +1 is unnecessary.
|
57
62
|
*/
|
58
|
-
if (token
|
63
|
+
if (token.range[0] >= startLoc) {
|
59
64
|
return index;
|
60
65
|
}
|
61
66
|
return index + 1;
|
@@ -77,13 +82,18 @@ exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) {
|
|
77
82
|
}
|
78
83
|
if ((endLoc - 1) in indexMap) {
|
79
84
|
const index = indexMap[endLoc - 1];
|
80
|
-
const token =
|
85
|
+
const token = tokens[index];
|
86
|
+
|
87
|
+
// If the mapped index is out of bounds, the returned cursor index will point before the end of the tokens array.
|
88
|
+
if (!token) {
|
89
|
+
return tokens.length - 1;
|
90
|
+
}
|
81
91
|
|
82
92
|
/*
|
83
93
|
* For the map of "comment's location -> token's index", it points the next token of a comment.
|
84
94
|
* In that case, -1 is necessary.
|
85
95
|
*/
|
86
|
-
if (token
|
96
|
+
if (token.range[1] > endLoc) {
|
87
97
|
return index - 1;
|
88
98
|
}
|
89
99
|
return index;
|