eslint 7.1.0 → 7.4.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/CHANGELOG.md +69 -0
- package/README.md +12 -7
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/config-array-factory.js +1 -1
- package/lib/init/config-initializer.js +91 -74
- package/lib/linter/code-path-analysis/code-path-analyzer.js +2 -2
- package/lib/linter/code-path-analysis/code-path-state.js +34 -12
- package/lib/linter/config-comment-parser.js +1 -1
- package/lib/rule-tester/rule-tester.js +9 -0
- package/lib/rules/array-callback-return.js +21 -10
- package/lib/rules/arrow-body-style.js +2 -2
- package/lib/rules/arrow-parens.js +91 -108
- package/lib/rules/camelcase.js +47 -0
- package/lib/rules/comma-dangle.js +2 -1
- package/lib/rules/curly.js +8 -1
- package/lib/rules/func-call-spacing.js +18 -3
- package/lib/rules/{id-blacklist.js → id-denylist.js} +12 -12
- package/lib/rules/id-match.js +2 -1
- package/lib/rules/index.js +6 -1
- package/lib/rules/key-spacing.js +6 -2
- package/lib/rules/keyword-spacing.js +9 -2
- package/lib/rules/max-lines.js +34 -8
- package/lib/rules/multiline-ternary.js +44 -25
- package/lib/rules/no-control-regex.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +3 -0
- package/lib/rules/no-extra-parens.js +50 -4
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-misleading-character-class.js +1 -1
- package/lib/rules/no-mixed-operators.js +3 -2
- package/lib/rules/no-mixed-spaces-and-tabs.js +14 -6
- package/lib/rules/no-promise-executor-return.js +121 -0
- package/lib/rules/no-regex-spaces.js +1 -1
- package/lib/rules/no-restricted-exports.js +6 -0
- package/lib/rules/no-unneeded-ternary.js +6 -4
- package/lib/rules/no-unreachable-loop.js +150 -0
- package/lib/rules/no-unused-expressions.js +1 -1
- package/lib/rules/no-unused-vars.js +5 -2
- package/lib/rules/no-useless-backreference.js +1 -1
- package/lib/rules/object-property-newline.js +1 -1
- package/lib/rules/operator-linebreak.js +2 -5
- package/lib/rules/padded-blocks.js +2 -1
- package/lib/rules/prefer-named-capture-group.js +1 -1
- package/lib/rules/prefer-regex-literals.js +66 -8
- package/lib/rules/quote-props.js +2 -2
- package/lib/rules/semi-spacing.js +1 -0
- package/lib/rules/template-tag-spacing.js +8 -2
- package/lib/rules/utils/ast-utils.js +55 -3
- package/package.json +6 -6
@@ -644,6 +644,10 @@ class RuleTester {
|
|
644
644
|
assert.ok(item.errors || item.errors === 0,
|
645
645
|
`Did not specify errors for an invalid test of ${ruleName}`);
|
646
646
|
|
647
|
+
if (Array.isArray(item.errors) && item.errors.length === 0) {
|
648
|
+
assert.fail("Invalid cases must have at least one error");
|
649
|
+
}
|
650
|
+
|
647
651
|
const ruleHasMetaMessages = hasOwnProperty(rule, "meta") && hasOwnProperty(rule.meta, "messages");
|
648
652
|
const friendlyIDList = ruleHasMetaMessages ? `[${Object.keys(rule.meta.messages).map(key => `'${key}'`).join(", ")}]` : null;
|
649
653
|
|
@@ -651,6 +655,11 @@ class RuleTester {
|
|
651
655
|
const messages = result.messages;
|
652
656
|
|
653
657
|
if (typeof item.errors === "number") {
|
658
|
+
|
659
|
+
if (item.errors === 0) {
|
660
|
+
assert.fail("Invalid cases must have 'error' value greater than 0");
|
661
|
+
}
|
662
|
+
|
654
663
|
assert.strictEqual(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
|
655
664
|
item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
|
656
665
|
} else {
|
@@ -9,8 +9,6 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const lodash = require("lodash");
|
13
|
-
|
14
12
|
const astUtils = require("./utils/ast-utils");
|
15
13
|
|
16
14
|
//------------------------------------------------------------------------------
|
@@ -43,6 +41,19 @@ function isTargetMethod(node) {
|
|
43
41
|
);
|
44
42
|
}
|
45
43
|
|
44
|
+
/**
|
45
|
+
* Returns a human-legible description of an array method
|
46
|
+
* @param {string} arrayMethodName A method name to fully qualify
|
47
|
+
* @returns {string} the method name prefixed with `Array.` if it is a class method,
|
48
|
+
* or else `Array.prototype.` if it is an instance method.
|
49
|
+
*/
|
50
|
+
function fullMethodName(arrayMethodName) {
|
51
|
+
if (["from", "of", "isArray"].includes(arrayMethodName)) {
|
52
|
+
return "Array.".concat(arrayMethodName);
|
53
|
+
}
|
54
|
+
return "Array.prototype.".concat(arrayMethodName);
|
55
|
+
}
|
56
|
+
|
46
57
|
/**
|
47
58
|
* Checks whether or not a given node is a function expression which is the
|
48
59
|
* callback of an array method, returning the method name.
|
@@ -153,10 +164,10 @@ module.exports = {
|
|
153
164
|
],
|
154
165
|
|
155
166
|
messages: {
|
156
|
-
expectedAtEnd: "
|
157
|
-
expectedInside: "
|
158
|
-
expectedReturnValue: "{{
|
159
|
-
expectedNoReturnValue: "{{
|
167
|
+
expectedAtEnd: "{{arrayMethodName}}() expects a value to be returned at the end of {{name}}.",
|
168
|
+
expectedInside: "{{arrayMethodName}}() expects a return value from {{name}}.",
|
169
|
+
expectedReturnValue: "{{arrayMethodName}}() expects a return value from {{name}}.",
|
170
|
+
expectedNoReturnValue: "{{arrayMethodName}}() expects no useless return value from {{name}}."
|
160
171
|
}
|
161
172
|
},
|
162
173
|
|
@@ -202,14 +213,13 @@ module.exports = {
|
|
202
213
|
}
|
203
214
|
|
204
215
|
if (messageId) {
|
205
|
-
|
216
|
+
const name = astUtils.getFunctionNameWithKind(node);
|
206
217
|
|
207
|
-
name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name;
|
208
218
|
context.report({
|
209
219
|
node,
|
210
220
|
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
|
211
221
|
messageId,
|
212
|
-
data: { name }
|
222
|
+
data: { name, arrayMethodName: fullMethodName(funcInfo.arrayMethodName) }
|
213
223
|
});
|
214
224
|
}
|
215
225
|
}
|
@@ -273,7 +283,8 @@ module.exports = {
|
|
273
283
|
node,
|
274
284
|
messageId,
|
275
285
|
data: {
|
276
|
-
name:
|
286
|
+
name: astUtils.getFunctionNameWithKind(funcInfo.node),
|
287
|
+
arrayMethodName: fullMethodName(funcInfo.arrayMethodName)
|
277
288
|
}
|
278
289
|
});
|
279
290
|
}
|
@@ -136,7 +136,7 @@ module.exports = {
|
|
136
136
|
|
137
137
|
context.report({
|
138
138
|
node,
|
139
|
-
loc: arrowBody.loc
|
139
|
+
loc: arrowBody.loc,
|
140
140
|
messageId,
|
141
141
|
fix(fixer) {
|
142
142
|
const fixes = [];
|
@@ -201,7 +201,7 @@ module.exports = {
|
|
201
201
|
if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) {
|
202
202
|
context.report({
|
203
203
|
node,
|
204
|
-
loc: arrowBody.loc
|
204
|
+
loc: arrowBody.loc,
|
205
205
|
messageId: "expectedBlock",
|
206
206
|
fix(fixer) {
|
207
207
|
const fixes = [];
|
@@ -15,15 +15,12 @@ const astUtils = require("./utils/ast-utils");
|
|
15
15
|
//------------------------------------------------------------------------------
|
16
16
|
|
17
17
|
/**
|
18
|
-
*
|
19
|
-
* @param {ASTNode} node
|
20
|
-
* @returns {
|
18
|
+
* Determines if the given arrow function has block body.
|
19
|
+
* @param {ASTNode} node `ArrowFunctionExpression` node.
|
20
|
+
* @returns {boolean} `true` if the function has block body.
|
21
21
|
*/
|
22
|
-
function
|
23
|
-
return
|
24
|
-
start: node.params[0].loc.start,
|
25
|
-
end: node.params[node.params.length - 1].loc.end
|
26
|
-
};
|
22
|
+
function hasBlockBody(node) {
|
23
|
+
return node.body.type === "BlockStatement";
|
27
24
|
}
|
28
25
|
|
29
26
|
//------------------------------------------------------------------------------
|
@@ -75,126 +72,112 @@ module.exports = {
|
|
75
72
|
const sourceCode = context.getSourceCode();
|
76
73
|
|
77
74
|
/**
|
78
|
-
*
|
79
|
-
*
|
80
|
-
* @
|
75
|
+
* Finds opening paren of parameters for the given arrow function, if it exists.
|
76
|
+
* It is assumed that the given arrow function has exactly one parameter.
|
77
|
+
* @param {ASTNode} node `ArrowFunctionExpression` node.
|
78
|
+
* @returns {Token|null} the opening paren, or `null` if the given arrow function doesn't have parens of parameters.
|
81
79
|
*/
|
82
|
-
function
|
83
|
-
const
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
function fixParamsWithParenthesis(fixer) {
|
92
|
-
const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
|
93
|
-
|
94
|
-
/*
|
95
|
-
* ES8 allows Trailing commas in function parameter lists and calls
|
96
|
-
* https://github.com/eslint/eslint/issues/8834
|
97
|
-
*/
|
98
|
-
const closingParenToken = sourceCode.getTokenAfter(paramToken, astUtils.isClosingParenToken);
|
99
|
-
const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
|
100
|
-
const shouldAddSpaceForAsync = asyncToken && (asyncToken.range[1] === firstTokenOfParam.range[0]);
|
101
|
-
|
102
|
-
return fixer.replaceTextRange([
|
103
|
-
firstTokenOfParam.range[0],
|
104
|
-
closingParenToken.range[1]
|
105
|
-
], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
|
80
|
+
function findOpeningParenOfParams(node) {
|
81
|
+
const tokenBeforeParams = sourceCode.getTokenBefore(node.params[0]);
|
82
|
+
|
83
|
+
if (
|
84
|
+
tokenBeforeParams &&
|
85
|
+
astUtils.isOpeningParenToken(tokenBeforeParams) &&
|
86
|
+
node.range[0] <= tokenBeforeParams.range[0]
|
87
|
+
) {
|
88
|
+
return tokenBeforeParams;
|
106
89
|
}
|
107
90
|
|
108
|
-
|
109
|
-
|
110
|
-
* @returns {boolean} `true` if there are comments inside of parens, else `false`
|
111
|
-
*/
|
112
|
-
function hasCommentsInParens() {
|
113
|
-
if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
|
114
|
-
const closingParenToken = sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken);
|
91
|
+
return null;
|
92
|
+
}
|
115
93
|
|
116
|
-
|
117
|
-
|
118
|
-
|
94
|
+
/**
|
95
|
+
* Finds closing paren of parameters for the given arrow function.
|
96
|
+
* It is assumed that the given arrow function has parens of parameters and that it has exactly one parameter.
|
97
|
+
* @param {ASTNode} node `ArrowFunctionExpression` node.
|
98
|
+
* @returns {Token} the closing paren of parameters.
|
99
|
+
*/
|
100
|
+
function getClosingParenOfParams(node) {
|
101
|
+
return sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken);
|
102
|
+
}
|
119
103
|
|
120
|
-
|
104
|
+
/**
|
105
|
+
* Determines whether the given arrow function has comments inside parens of parameters.
|
106
|
+
* It is assumed that the given arrow function has parens of parameters.
|
107
|
+
* @param {ASTNode} node `ArrowFunctionExpression` node.
|
108
|
+
* @param {Token} openingParen Opening paren of parameters.
|
109
|
+
* @returns {boolean} `true` if the function has at least one comment inside of parens of parameters.
|
110
|
+
*/
|
111
|
+
function hasCommentsInParensOfParams(node, openingParen) {
|
112
|
+
return sourceCode.commentsExistBetween(openingParen, getClosingParenOfParams(node));
|
113
|
+
}
|
121
114
|
|
122
|
-
|
123
|
-
|
124
|
-
|
115
|
+
/**
|
116
|
+
* Determines whether the given arrow function has unexpected tokens before opening paren of parameters,
|
117
|
+
* in which case it will be assumed that the existing parens of parameters are necessary.
|
118
|
+
* Only tokens within the range of the arrow function (tokens that are part of the arrow function) are taken into account.
|
119
|
+
* Example: <T>(a) => b
|
120
|
+
* @param {ASTNode} node `ArrowFunctionExpression` node.
|
121
|
+
* @param {Token} openingParen Opening paren of parameters.
|
122
|
+
* @returns {boolean} `true` if the function has at least one unexpected token.
|
123
|
+
*/
|
124
|
+
function hasUnexpectedTokensBeforeOpeningParen(node, openingParen) {
|
125
|
+
const expectedCount = node.async ? 1 : 0;
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
requireForBlockBody &&
|
129
|
-
node.params[0].type === "Identifier" &&
|
130
|
-
!node.params[0].typeAnnotation &&
|
131
|
-
node.body.type !== "BlockStatement" &&
|
132
|
-
!node.returnType
|
133
|
-
) {
|
134
|
-
if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
|
135
|
-
context.report({
|
136
|
-
node,
|
137
|
-
messageId: "unexpectedParensInline",
|
138
|
-
loc: getLocation(node),
|
139
|
-
fix: fixParamsWithParenthesis
|
140
|
-
});
|
141
|
-
}
|
142
|
-
return;
|
143
|
-
}
|
127
|
+
return sourceCode.getFirstToken(node, { skip: expectedCount }) !== openingParen;
|
128
|
+
}
|
144
129
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
node,
|
152
|
-
messageId: "expectedParensBlock",
|
153
|
-
loc: getLocation(node),
|
154
|
-
fix(fixer) {
|
155
|
-
return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
|
156
|
-
}
|
157
|
-
});
|
158
|
-
}
|
159
|
-
return;
|
160
|
-
}
|
130
|
+
return {
|
131
|
+
"ArrowFunctionExpression[params.length=1]"(node) {
|
132
|
+
const shouldHaveParens = !asNeeded || requireForBlockBody && hasBlockBody(node);
|
133
|
+
const openingParen = findOpeningParenOfParams(node);
|
134
|
+
const hasParens = openingParen !== null;
|
135
|
+
const [param] = node.params;
|
161
136
|
|
162
|
-
|
163
|
-
if (asNeeded &&
|
164
|
-
node.params[0].type === "Identifier" &&
|
165
|
-
!node.params[0].typeAnnotation &&
|
166
|
-
!node.returnType
|
167
|
-
) {
|
168
|
-
if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
|
137
|
+
if (shouldHaveParens && !hasParens) {
|
169
138
|
context.report({
|
170
139
|
node,
|
171
|
-
messageId: "
|
172
|
-
loc:
|
173
|
-
fix
|
140
|
+
messageId: requireForBlockBody ? "expectedParensBlock" : "expectedParens",
|
141
|
+
loc: param.loc,
|
142
|
+
*fix(fixer) {
|
143
|
+
yield fixer.insertTextBefore(param, "(");
|
144
|
+
yield fixer.insertTextAfter(param, ")");
|
145
|
+
}
|
174
146
|
});
|
175
147
|
}
|
176
|
-
return;
|
177
|
-
}
|
178
148
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
149
|
+
if (
|
150
|
+
!shouldHaveParens &&
|
151
|
+
hasParens &&
|
152
|
+
param.type === "Identifier" &&
|
153
|
+
!param.typeAnnotation &&
|
154
|
+
!node.returnType &&
|
155
|
+
!hasCommentsInParensOfParams(node, openingParen) &&
|
156
|
+
!hasUnexpectedTokensBeforeOpeningParen(node, openingParen)
|
157
|
+
) {
|
184
158
|
context.report({
|
185
159
|
node,
|
186
|
-
messageId: "
|
187
|
-
loc:
|
188
|
-
fix(fixer) {
|
189
|
-
|
160
|
+
messageId: requireForBlockBody ? "unexpectedParensInline" : "unexpectedParens",
|
161
|
+
loc: param.loc,
|
162
|
+
*fix(fixer) {
|
163
|
+
const tokenBeforeOpeningParen = sourceCode.getTokenBefore(openingParen);
|
164
|
+
const closingParen = getClosingParenOfParams(node);
|
165
|
+
|
166
|
+
if (
|
167
|
+
tokenBeforeOpeningParen &&
|
168
|
+
tokenBeforeOpeningParen.range[1] === openingParen.range[0] &&
|
169
|
+
!astUtils.canTokensBeAdjacent(tokenBeforeOpeningParen, sourceCode.getFirstToken(param))
|
170
|
+
) {
|
171
|
+
yield fixer.insertTextBefore(openingParen, " ");
|
172
|
+
}
|
173
|
+
|
174
|
+
// remove parens, whitespace inside parens, and possible trailing comma
|
175
|
+
yield fixer.removeRange([openingParen.range[0], param.range[0]]);
|
176
|
+
yield fixer.removeRange([param.range[1], closingParen.range[1]]);
|
190
177
|
}
|
191
178
|
});
|
192
179
|
}
|
193
180
|
}
|
194
|
-
}
|
195
|
-
|
196
|
-
return {
|
197
|
-
"ArrowFunctionExpression[params.length=1]": parens
|
198
181
|
};
|
199
182
|
}
|
200
183
|
};
|
package/lib/rules/camelcase.js
CHANGED
@@ -32,6 +32,10 @@ module.exports = {
|
|
32
32
|
type: "boolean",
|
33
33
|
default: false
|
34
34
|
},
|
35
|
+
ignoreGlobals: {
|
36
|
+
type: "boolean",
|
37
|
+
default: false
|
38
|
+
},
|
35
39
|
properties: {
|
36
40
|
enum: ["always", "never"]
|
37
41
|
},
|
@@ -61,8 +65,11 @@ module.exports = {
|
|
61
65
|
let properties = options.properties || "";
|
62
66
|
const ignoreDestructuring = options.ignoreDestructuring;
|
63
67
|
const ignoreImports = options.ignoreImports;
|
68
|
+
const ignoreGlobals = options.ignoreGlobals;
|
64
69
|
const allow = options.allow || [];
|
65
70
|
|
71
|
+
let globalScope;
|
72
|
+
|
66
73
|
if (properties !== "always" && properties !== "never") {
|
67
74
|
properties = "always";
|
68
75
|
}
|
@@ -159,6 +166,37 @@ module.exports = {
|
|
159
166
|
return false;
|
160
167
|
}
|
161
168
|
|
169
|
+
/**
|
170
|
+
* Checks whether the given node represents a reference to a global variable that is not declared in the source code.
|
171
|
+
* These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
|
172
|
+
* @param {ASTNode} node `Identifier` node to check.
|
173
|
+
* @returns {boolean} `true` if the node is a reference to a global variable.
|
174
|
+
*/
|
175
|
+
function isReferenceToGlobalVariable(node) {
|
176
|
+
const variable = globalScope.set.get(node.name);
|
177
|
+
|
178
|
+
return variable && variable.defs.length === 0 &&
|
179
|
+
variable.references.some(ref => ref.identifier === node);
|
180
|
+
}
|
181
|
+
|
182
|
+
/**
|
183
|
+
* Checks whether the given node represents a reference to a property of an object in an object literal expression.
|
184
|
+
* This allows to differentiate between a global variable that is allowed to be used as a reference, and the key
|
185
|
+
* of the expressed object (which shouldn't be allowed).
|
186
|
+
* @param {ASTNode} node `Identifier` node to check.
|
187
|
+
* @returns {boolean} `true` if the node is a property name of an object literal expression
|
188
|
+
*/
|
189
|
+
function isPropertyNameInObjectLiteral(node) {
|
190
|
+
const parent = node.parent;
|
191
|
+
|
192
|
+
return (
|
193
|
+
parent.type === "Property" &&
|
194
|
+
parent.parent.type === "ObjectExpression" &&
|
195
|
+
!parent.computed &&
|
196
|
+
parent.key === node
|
197
|
+
);
|
198
|
+
}
|
199
|
+
|
162
200
|
/**
|
163
201
|
* Reports an AST node as a rule violation.
|
164
202
|
* @param {ASTNode} node The node to report.
|
@@ -174,6 +212,10 @@ module.exports = {
|
|
174
212
|
|
175
213
|
return {
|
176
214
|
|
215
|
+
Program() {
|
216
|
+
globalScope = context.getScope();
|
217
|
+
},
|
218
|
+
|
177
219
|
Identifier(node) {
|
178
220
|
|
179
221
|
/*
|
@@ -189,6 +231,11 @@ module.exports = {
|
|
189
231
|
return;
|
190
232
|
}
|
191
233
|
|
234
|
+
// Check if it's a global variable
|
235
|
+
if (ignoreGlobals && isReferenceToGlobalVariable(node) && !isPropertyNameInObjectLiteral(node)) {
|
236
|
+
return;
|
237
|
+
}
|
238
|
+
|
192
239
|
// MemberExpressions get special rules
|
193
240
|
if (node.parent.type === "MemberExpression") {
|
194
241
|
|
package/lib/rules/curly.js
CHANGED
@@ -457,11 +457,18 @@ module.exports = {
|
|
457
457
|
|
458
458
|
return {
|
459
459
|
IfStatement(node) {
|
460
|
-
|
460
|
+
const parent = node.parent;
|
461
|
+
const isElseIf = parent.type === "IfStatement" && parent.alternate === node;
|
462
|
+
|
463
|
+
if (!isElseIf) {
|
464
|
+
|
465
|
+
// This is a top `if`, check the whole `if-else-if` chain
|
461
466
|
prepareIfChecks(node).forEach(preparedCheck => {
|
462
467
|
preparedCheck.check();
|
463
468
|
});
|
464
469
|
}
|
470
|
+
|
471
|
+
// Skip `else if`, it's already checked (when the top `if` was visited)
|
465
472
|
},
|
466
473
|
|
467
474
|
WhileStatement(node) {
|
@@ -116,7 +116,13 @@ module.exports = {
|
|
116
116
|
if (never && hasWhitespace) {
|
117
117
|
context.report({
|
118
118
|
node,
|
119
|
-
loc:
|
119
|
+
loc: {
|
120
|
+
start: leftToken.loc.end,
|
121
|
+
end: {
|
122
|
+
line: rightToken.loc.start.line,
|
123
|
+
column: rightToken.loc.start.column - 1
|
124
|
+
}
|
125
|
+
},
|
120
126
|
messageId: "unexpectedWhitespace",
|
121
127
|
fix(fixer) {
|
122
128
|
|
@@ -134,7 +140,13 @@ module.exports = {
|
|
134
140
|
} else if (!never && !hasWhitespace) {
|
135
141
|
context.report({
|
136
142
|
node,
|
137
|
-
loc:
|
143
|
+
loc: {
|
144
|
+
start: {
|
145
|
+
line: leftToken.loc.end.line,
|
146
|
+
column: leftToken.loc.end.column - 1
|
147
|
+
},
|
148
|
+
end: rightToken.loc.start
|
149
|
+
},
|
138
150
|
messageId: "missing",
|
139
151
|
fix(fixer) {
|
140
152
|
return fixer.insertTextBefore(rightToken, " ");
|
@@ -143,7 +155,10 @@ module.exports = {
|
|
143
155
|
} else if (!never && !allowNewlines && hasNewline) {
|
144
156
|
context.report({
|
145
157
|
node,
|
146
|
-
loc:
|
158
|
+
loc: {
|
159
|
+
start: leftToken.loc.end,
|
160
|
+
end: rightToken.loc.start
|
161
|
+
},
|
147
162
|
messageId: "unexpectedNewline",
|
148
163
|
fix(fixer) {
|
149
164
|
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule that warns when identifier names that are
|
3
|
-
*
|
3
|
+
* specified in the configuration are used.
|
4
4
|
* @author Keith Cirkel (http://keithcirkel.co.uk)
|
5
5
|
*/
|
6
6
|
|
@@ -117,7 +117,7 @@ module.exports = {
|
|
117
117
|
description: "disallow specified identifiers",
|
118
118
|
category: "Stylistic Issues",
|
119
119
|
recommended: false,
|
120
|
-
url: "https://eslint.org/docs/rules/id-
|
120
|
+
url: "https://eslint.org/docs/rules/id-denylist"
|
121
121
|
},
|
122
122
|
|
123
123
|
schema: {
|
@@ -128,25 +128,25 @@ module.exports = {
|
|
128
128
|
uniqueItems: true
|
129
129
|
},
|
130
130
|
messages: {
|
131
|
-
|
131
|
+
restricted: "Identifier '{{name}}' is restricted."
|
132
132
|
}
|
133
133
|
},
|
134
134
|
|
135
135
|
create(context) {
|
136
136
|
|
137
|
-
const
|
137
|
+
const denyList = new Set(context.options);
|
138
138
|
const reportedNodes = new Set();
|
139
139
|
|
140
140
|
let globalScope;
|
141
141
|
|
142
142
|
/**
|
143
|
-
* Checks whether the given name is
|
143
|
+
* Checks whether the given name is restricted.
|
144
144
|
* @param {string} name The name to check.
|
145
|
-
* @returns {boolean} `true` if the name is
|
145
|
+
* @returns {boolean} `true` if the name is restricted.
|
146
146
|
* @private
|
147
147
|
*/
|
148
|
-
function
|
149
|
-
return
|
148
|
+
function isRestricted(name) {
|
149
|
+
return denyList.has(name);
|
150
150
|
}
|
151
151
|
|
152
152
|
/**
|
@@ -172,8 +172,8 @@ module.exports = {
|
|
172
172
|
|
173
173
|
/*
|
174
174
|
* Member access has special rules for checking property names.
|
175
|
-
* Read access to a property with a
|
176
|
-
* Write access isn't allowed, because it potentially creates a new property with a
|
175
|
+
* Read access to a property with a restricted name is allowed, because it can be on an object that user has no control over.
|
176
|
+
* Write access isn't allowed, because it potentially creates a new property with a restricted name.
|
177
177
|
*/
|
178
178
|
if (
|
179
179
|
parent.type === "MemberExpression" &&
|
@@ -205,7 +205,7 @@ module.exports = {
|
|
205
205
|
if (!reportedNodes.has(node)) {
|
206
206
|
context.report({
|
207
207
|
node,
|
208
|
-
messageId: "
|
208
|
+
messageId: "restricted",
|
209
209
|
data: {
|
210
210
|
name: node.name
|
211
211
|
}
|
@@ -221,7 +221,7 @@ module.exports = {
|
|
221
221
|
},
|
222
222
|
|
223
223
|
Identifier(node) {
|
224
|
-
if (
|
224
|
+
if (isRestricted(node.name) && shouldCheck(node)) {
|
225
225
|
report(node);
|
226
226
|
}
|
227
227
|
}
|
package/lib/rules/id-match.js
CHANGED
package/lib/rules/index.js
CHANGED
@@ -56,7 +56,10 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
56
56
|
"grouped-accessor-pairs": () => require("./grouped-accessor-pairs"),
|
57
57
|
"guard-for-in": () => require("./guard-for-in"),
|
58
58
|
"handle-callback-err": () => require("./handle-callback-err"),
|
59
|
-
|
59
|
+
|
60
|
+
// Renamed to id-denylist.
|
61
|
+
"id-blacklist": () => require("./id-denylist"),
|
62
|
+
"id-denylist": () => require("./id-denylist"),
|
60
63
|
"id-length": () => require("./id-length"),
|
61
64
|
"id-match": () => require("./id-match"),
|
62
65
|
"implicit-arrow-linebreak": () => require("./implicit-arrow-linebreak"),
|
@@ -176,6 +179,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
176
179
|
"no-plusplus": () => require("./no-plusplus"),
|
177
180
|
"no-process-env": () => require("./no-process-env"),
|
178
181
|
"no-process-exit": () => require("./no-process-exit"),
|
182
|
+
"no-promise-executor-return": () => require("./no-promise-executor-return"),
|
179
183
|
"no-proto": () => require("./no-proto"),
|
180
184
|
"no-prototype-builtins": () => require("./no-prototype-builtins"),
|
181
185
|
"no-redeclare": () => require("./no-redeclare"),
|
@@ -212,6 +216,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
212
216
|
"no-unmodified-loop-condition": () => require("./no-unmodified-loop-condition"),
|
213
217
|
"no-unneeded-ternary": () => require("./no-unneeded-ternary"),
|
214
218
|
"no-unreachable": () => require("./no-unreachable"),
|
219
|
+
"no-unreachable-loop": () => require("./no-unreachable-loop"),
|
215
220
|
"no-unsafe-finally": () => require("./no-unsafe-finally"),
|
216
221
|
"no-unsafe-negation": () => require("./no-unsafe-negation"),
|
217
222
|
"no-unused-expressions": () => require("./no-unused-expressions"),
|
package/lib/rules/key-spacing.js
CHANGED
@@ -433,11 +433,15 @@ module.exports = {
|
|
433
433
|
tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
|
434
434
|
tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
|
435
435
|
isKeySide = side === "key",
|
436
|
-
locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
|
437
436
|
isExtra = diff > 0,
|
438
437
|
diffAbs = Math.abs(diff),
|
439
438
|
spaces = Array(diffAbs + 1).join(" ");
|
440
439
|
|
440
|
+
const locStart = isKeySide ? tokenBeforeColon.loc.end : nextColon.loc.start;
|
441
|
+
const locEnd = isKeySide ? nextColon.loc.start : tokenAfterColon.loc.start;
|
442
|
+
const missingLoc = isKeySide ? tokenBeforeColon.loc : tokenAfterColon.loc;
|
443
|
+
const loc = isExtra ? { start: locStart, end: locEnd } : missingLoc;
|
444
|
+
|
441
445
|
if ((
|
442
446
|
diff && mode === "strict" ||
|
443
447
|
diff < 0 && mode === "minimum" ||
|
@@ -482,7 +486,7 @@ module.exports = {
|
|
482
486
|
|
483
487
|
context.report({
|
484
488
|
node: property[side],
|
485
|
-
loc
|
489
|
+
loc,
|
486
490
|
messageId,
|
487
491
|
data: {
|
488
492
|
computed: property.computed ? "computed " : "",
|