eslint 7.5.0 → 7.8.1
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/CHANGELOG.md +65 -0
- package/README.md +26 -16
- package/conf/config-schema.js +12 -0
- package/lib/cli-engine/cascading-config-array-factory.js +12 -0
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/config-array/config-array.js +12 -0
- package/lib/cli-engine/config-array/config-dependency.js +12 -0
- package/lib/cli-engine/config-array/extracted-config.js +12 -0
- package/lib/cli-engine/config-array/ignore-pattern.js +12 -0
- package/lib/cli-engine/config-array/index.js +12 -0
- package/lib/cli-engine/config-array/override-tester.js +12 -0
- package/lib/cli-engine/config-array-factory.js +13 -1
- package/lib/cli-engine/formatters/checkstyle.js +2 -2
- package/lib/eslint/eslint.js +7 -1
- package/lib/init/autoconfig.js +1 -1
- package/lib/init/config-initializer.js +3 -3
- package/lib/linter/code-path-analysis/code-path-analyzer.js +38 -0
- package/lib/linter/code-path-analysis/code-path-state.js +2 -2
- package/lib/linter/config-comment-parser.js +1 -1
- package/lib/linter/linter.js +6 -3
- package/lib/rule-tester/rule-tester.js +10 -0
- package/lib/rules/comma-dangle.js +1 -2
- package/lib/rules/constructor-super.js +17 -1
- package/lib/rules/id-length.js +19 -1
- package/lib/rules/indent.js +4 -3
- package/lib/rules/no-duplicate-case.js +23 -4
- package/lib/rules/no-loss-of-precision.js +10 -2
- package/lib/rules/no-magic-numbers.js +20 -3
- package/lib/rules/no-underscore-dangle.js +66 -21
- package/lib/rules/no-warning-comments.js +40 -7
- package/lib/rules/operator-assignment.js +1 -1
- package/lib/rules/prefer-numeric-literals.js +10 -0
- package/lib/rules/utils/ast-utils.js +47 -13
- package/lib/shared/config-validator.js +14 -2
- package/lib/shared/relative-module-resolver.js +12 -0
- package/lib/shared/types.js +1 -1
- package/messages/extend-config-missing.txt +1 -1
- package/messages/no-config-found.txt +1 -1
- package/messages/plugin-conflict.txt +1 -1
- package/messages/plugin-missing.txt +1 -1
- package/messages/whitespace-found.txt +1 -1
- package/package.json +3 -3
- package/conf/environments.js +0 -168
- package/lib/shared/config-ops.js +0 -130
- package/lib/shared/naming.js +0 -97
package/lib/rules/id-length.js
CHANGED
@@ -39,6 +39,13 @@ module.exports = {
|
|
39
39
|
type: "string"
|
40
40
|
}
|
41
41
|
},
|
42
|
+
exceptionPatterns: {
|
43
|
+
type: "array",
|
44
|
+
uniqueItems: true,
|
45
|
+
items: {
|
46
|
+
type: "string"
|
47
|
+
}
|
48
|
+
},
|
42
49
|
properties: {
|
43
50
|
enum: ["always", "never"]
|
44
51
|
}
|
@@ -63,8 +70,19 @@ module.exports = {
|
|
63
70
|
|
64
71
|
return obj;
|
65
72
|
}, {});
|
73
|
+
const exceptionPatterns = (options.exceptionPatterns || []).map(pattern => new RegExp(pattern, "u"));
|
66
74
|
const reportedNode = new Set();
|
67
75
|
|
76
|
+
/**
|
77
|
+
* Checks if a string matches the provided exception patterns
|
78
|
+
* @param {string} name The string to check.
|
79
|
+
* @returns {boolean} if the string is a match
|
80
|
+
* @private
|
81
|
+
*/
|
82
|
+
function matchesExceptionPattern(name) {
|
83
|
+
return exceptionPatterns.some(pattern => pattern.test(name));
|
84
|
+
}
|
85
|
+
|
68
86
|
const SUPPORTED_EXPRESSIONS = {
|
69
87
|
MemberExpression: properties && function(parent) {
|
70
88
|
return !parent.computed && (
|
@@ -112,7 +130,7 @@ module.exports = {
|
|
112
130
|
const isShort = name.length < minLength;
|
113
131
|
const isLong = name.length > maxLength;
|
114
132
|
|
115
|
-
if (!(isShort || isLong) || exceptions[name]) {
|
133
|
+
if (!(isShort || isLong) || exceptions[name] || matchesExceptionPattern(name)) {
|
116
134
|
return; // Nothing to report
|
117
135
|
}
|
118
136
|
|
package/lib/rules/indent.js
CHANGED
@@ -1084,16 +1084,17 @@ module.exports = {
|
|
1084
1084
|
},
|
1085
1085
|
|
1086
1086
|
ArrowFunctionExpression(node) {
|
1087
|
-
const
|
1087
|
+
const maybeOpeningParen = sourceCode.getFirstToken(node, { skip: node.async ? 1 : 0 });
|
1088
1088
|
|
1089
|
-
if (astUtils.isOpeningParenToken(
|
1090
|
-
const openingParen =
|
1089
|
+
if (astUtils.isOpeningParenToken(maybeOpeningParen)) {
|
1090
|
+
const openingParen = maybeOpeningParen;
|
1091
1091
|
const closingParen = sourceCode.getTokenBefore(node.body, astUtils.isClosingParenToken);
|
1092
1092
|
|
1093
1093
|
parameterParens.add(openingParen);
|
1094
1094
|
parameterParens.add(closingParen);
|
1095
1095
|
addElementListIndent(node.params, openingParen, closingParen, options.FunctionExpression.parameters);
|
1096
1096
|
}
|
1097
|
+
|
1097
1098
|
addBlocklessNodeIndent(node.body);
|
1098
1099
|
},
|
1099
1100
|
|
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Requirements
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
const astUtils = require("./utils/ast-utils");
|
14
|
+
|
9
15
|
//------------------------------------------------------------------------------
|
10
16
|
// Rule Definition
|
11
17
|
//------------------------------------------------------------------------------
|
@@ -31,18 +37,31 @@ module.exports = {
|
|
31
37
|
create(context) {
|
32
38
|
const sourceCode = context.getSourceCode();
|
33
39
|
|
40
|
+
/**
|
41
|
+
* Determines whether the two given nodes are considered to be equal.
|
42
|
+
* @param {ASTNode} a First node.
|
43
|
+
* @param {ASTNode} b Second node.
|
44
|
+
* @returns {boolean} `true` if the nodes are considered to be equal.
|
45
|
+
*/
|
46
|
+
function equal(a, b) {
|
47
|
+
if (a.type !== b.type) {
|
48
|
+
return false;
|
49
|
+
}
|
50
|
+
|
51
|
+
return astUtils.equalTokens(a, b, sourceCode);
|
52
|
+
}
|
34
53
|
return {
|
35
54
|
SwitchStatement(node) {
|
36
|
-
const
|
55
|
+
const previousTests = [];
|
37
56
|
|
38
57
|
for (const switchCase of node.cases) {
|
39
58
|
if (switchCase.test) {
|
40
|
-
const
|
59
|
+
const test = switchCase.test;
|
41
60
|
|
42
|
-
if (
|
61
|
+
if (previousTests.some(previousTest => equal(previousTest, test))) {
|
43
62
|
context.report({ node: switchCase, messageId: "unexpected" });
|
44
63
|
} else {
|
45
|
-
|
64
|
+
previousTests.push(test);
|
46
65
|
}
|
47
66
|
}
|
48
67
|
}
|
@@ -36,6 +36,14 @@ module.exports = {
|
|
36
36
|
return typeof node.value === "number";
|
37
37
|
}
|
38
38
|
|
39
|
+
/**
|
40
|
+
* Gets the source code of the given number literal. Removes `_` numeric separators from the result.
|
41
|
+
* @param {Node} node the number `Literal` node
|
42
|
+
* @returns {string} raw source code of the literal, without numeric separators
|
43
|
+
*/
|
44
|
+
function getRaw(node) {
|
45
|
+
return node.raw.replace(/_/gu, "");
|
46
|
+
}
|
39
47
|
|
40
48
|
/**
|
41
49
|
* Checks whether the number is base ten
|
@@ -55,7 +63,7 @@ module.exports = {
|
|
55
63
|
* @returns {boolean} true if they do not match
|
56
64
|
*/
|
57
65
|
function notBaseTenLosesPrecision(node) {
|
58
|
-
const rawString = node.
|
66
|
+
const rawString = getRaw(node).toUpperCase();
|
59
67
|
let base = 0;
|
60
68
|
|
61
69
|
if (rawString.startsWith("0B")) {
|
@@ -161,7 +169,7 @@ module.exports = {
|
|
161
169
|
* @returns {boolean} true if they do not match
|
162
170
|
*/
|
163
171
|
function baseTenLosesPrecision(node) {
|
164
|
-
const normalizedRawNumber = convertNumberToScientificNotation(node
|
172
|
+
const normalizedRawNumber = convertNumberToScientificNotation(getRaw(node));
|
165
173
|
const requestedPrecision = normalizedRawNumber.split("e")[0].replace(".", "").length;
|
166
174
|
|
167
175
|
if (requestedPrecision > 100) {
|
@@ -61,6 +61,10 @@ module.exports = {
|
|
61
61
|
ignoreArrayIndexes: {
|
62
62
|
type: "boolean",
|
63
63
|
default: false
|
64
|
+
},
|
65
|
+
ignoreDefaultValues: {
|
66
|
+
type: "boolean",
|
67
|
+
default: false
|
64
68
|
}
|
65
69
|
},
|
66
70
|
additionalProperties: false
|
@@ -77,7 +81,8 @@ module.exports = {
|
|
77
81
|
detectObjects = !!config.detectObjects,
|
78
82
|
enforceConst = !!config.enforceConst,
|
79
83
|
ignore = (config.ignore || []).map(normalizeIgnoreValue),
|
80
|
-
ignoreArrayIndexes = !!config.ignoreArrayIndexes
|
84
|
+
ignoreArrayIndexes = !!config.ignoreArrayIndexes,
|
85
|
+
ignoreDefaultValues = !!config.ignoreDefaultValues;
|
81
86
|
|
82
87
|
const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
|
83
88
|
|
@@ -90,6 +95,17 @@ module.exports = {
|
|
90
95
|
return ignore.indexOf(value) !== -1;
|
91
96
|
}
|
92
97
|
|
98
|
+
/**
|
99
|
+
* Returns whether the number is a default value assignment.
|
100
|
+
* @param {ASTNode} fullNumberNode `Literal` or `UnaryExpression` full number node
|
101
|
+
* @returns {boolean} true if the number is a default value
|
102
|
+
*/
|
103
|
+
function isDefaultValue(fullNumberNode) {
|
104
|
+
const parent = fullNumberNode.parent;
|
105
|
+
|
106
|
+
return parent.type === "AssignmentPattern" && parent.right === fullNumberNode;
|
107
|
+
}
|
108
|
+
|
93
109
|
/**
|
94
110
|
* Returns whether the given node is used as a radix within parseInt() or Number.parseInt()
|
95
111
|
* @param {ASTNode} fullNumberNode `Literal` or `UnaryExpression` full number node
|
@@ -172,9 +188,12 @@ module.exports = {
|
|
172
188
|
raw = node.raw;
|
173
189
|
}
|
174
190
|
|
191
|
+
const parent = fullNumberNode.parent;
|
192
|
+
|
175
193
|
// Always allow radix arguments and JSX props
|
176
194
|
if (
|
177
195
|
isIgnoredValue(value) ||
|
196
|
+
(ignoreDefaultValues && isDefaultValue(fullNumberNode)) ||
|
178
197
|
isParseIntRadix(fullNumberNode) ||
|
179
198
|
isJSXNumber(fullNumberNode) ||
|
180
199
|
(ignoreArrayIndexes && isArrayIndex(fullNumberNode, value))
|
@@ -182,8 +201,6 @@ module.exports = {
|
|
182
201
|
return;
|
183
202
|
}
|
184
203
|
|
185
|
-
const parent = fullNumberNode.parent;
|
186
|
-
|
187
204
|
if (parent.type === "VariableDeclarator") {
|
188
205
|
if (enforceConst && parent.parent.kind !== "const") {
|
189
206
|
context.report({
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @fileoverview Rule to flag
|
2
|
+
* @fileoverview Rule to flag dangling underscores in variable declarations.
|
3
3
|
* @author Matt DuVall <http://www.mattduvall.com>
|
4
4
|
*/
|
5
5
|
|
@@ -45,6 +45,10 @@ module.exports = {
|
|
45
45
|
enforceInMethodNames: {
|
46
46
|
type: "boolean",
|
47
47
|
default: false
|
48
|
+
},
|
49
|
+
allowFunctionParams: {
|
50
|
+
type: "boolean",
|
51
|
+
default: true
|
48
52
|
}
|
49
53
|
},
|
50
54
|
additionalProperties: false
|
@@ -64,6 +68,7 @@ module.exports = {
|
|
64
68
|
const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
|
65
69
|
const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
|
66
70
|
const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
|
71
|
+
const allowFunctionParams = typeof options.allowFunctionParams !== "undefined" ? options.allowFunctionParams : true;
|
67
72
|
|
68
73
|
//-------------------------------------------------------------------------
|
69
74
|
// Helpers
|
@@ -80,12 +85,12 @@ module.exports = {
|
|
80
85
|
}
|
81
86
|
|
82
87
|
/**
|
83
|
-
* Check if identifier has a underscore
|
88
|
+
* Check if identifier has a dangling underscore
|
84
89
|
* @param {string} identifier name of the node
|
85
90
|
* @returns {boolean} true if its is present
|
86
91
|
* @private
|
87
92
|
*/
|
88
|
-
function
|
93
|
+
function hasDanglingUnderscore(identifier) {
|
89
94
|
const len = identifier.length;
|
90
95
|
|
91
96
|
return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_");
|
@@ -126,16 +131,53 @@ module.exports = {
|
|
126
131
|
}
|
127
132
|
|
128
133
|
/**
|
129
|
-
* Check if function has a underscore
|
134
|
+
* Check if function parameter has a dangling underscore.
|
135
|
+
* @param {ASTNode} node function node to evaluate
|
136
|
+
* @returns {void}
|
137
|
+
* @private
|
138
|
+
*/
|
139
|
+
function checkForDanglingUnderscoreInFunctionParameters(node) {
|
140
|
+
if (!allowFunctionParams) {
|
141
|
+
node.params.forEach(param => {
|
142
|
+
const { type } = param;
|
143
|
+
let nodeToCheck;
|
144
|
+
|
145
|
+
if (type === "RestElement") {
|
146
|
+
nodeToCheck = param.argument;
|
147
|
+
} else if (type === "AssignmentPattern") {
|
148
|
+
nodeToCheck = param.left;
|
149
|
+
} else {
|
150
|
+
nodeToCheck = param;
|
151
|
+
}
|
152
|
+
|
153
|
+
if (nodeToCheck.type === "Identifier") {
|
154
|
+
const identifier = nodeToCheck.name;
|
155
|
+
|
156
|
+
if (hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
|
157
|
+
context.report({
|
158
|
+
node: param,
|
159
|
+
messageId: "unexpectedUnderscore",
|
160
|
+
data: {
|
161
|
+
identifier
|
162
|
+
}
|
163
|
+
});
|
164
|
+
}
|
165
|
+
}
|
166
|
+
});
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Check if function has a dangling underscore
|
130
172
|
* @param {ASTNode} node node to evaluate
|
131
173
|
* @returns {void}
|
132
174
|
* @private
|
133
175
|
*/
|
134
|
-
function
|
135
|
-
if (node.id) {
|
176
|
+
function checkForDanglingUnderscoreInFunction(node) {
|
177
|
+
if (node.type === "FunctionDeclaration" && node.id) {
|
136
178
|
const identifier = node.id.name;
|
137
179
|
|
138
|
-
if (typeof identifier !== "undefined" &&
|
180
|
+
if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
|
139
181
|
context.report({
|
140
182
|
node,
|
141
183
|
messageId: "unexpectedUnderscore",
|
@@ -145,18 +187,19 @@ module.exports = {
|
|
145
187
|
});
|
146
188
|
}
|
147
189
|
}
|
190
|
+
checkForDanglingUnderscoreInFunctionParameters(node);
|
148
191
|
}
|
149
192
|
|
150
193
|
/**
|
151
|
-
* Check if variable expression has a underscore
|
194
|
+
* Check if variable expression has a dangling underscore
|
152
195
|
* @param {ASTNode} node node to evaluate
|
153
196
|
* @returns {void}
|
154
197
|
* @private
|
155
198
|
*/
|
156
|
-
function
|
199
|
+
function checkForDanglingUnderscoreInVariableExpression(node) {
|
157
200
|
const identifier = node.id.name;
|
158
201
|
|
159
|
-
if (typeof identifier !== "undefined" &&
|
202
|
+
if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
|
160
203
|
!isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
|
161
204
|
context.report({
|
162
205
|
node,
|
@@ -169,18 +212,18 @@ module.exports = {
|
|
169
212
|
}
|
170
213
|
|
171
214
|
/**
|
172
|
-
* Check if member expression has a underscore
|
215
|
+
* Check if member expression has a dangling underscore
|
173
216
|
* @param {ASTNode} node node to evaluate
|
174
217
|
* @returns {void}
|
175
218
|
* @private
|
176
219
|
*/
|
177
|
-
function
|
220
|
+
function checkForDanglingUnderscoreInMemberExpression(node) {
|
178
221
|
const identifier = node.property.name,
|
179
222
|
isMemberOfThis = node.object.type === "ThisExpression",
|
180
223
|
isMemberOfSuper = node.object.type === "Super",
|
181
224
|
isMemberOfThisConstructor = isThisConstructorReference(node);
|
182
225
|
|
183
|
-
if (typeof identifier !== "undefined" &&
|
226
|
+
if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
|
184
227
|
!(isMemberOfThis && allowAfterThis) &&
|
185
228
|
!(isMemberOfSuper && allowAfterSuper) &&
|
186
229
|
!(isMemberOfThisConstructor && allowAfterThisConstructor) &&
|
@@ -196,16 +239,16 @@ module.exports = {
|
|
196
239
|
}
|
197
240
|
|
198
241
|
/**
|
199
|
-
* Check if method declaration or method property has a underscore
|
242
|
+
* Check if method declaration or method property has a dangling underscore
|
200
243
|
* @param {ASTNode} node node to evaluate
|
201
244
|
* @returns {void}
|
202
245
|
* @private
|
203
246
|
*/
|
204
|
-
function
|
247
|
+
function checkForDanglingUnderscoreInMethod(node) {
|
205
248
|
const identifier = node.key.name;
|
206
249
|
const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;
|
207
250
|
|
208
|
-
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod &&
|
251
|
+
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
|
209
252
|
context.report({
|
210
253
|
node,
|
211
254
|
messageId: "unexpectedUnderscore",
|
@@ -221,11 +264,13 @@ module.exports = {
|
|
221
264
|
//--------------------------------------------------------------------------
|
222
265
|
|
223
266
|
return {
|
224
|
-
FunctionDeclaration:
|
225
|
-
VariableDeclarator:
|
226
|
-
MemberExpression:
|
227
|
-
MethodDefinition:
|
228
|
-
Property:
|
267
|
+
FunctionDeclaration: checkForDanglingUnderscoreInFunction,
|
268
|
+
VariableDeclarator: checkForDanglingUnderscoreInVariableExpression,
|
269
|
+
MemberExpression: checkForDanglingUnderscoreInMemberExpression,
|
270
|
+
MethodDefinition: checkForDanglingUnderscoreInMethod,
|
271
|
+
Property: checkForDanglingUnderscoreInMethod,
|
272
|
+
FunctionExpression: checkForDanglingUnderscoreInFunction,
|
273
|
+
ArrowFunctionExpression: checkForDanglingUnderscoreInFunction
|
229
274
|
};
|
230
275
|
|
231
276
|
}
|
@@ -8,6 +8,8 @@
|
|
8
8
|
const { escapeRegExp } = require("lodash");
|
9
9
|
const astUtils = require("./utils/ast-utils");
|
10
10
|
|
11
|
+
const CHAR_LIMIT = 40;
|
12
|
+
|
11
13
|
//------------------------------------------------------------------------------
|
12
14
|
// Rule Definition
|
13
15
|
//------------------------------------------------------------------------------
|
@@ -42,12 +44,11 @@ module.exports = {
|
|
42
44
|
],
|
43
45
|
|
44
46
|
messages: {
|
45
|
-
unexpectedComment: "Unexpected '{{matchedTerm}}' comment."
|
47
|
+
unexpectedComment: "Unexpected '{{matchedTerm}}' comment: '{{comment}}'."
|
46
48
|
}
|
47
49
|
},
|
48
50
|
|
49
51
|
create(context) {
|
50
|
-
|
51
52
|
const sourceCode = context.getSourceCode(),
|
52
53
|
configuration = context.options[0] || {},
|
53
54
|
warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
|
@@ -107,7 +108,15 @@ module.exports = {
|
|
107
108
|
* \bTERM\b|\bTERM\b, this checks the entire comment
|
108
109
|
* for the term.
|
109
110
|
*/
|
110
|
-
return new RegExp(
|
111
|
+
return new RegExp(
|
112
|
+
prefix +
|
113
|
+
escaped +
|
114
|
+
suffix +
|
115
|
+
eitherOrWordBoundary +
|
116
|
+
term +
|
117
|
+
wordBoundary,
|
118
|
+
"iu"
|
119
|
+
);
|
111
120
|
}
|
112
121
|
|
113
122
|
const warningRegExps = warningTerms.map(convertToRegExp);
|
@@ -135,18 +144,40 @@ module.exports = {
|
|
135
144
|
* @returns {void} undefined.
|
136
145
|
*/
|
137
146
|
function checkComment(node) {
|
138
|
-
|
147
|
+
const comment = node.value;
|
148
|
+
|
149
|
+
if (
|
150
|
+
astUtils.isDirectiveComment(node) &&
|
151
|
+
selfConfigRegEx.test(comment)
|
152
|
+
) {
|
139
153
|
return;
|
140
154
|
}
|
141
155
|
|
142
|
-
const matches = commentContainsWarningTerm(
|
156
|
+
const matches = commentContainsWarningTerm(comment);
|
143
157
|
|
144
158
|
matches.forEach(matchedTerm => {
|
159
|
+
let commentToDisplay = "";
|
160
|
+
let truncated = false;
|
161
|
+
|
162
|
+
for (const c of comment.trim().split(/\s+/u)) {
|
163
|
+
const tmp = commentToDisplay ? `${commentToDisplay} ${c}` : c;
|
164
|
+
|
165
|
+
if (tmp.length <= CHAR_LIMIT) {
|
166
|
+
commentToDisplay = tmp;
|
167
|
+
} else {
|
168
|
+
truncated = true;
|
169
|
+
break;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
145
173
|
context.report({
|
146
174
|
node,
|
147
175
|
messageId: "unexpectedComment",
|
148
176
|
data: {
|
149
|
-
matchedTerm
|
177
|
+
matchedTerm,
|
178
|
+
comment: `${commentToDisplay}${
|
179
|
+
truncated ? "..." : ""
|
180
|
+
}`
|
150
181
|
}
|
151
182
|
});
|
152
183
|
});
|
@@ -156,7 +187,9 @@ module.exports = {
|
|
156
187
|
Program() {
|
157
188
|
const comments = sourceCode.getAllComments();
|
158
189
|
|
159
|
-
comments
|
190
|
+
comments
|
191
|
+
.filter(token => token.type !== "Shebang")
|
192
|
+
.forEach(checkComment);
|
160
193
|
}
|
161
194
|
};
|
162
195
|
}
|
@@ -151,7 +151,7 @@ module.exports = {
|
|
151
151
|
* @returns {void}
|
152
152
|
*/
|
153
153
|
function prohibit(node) {
|
154
|
-
if (node.operator !== "=") {
|
154
|
+
if (node.operator !== "=" && !astUtils.isLogicalAssignmentOperator(node.operator)) {
|
155
155
|
context.report({
|
156
156
|
node,
|
157
157
|
messageId: "unexpected",
|
@@ -103,6 +103,16 @@ module.exports = {
|
|
103
103
|
/*
|
104
104
|
* If the newly-produced literal would be invalid, (e.g. 0b1234),
|
105
105
|
* or it would yield an incorrect parseInt result for some other reason, don't make a fix.
|
106
|
+
*
|
107
|
+
* If `str` had numeric separators, `+replacement` will evaluate to `NaN` because unary `+`
|
108
|
+
* per the specification doesn't support numeric separators. Thus, the above condition will be `true`
|
109
|
+
* (`NaN !== anything` is always `true`) regardless of the `parseInt(str, radix)` value.
|
110
|
+
* Consequently, no autofixes will be made. This is correct behavior because `parseInt` also
|
111
|
+
* doesn't support numeric separators, but it does parse part of the string before the first `_`,
|
112
|
+
* so the autofix would be invalid:
|
113
|
+
*
|
114
|
+
* parseInt("1_1", 2) // === 1
|
115
|
+
* 0b1_1 // === 3
|
106
116
|
*/
|
107
117
|
return null;
|
108
118
|
}
|
@@ -37,9 +37,11 @@ const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
|
|
37
37
|
// A set of node types that can contain a list of statements
|
38
38
|
const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
|
39
39
|
|
40
|
-
const DECIMAL_INTEGER_PATTERN = /^(0|[1-9]
|
40
|
+
const DECIMAL_INTEGER_PATTERN = /^(0|[1-9](?:_?\d)*)$/u;
|
41
41
|
const OCTAL_ESCAPE_PATTERN = /^(?:[^\\]|\\[^0-7]|\\0(?![0-9]))*\\(?:[1-7]|0[0-9])/u;
|
42
42
|
|
43
|
+
const LOGICAL_ASSIGNMENT_OPERATORS = new Set(["&&=", "||=", "??="]);
|
44
|
+
|
43
45
|
/**
|
44
46
|
* Checks reference if is non initializer and writable.
|
45
47
|
* @param {Reference} reference A reference to check.
|
@@ -722,6 +724,15 @@ function isMixedLogicalAndCoalesceExpressions(left, right) {
|
|
722
724
|
);
|
723
725
|
}
|
724
726
|
|
727
|
+
/**
|
728
|
+
* Checks if the given operator is a logical assignment operator.
|
729
|
+
* @param {string} operator The operator to check.
|
730
|
+
* @returns {boolean} `true` if the operator is a logical assignment operator.
|
731
|
+
*/
|
732
|
+
function isLogicalAssignmentOperator(operator) {
|
733
|
+
return LOGICAL_ASSIGNMENT_OPERATORS.has(operator);
|
734
|
+
}
|
735
|
+
|
725
736
|
//------------------------------------------------------------------------------
|
726
737
|
// Public Interface
|
727
738
|
//------------------------------------------------------------------------------
|
@@ -1228,16 +1239,25 @@ module.exports = {
|
|
1228
1239
|
* @returns {boolean} `true` if this node is a decimal integer.
|
1229
1240
|
* @example
|
1230
1241
|
*
|
1231
|
-
*
|
1232
|
-
* 5
|
1233
|
-
*
|
1234
|
-
*
|
1235
|
-
*
|
1236
|
-
*
|
1237
|
-
*
|
1238
|
-
*
|
1239
|
-
*
|
1240
|
-
*
|
1242
|
+
* 0 // true
|
1243
|
+
* 5 // true
|
1244
|
+
* 50 // true
|
1245
|
+
* 5_000 // true
|
1246
|
+
* 1_234_56 // true
|
1247
|
+
* 5. // false
|
1248
|
+
* .5 // false
|
1249
|
+
* 5.0 // false
|
1250
|
+
* 5.00_00 // false
|
1251
|
+
* 05 // false
|
1252
|
+
* 0x5 // false
|
1253
|
+
* 0b101 // false
|
1254
|
+
* 0b11_01 // false
|
1255
|
+
* 0o5 // false
|
1256
|
+
* 5e0 // false
|
1257
|
+
* 5e1_000 // false
|
1258
|
+
* 5n // false
|
1259
|
+
* 1_000n // false
|
1260
|
+
* '5' // false
|
1241
1261
|
*/
|
1242
1262
|
isDecimalInteger(node) {
|
1243
1263
|
return node.type === "Literal" && typeof node.value === "number" &&
|
@@ -1567,7 +1587,20 @@ module.exports = {
|
|
1567
1587
|
return true; // possibly an error object.
|
1568
1588
|
|
1569
1589
|
case "AssignmentExpression":
|
1570
|
-
|
1590
|
+
if (["=", "&&="].includes(node.operator)) {
|
1591
|
+
return module.exports.couldBeError(node.right);
|
1592
|
+
}
|
1593
|
+
|
1594
|
+
if (["||=", "??="].includes(node.operator)) {
|
1595
|
+
return module.exports.couldBeError(node.left) || module.exports.couldBeError(node.right);
|
1596
|
+
}
|
1597
|
+
|
1598
|
+
/**
|
1599
|
+
* All other assignment operators are mathematical assignment operators (arithmetic or bitwise).
|
1600
|
+
* An assignment expression with a mathematical operator can either evaluate to a primitive value,
|
1601
|
+
* or throw, depending on the operands. Thus, it cannot evaluate to an `Error` object.
|
1602
|
+
*/
|
1603
|
+
return false;
|
1571
1604
|
|
1572
1605
|
case "SequenceExpression": {
|
1573
1606
|
const exprs = node.expressions;
|
@@ -1754,5 +1787,6 @@ module.exports = {
|
|
1754
1787
|
isSpecificId,
|
1755
1788
|
isSpecificMemberAccess,
|
1756
1789
|
equalLiteralValue,
|
1757
|
-
isSameReference
|
1790
|
+
isSameReference,
|
1791
|
+
isLogicalAssignmentOperator
|
1758
1792
|
};
|
@@ -1,3 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* STOP!!! DO NOT MODIFY.
|
3
|
+
*
|
4
|
+
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
+
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
+
* unchanged in order for this work to proceed.
|
7
|
+
*
|
8
|
+
* If you think you need to change this file, please contact @nzakas first.
|
9
|
+
*
|
10
|
+
* Thanks in advance for your cooperation.
|
11
|
+
*/
|
12
|
+
|
1
13
|
/**
|
2
14
|
* @fileoverview Validates configs.
|
3
15
|
* @author Brandon Mills
|
@@ -12,9 +24,9 @@
|
|
12
24
|
const
|
13
25
|
util = require("util"),
|
14
26
|
configSchema = require("../../conf/config-schema"),
|
15
|
-
BuiltInEnvironments = require("
|
27
|
+
BuiltInEnvironments = require("@eslint/eslintrc/conf/environments"),
|
16
28
|
BuiltInRules = require("../rules"),
|
17
|
-
ConfigOps = require("
|
29
|
+
ConfigOps = require("@eslint/eslintrc/lib/shared/config-ops"),
|
18
30
|
{ emitDeprecationWarning } = require("./deprecation-warnings");
|
19
31
|
|
20
32
|
const ajv = require("./ajv")();
|
@@ -1,3 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* STOP!!! DO NOT MODIFY.
|
3
|
+
*
|
4
|
+
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
+
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
+
* unchanged in order for this work to proceed.
|
7
|
+
*
|
8
|
+
* If you think you need to change this file, please contact @nzakas first.
|
9
|
+
*
|
10
|
+
* Thanks in advance for your cooperation.
|
11
|
+
*/
|
12
|
+
|
1
13
|
/**
|
2
14
|
* Utility for resolving a module relative to another module
|
3
15
|
* @author Teddy Katz
|
package/lib/shared/types.js
CHANGED
@@ -21,7 +21,7 @@ module.exports = {};
|
|
21
21
|
/**
|
22
22
|
* @typedef {Object} ParserOptions
|
23
23
|
* @property {EcmaFeatures} [ecmaFeatures] The optional features.
|
24
|
-
* @property {3|5|6|7|8|9|10|11|2015|2016|2017|2018|2019|2020} [ecmaVersion] The ECMAScript version (or revision number).
|
24
|
+
* @property {3|5|6|7|8|9|10|11|12|2015|2016|2017|2018|2019|2020|2021} [ecmaVersion] The ECMAScript version (or revision number).
|
25
25
|
* @property {"script"|"module"} [sourceType] The source code type.
|
26
26
|
*/
|
27
27
|
|
@@ -2,4 +2,4 @@ ESLint couldn't find the config "<%- configName %>" to extend from. Please check
|
|
2
2
|
|
3
3
|
The config "<%- configName %>" was referenced from the config file in "<%- importerName %>".
|
4
4
|
|
5
|
-
If you still have problems, please stop by https://eslint.org/chat to chat with the team.
|
5
|
+
If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.
|