eslint 6.2.0 → 6.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 +66 -0
- package/README.md +8 -2
- package/conf/config-schema.js +1 -0
- package/conf/default-cli-options.js +1 -1
- package/lib/cli-engine/config-array/config-array.js +6 -0
- package/lib/cli-engine/config-array/extracted-config.js +6 -0
- package/lib/cli-engine/config-array/override-tester.js +2 -2
- package/lib/cli-engine/config-array-factory.js +2 -0
- package/lib/cli-engine/formatters/stylish.js +2 -1
- package/lib/init/config-initializer.js +29 -0
- package/lib/init/npm-utils.js +8 -8
- package/lib/linter/apply-disable-directives.js +17 -9
- package/lib/linter/linter.js +23 -3
- package/lib/options.js +1 -1
- package/lib/rules/accessor-pairs.js +51 -11
- package/lib/rules/computed-property-spacing.js +18 -1
- package/lib/rules/default-param-last.js +61 -0
- package/lib/rules/eqeqeq.js +7 -19
- package/lib/rules/func-name-matching.js +1 -0
- package/lib/rules/function-paren-newline.js +2 -2
- package/lib/rules/indent.js +16 -6
- package/lib/rules/index.js +3 -0
- package/lib/rules/no-extra-boolean-cast.js +12 -2
- package/lib/rules/no-extra-parens.js +8 -1
- package/lib/rules/no-import-assign.js +238 -0
- package/lib/rules/no-lone-blocks.js +6 -1
- package/lib/rules/no-obj-calls.js +29 -9
- package/lib/rules/no-octal-escape.js +14 -8
- package/lib/rules/no-self-assign.js +17 -6
- package/lib/rules/no-sequences.js +2 -2
- package/lib/rules/no-unsafe-negation.js +2 -10
- package/lib/rules/object-curly-spacing.js +1 -1
- package/lib/rules/object-shorthand.js +35 -9
- package/lib/rules/prefer-regex-literals.js +125 -0
- package/lib/rules/quotes.js +6 -0
- package/lib/rules/space-before-function-paren.js +12 -1
- package/lib/rules/space-in-parens.js +77 -71
- package/lib/rules/yoda.js +11 -2
- package/lib/shared/types.js +2 -0
- package/package.json +3 -3
package/lib/rules/eqeqeq.js
CHANGED
@@ -116,18 +116,6 @@ module.exports = {
|
|
116
116
|
return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
|
117
117
|
}
|
118
118
|
|
119
|
-
/**
|
120
|
-
* Gets the location (line and column) of the binary expression's operator
|
121
|
-
* @param {ASTNode} node The binary expression node to check
|
122
|
-
* @returns {Object} { line, column } location of operator
|
123
|
-
* @private
|
124
|
-
*/
|
125
|
-
function getOperatorLocation(node) {
|
126
|
-
const opToken = sourceCode.getTokenAfter(node.left);
|
127
|
-
|
128
|
-
return { line: opToken.loc.start.line, column: opToken.loc.start.column };
|
129
|
-
}
|
130
|
-
|
131
119
|
/**
|
132
120
|
* Reports a message for this rule.
|
133
121
|
* @param {ASTNode} node The binary expression node that was checked
|
@@ -136,21 +124,21 @@ module.exports = {
|
|
136
124
|
* @private
|
137
125
|
*/
|
138
126
|
function report(node, expectedOperator) {
|
127
|
+
const operatorToken = sourceCode.getFirstTokenBetween(
|
128
|
+
node.left,
|
129
|
+
node.right,
|
130
|
+
token => token.value === node.operator
|
131
|
+
);
|
132
|
+
|
139
133
|
context.report({
|
140
134
|
node,
|
141
|
-
loc:
|
135
|
+
loc: operatorToken.loc,
|
142
136
|
messageId: "unexpected",
|
143
137
|
data: { expectedOperator, actualOperator: node.operator },
|
144
138
|
fix(fixer) {
|
145
139
|
|
146
140
|
// If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
|
147
141
|
if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
|
148
|
-
const operatorToken = sourceCode.getFirstTokenBetween(
|
149
|
-
node.left,
|
150
|
-
node.right,
|
151
|
-
token => token.value === node.operator
|
152
|
-
);
|
153
|
-
|
154
142
|
return fixer.replaceText(operatorToken, expectedOperator);
|
155
143
|
}
|
156
144
|
return null;
|
@@ -51,8 +51,8 @@ module.exports = {
|
|
51
51
|
expectedBefore: "Expected newline before ')'.",
|
52
52
|
expectedAfter: "Expected newline after '('.",
|
53
53
|
expectedBetween: "Expected newline between arguments/params.",
|
54
|
-
unexpectedBefore: "Unexpected newline before '
|
55
|
-
unexpectedAfter: "Unexpected newline after '
|
54
|
+
unexpectedBefore: "Unexpected newline before ')'.",
|
55
|
+
unexpectedAfter: "Unexpected newline after '('."
|
56
56
|
}
|
57
57
|
},
|
58
58
|
|
package/lib/rules/indent.js
CHANGED
@@ -1588,18 +1588,23 @@ module.exports = {
|
|
1588
1588
|
return;
|
1589
1589
|
}
|
1590
1590
|
|
1591
|
-
// If the token matches the expected expected indentation, don't report it.
|
1592
|
-
if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
|
1593
|
-
return;
|
1594
|
-
}
|
1595
|
-
|
1596
1591
|
if (astUtils.isCommentToken(firstTokenOfLine)) {
|
1597
1592
|
const tokenBefore = precedingTokens.get(firstTokenOfLine);
|
1598
1593
|
const tokenAfter = tokenBefore ? sourceCode.getTokenAfter(tokenBefore) : sourceCode.ast.tokens[0];
|
1599
|
-
|
1600
1594
|
const mayAlignWithBefore = tokenBefore && !hasBlankLinesBetween(tokenBefore, firstTokenOfLine);
|
1601
1595
|
const mayAlignWithAfter = tokenAfter && !hasBlankLinesBetween(firstTokenOfLine, tokenAfter);
|
1602
1596
|
|
1597
|
+
/*
|
1598
|
+
* If a comment precedes a line that begins with a semicolon token, align to that token, i.e.
|
1599
|
+
*
|
1600
|
+
* let foo
|
1601
|
+
* // comment
|
1602
|
+
* ;(async () => {})()
|
1603
|
+
*/
|
1604
|
+
if (tokenAfter && astUtils.isSemicolonToken(tokenAfter) && !astUtils.isTokenOnSameLine(firstTokenOfLine, tokenAfter)) {
|
1605
|
+
offsets.setDesiredOffset(firstTokenOfLine, tokenAfter, 0);
|
1606
|
+
}
|
1607
|
+
|
1603
1608
|
// If a comment matches the expected indentation of the token immediately before or after, don't report it.
|
1604
1609
|
if (
|
1605
1610
|
mayAlignWithBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) ||
|
@@ -1609,6 +1614,11 @@ module.exports = {
|
|
1609
1614
|
}
|
1610
1615
|
}
|
1611
1616
|
|
1617
|
+
// If the token matches the expected indentation, don't report it.
|
1618
|
+
if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
|
1619
|
+
return;
|
1620
|
+
}
|
1621
|
+
|
1612
1622
|
// Otherwise, report the token/comment.
|
1613
1623
|
report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine));
|
1614
1624
|
});
|
package/lib/rules/index.js
CHANGED
@@ -37,6 +37,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
37
37
|
"constructor-super": () => require("./constructor-super"),
|
38
38
|
curly: () => require("./curly"),
|
39
39
|
"default-case": () => require("./default-case"),
|
40
|
+
"default-param-last": () => require("./default-param-last"),
|
40
41
|
"dot-location": () => require("./dot-location"),
|
41
42
|
"dot-notation": () => require("./dot-notation"),
|
42
43
|
"eol-last": () => require("./eol-last"),
|
@@ -131,6 +132,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
131
132
|
"no-implicit-coercion": () => require("./no-implicit-coercion"),
|
132
133
|
"no-implicit-globals": () => require("./no-implicit-globals"),
|
133
134
|
"no-implied-eval": () => require("./no-implied-eval"),
|
135
|
+
"no-import-assign": () => require("./no-import-assign"),
|
134
136
|
"no-inline-comments": () => require("./no-inline-comments"),
|
135
137
|
"no-inner-declarations": () => require("./no-inner-declarations"),
|
136
138
|
"no-invalid-regexp": () => require("./no-invalid-regexp"),
|
@@ -241,6 +243,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
241
243
|
"prefer-object-spread": () => require("./prefer-object-spread"),
|
242
244
|
"prefer-promise-reject-errors": () => require("./prefer-promise-reject-errors"),
|
243
245
|
"prefer-reflect": () => require("./prefer-reflect"),
|
246
|
+
"prefer-regex-literals": () => require("./prefer-regex-literals"),
|
244
247
|
"prefer-rest-params": () => require("./prefer-rest-params"),
|
245
248
|
"prefer-spread": () => require("./prefer-spread"),
|
246
249
|
"prefer-template": () => require("./prefer-template"),
|
@@ -96,13 +96,23 @@ module.exports = {
|
|
96
96
|
grandparent.callee.name === "Boolean")
|
97
97
|
) {
|
98
98
|
context.report({
|
99
|
-
node,
|
99
|
+
node: parent,
|
100
100
|
messageId: "unexpectedNegation",
|
101
101
|
fix: fixer => {
|
102
102
|
if (hasCommentsInside(parent)) {
|
103
103
|
return null;
|
104
104
|
}
|
105
|
-
|
105
|
+
|
106
|
+
let prefix = "";
|
107
|
+
const tokenBefore = sourceCode.getTokenBefore(parent);
|
108
|
+
const firstReplacementToken = sourceCode.getFirstToken(node.argument);
|
109
|
+
|
110
|
+
if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
|
111
|
+
!astUtils.canTokensBeAdjacent(tokenBefore, firstReplacementToken)) {
|
112
|
+
prefix = " ";
|
113
|
+
}
|
114
|
+
|
115
|
+
return fixer.replaceText(parent, prefix + sourceCode.getText(node.argument));
|
106
116
|
}
|
107
117
|
});
|
108
118
|
}
|
@@ -49,7 +49,8 @@ module.exports = {
|
|
49
49
|
nestedBinaryExpressions: { type: "boolean" },
|
50
50
|
returnAssign: { type: "boolean" },
|
51
51
|
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] },
|
52
|
-
enforceForArrowConditionals: { type: "boolean" }
|
52
|
+
enforceForArrowConditionals: { type: "boolean" },
|
53
|
+
enforceForSequenceExpressions: { type: "boolean" }
|
53
54
|
},
|
54
55
|
additionalProperties: false
|
55
56
|
}
|
@@ -77,6 +78,8 @@ module.exports = {
|
|
77
78
|
const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX;
|
78
79
|
const IGNORE_ARROW_CONDITIONALS = ALL_NODES && context.options[1] &&
|
79
80
|
context.options[1].enforceForArrowConditionals === false;
|
81
|
+
const IGNORE_SEQUENCE_EXPRESSIONS = ALL_NODES && context.options[1] &&
|
82
|
+
context.options[1].enforceForSequenceExpressions === false;
|
80
83
|
|
81
84
|
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
|
82
85
|
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
|
@@ -115,6 +118,10 @@ module.exports = {
|
|
115
118
|
}
|
116
119
|
}
|
117
120
|
|
121
|
+
if (node.type === "SequenceExpression" && IGNORE_SEQUENCE_EXPRESSIONS) {
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
|
118
125
|
return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
119
126
|
}
|
120
127
|
|
@@ -0,0 +1,238 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to flag updates of imported bindings.
|
3
|
+
* @author Toru Nagashima <https://github.com/mysticatea>
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Helpers
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const { findVariable, getPropertyName } = require("eslint-utils");
|
13
|
+
|
14
|
+
const MutationMethods = {
|
15
|
+
Object: new Set([
|
16
|
+
"assign", "defineProperties", "defineProperty", "freeze",
|
17
|
+
"setPrototypeOf"
|
18
|
+
]),
|
19
|
+
Reflect: new Set([
|
20
|
+
"defineProperty", "deleteProperty", "set", "setPrototypeOf"
|
21
|
+
])
|
22
|
+
};
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Check if a given node is LHS of an assignment node.
|
26
|
+
* @param {ASTNode} node The node to check.
|
27
|
+
* @returns {boolean} `true` if the node is LHS.
|
28
|
+
*/
|
29
|
+
function isAssignmentLeft(node) {
|
30
|
+
const { parent } = node;
|
31
|
+
|
32
|
+
return (
|
33
|
+
(
|
34
|
+
parent.type === "AssignmentExpression" &&
|
35
|
+
parent.left === node
|
36
|
+
) ||
|
37
|
+
|
38
|
+
// Destructuring assignments
|
39
|
+
parent.type === "ArrayPattern" ||
|
40
|
+
(
|
41
|
+
parent.type === "Property" &&
|
42
|
+
parent.value === node &&
|
43
|
+
parent.parent.type === "ObjectPattern"
|
44
|
+
) ||
|
45
|
+
parent.type === "RestElement" ||
|
46
|
+
(
|
47
|
+
parent.type === "AssignmentPattern" &&
|
48
|
+
parent.left === node
|
49
|
+
)
|
50
|
+
);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Check if a given node is the operand of mutation unary operator.
|
55
|
+
* @param {ASTNode} node The node to check.
|
56
|
+
* @returns {boolean} `true` if the node is the operand of mutation unary operator.
|
57
|
+
*/
|
58
|
+
function isOperandOfMutationUnaryOperator(node) {
|
59
|
+
const { parent } = node;
|
60
|
+
|
61
|
+
return (
|
62
|
+
(
|
63
|
+
parent.type === "UpdateExpression" &&
|
64
|
+
parent.argument === node
|
65
|
+
) ||
|
66
|
+
(
|
67
|
+
parent.type === "UnaryExpression" &&
|
68
|
+
parent.operator === "delete" &&
|
69
|
+
parent.argument === node
|
70
|
+
)
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Check if a given node is the iteration variable of `for-in`/`for-of` syntax.
|
76
|
+
* @param {ASTNode} node The node to check.
|
77
|
+
* @returns {boolean} `true` if the node is the iteration variable.
|
78
|
+
*/
|
79
|
+
function isIterationVariable(node) {
|
80
|
+
const { parent } = node;
|
81
|
+
|
82
|
+
return (
|
83
|
+
(
|
84
|
+
parent.type === "ForInStatement" &&
|
85
|
+
parent.left === node
|
86
|
+
) ||
|
87
|
+
(
|
88
|
+
parent.type === "ForOfStatement" &&
|
89
|
+
parent.left === node
|
90
|
+
)
|
91
|
+
);
|
92
|
+
}
|
93
|
+
|
94
|
+
/**
|
95
|
+
* Check if a given node is the iteration variable of `for-in`/`for-of` syntax.
|
96
|
+
* @param {ASTNode} node The node to check.
|
97
|
+
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
98
|
+
* @returns {boolean} `true` if the node is the iteration variable.
|
99
|
+
*/
|
100
|
+
function isArgumentOfWellKnownMutationFunction(node, scope) {
|
101
|
+
const { parent } = node;
|
102
|
+
|
103
|
+
if (
|
104
|
+
parent.type === "CallExpression" &&
|
105
|
+
parent.arguments[0] === node &&
|
106
|
+
parent.callee.type === "MemberExpression" &&
|
107
|
+
parent.callee.object.type === "Identifier"
|
108
|
+
) {
|
109
|
+
const { callee } = parent;
|
110
|
+
const { object } = callee;
|
111
|
+
|
112
|
+
if (Object.keys(MutationMethods).includes(object.name)) {
|
113
|
+
const variable = findVariable(scope, object);
|
114
|
+
|
115
|
+
return (
|
116
|
+
variable !== null &&
|
117
|
+
variable.scope.type === "global" &&
|
118
|
+
MutationMethods[object.name].has(getPropertyName(callee, scope))
|
119
|
+
);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
return false;
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Check if the identifier node is placed at to update members.
|
128
|
+
* @param {ASTNode} id The Identifier node to check.
|
129
|
+
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
|
130
|
+
* @returns {boolean} `true` if the member of `id` was updated.
|
131
|
+
*/
|
132
|
+
function isMemberWrite(id, scope) {
|
133
|
+
const { parent } = id;
|
134
|
+
|
135
|
+
return (
|
136
|
+
(
|
137
|
+
parent.type === "MemberExpression" &&
|
138
|
+
parent.object === id &&
|
139
|
+
(
|
140
|
+
isAssignmentLeft(parent) ||
|
141
|
+
isOperandOfMutationUnaryOperator(parent) ||
|
142
|
+
isIterationVariable(parent)
|
143
|
+
)
|
144
|
+
) ||
|
145
|
+
isArgumentOfWellKnownMutationFunction(id, scope)
|
146
|
+
);
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Get the mutation node.
|
151
|
+
* @param {ASTNode} id The Identifier node to get.
|
152
|
+
* @returns {ASTNode} The mutation node.
|
153
|
+
*/
|
154
|
+
function getWriteNode(id) {
|
155
|
+
let node = id.parent;
|
156
|
+
|
157
|
+
while (
|
158
|
+
node &&
|
159
|
+
node.type !== "AssignmentExpression" &&
|
160
|
+
node.type !== "UpdateExpression" &&
|
161
|
+
node.type !== "UnaryExpression" &&
|
162
|
+
node.type !== "CallExpression" &&
|
163
|
+
node.type !== "ForInStatement" &&
|
164
|
+
node.type !== "ForOfStatement"
|
165
|
+
) {
|
166
|
+
node = node.parent;
|
167
|
+
}
|
168
|
+
|
169
|
+
return node || id;
|
170
|
+
}
|
171
|
+
|
172
|
+
//------------------------------------------------------------------------------
|
173
|
+
// Rule Definition
|
174
|
+
//------------------------------------------------------------------------------
|
175
|
+
|
176
|
+
module.exports = {
|
177
|
+
meta: {
|
178
|
+
type: "problem",
|
179
|
+
|
180
|
+
docs: {
|
181
|
+
description: "disallow assigning to imported bindings",
|
182
|
+
category: "Possible Errors",
|
183
|
+
recommended: false,
|
184
|
+
url: "https://eslint.org/docs/rules/no-import-assign"
|
185
|
+
},
|
186
|
+
|
187
|
+
schema: [],
|
188
|
+
|
189
|
+
messages: {
|
190
|
+
readonly: "'{{name}}' is read-only.",
|
191
|
+
readonlyMember: "The members of '{{name}}' are read-only."
|
192
|
+
}
|
193
|
+
},
|
194
|
+
|
195
|
+
create(context) {
|
196
|
+
return {
|
197
|
+
ImportDeclaration(node) {
|
198
|
+
const scope = context.getScope();
|
199
|
+
|
200
|
+
for (const variable of context.getDeclaredVariables(node)) {
|
201
|
+
const shouldCheckMembers = variable.defs.some(
|
202
|
+
d => d.node.type === "ImportNamespaceSpecifier"
|
203
|
+
);
|
204
|
+
let prevIdNode = null;
|
205
|
+
|
206
|
+
for (const reference of variable.references) {
|
207
|
+
const idNode = reference.identifier;
|
208
|
+
|
209
|
+
/*
|
210
|
+
* AssignmentPattern (e.g. `[a = 0] = b`) makes two write
|
211
|
+
* references for the same identifier. This should skip
|
212
|
+
* the one of the two in order to prevent redundant reports.
|
213
|
+
*/
|
214
|
+
if (idNode === prevIdNode) {
|
215
|
+
continue;
|
216
|
+
}
|
217
|
+
prevIdNode = idNode;
|
218
|
+
|
219
|
+
if (reference.isWrite()) {
|
220
|
+
context.report({
|
221
|
+
node: getWriteNode(idNode),
|
222
|
+
messageId: "readonly",
|
223
|
+
data: { name: idNode.name }
|
224
|
+
});
|
225
|
+
} else if (shouldCheckMembers && isMemberWrite(idNode, scope)) {
|
226
|
+
context.report({
|
227
|
+
node: getWriteNode(idNode),
|
228
|
+
messageId: "readonlyMember",
|
229
|
+
data: { name: idNode.name }
|
230
|
+
});
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
};
|
236
|
+
|
237
|
+
}
|
238
|
+
};
|
@@ -79,7 +79,7 @@ module.exports = {
|
|
79
79
|
}
|
80
80
|
};
|
81
81
|
|
82
|
-
// ES6: report blocks without block-level bindings
|
82
|
+
// ES6: report blocks without block-level bindings, or that's only child of another block
|
83
83
|
if (context.parserOptions.ecmaVersion >= 6) {
|
84
84
|
ruleDef = {
|
85
85
|
BlockStatement(node) {
|
@@ -91,6 +91,11 @@ module.exports = {
|
|
91
91
|
if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
|
92
92
|
loneBlocks.pop();
|
93
93
|
report(node);
|
94
|
+
} else if (
|
95
|
+
node.parent.type === "BlockStatement" &&
|
96
|
+
node.parent.body.length === 1
|
97
|
+
) {
|
98
|
+
report(node);
|
94
99
|
}
|
95
100
|
}
|
96
101
|
};
|
@@ -5,6 +5,18 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const { CALL, ReferenceTracker } = require("eslint-utils");
|
13
|
+
|
14
|
+
//------------------------------------------------------------------------------
|
15
|
+
// Helpers
|
16
|
+
//------------------------------------------------------------------------------
|
17
|
+
|
18
|
+
const nonCallableGlobals = ["Atomics", "JSON", "Math", "Reflect"];
|
19
|
+
|
8
20
|
//------------------------------------------------------------------------------
|
9
21
|
// Rule Definition
|
10
22
|
//------------------------------------------------------------------------------
|
@@ -20,23 +32,31 @@ module.exports = {
|
|
20
32
|
url: "https://eslint.org/docs/rules/no-obj-calls"
|
21
33
|
},
|
22
34
|
|
23
|
-
schema: []
|
35
|
+
schema: [],
|
36
|
+
|
37
|
+
messages: {
|
38
|
+
unexpectedCall: "'{{name}}' is not a function."
|
39
|
+
}
|
24
40
|
},
|
25
41
|
|
26
42
|
create(context) {
|
27
43
|
|
28
44
|
return {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
45
|
+
Program() {
|
46
|
+
const scope = context.getScope();
|
47
|
+
const tracker = new ReferenceTracker(scope);
|
48
|
+
const traceMap = {};
|
49
|
+
|
50
|
+
for (const global of nonCallableGlobals) {
|
51
|
+
traceMap[global] = {
|
52
|
+
[CALL]: true
|
53
|
+
};
|
54
|
+
}
|
33
55
|
|
34
|
-
|
35
|
-
|
36
|
-
}
|
56
|
+
for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
|
57
|
+
context.report({ node, messageId: "unexpectedCall", data: { name: node.callee.name } });
|
37
58
|
}
|
38
59
|
}
|
39
60
|
};
|
40
|
-
|
41
61
|
}
|
42
62
|
};
|
@@ -20,7 +20,11 @@ module.exports = {
|
|
20
20
|
url: "https://eslint.org/docs/rules/no-octal-escape"
|
21
21
|
},
|
22
22
|
|
23
|
-
schema: []
|
23
|
+
schema: [],
|
24
|
+
|
25
|
+
messages: {
|
26
|
+
octalEscapeSequence: "Don't use octal: '\\{{sequence}}'. Use '\\u....' instead."
|
27
|
+
}
|
24
28
|
},
|
25
29
|
|
26
30
|
create(context) {
|
@@ -32,15 +36,17 @@ module.exports = {
|
|
32
36
|
return;
|
33
37
|
}
|
34
38
|
|
35
|
-
|
39
|
+
// \0 represents a valid NULL character if it isn't followed by a digit.
|
40
|
+
const match = node.raw.match(
|
41
|
+
/^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|[1-7])/u
|
42
|
+
);
|
36
43
|
|
37
44
|
if (match) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
45
|
+
context.report({
|
46
|
+
node,
|
47
|
+
messageId: "octalEscapeSequence",
|
48
|
+
data: { sequence: match[1] }
|
49
|
+
});
|
44
50
|
}
|
45
51
|
}
|
46
52
|
|
@@ -94,9 +94,19 @@ function eachSelfAssignment(left, right, props, report) {
|
|
94
94
|
const end = Math.min(left.elements.length, right.elements.length);
|
95
95
|
|
96
96
|
for (let i = 0; i < end; ++i) {
|
97
|
+
const leftElement = left.elements[i];
|
97
98
|
const rightElement = right.elements[i];
|
98
99
|
|
99
|
-
|
100
|
+
// Avoid cases such as [...a] = [...a, 1]
|
101
|
+
if (
|
102
|
+
leftElement &&
|
103
|
+
leftElement.type === "RestElement" &&
|
104
|
+
i < right.elements.length - 1
|
105
|
+
) {
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
|
109
|
+
eachSelfAssignment(leftElement, rightElement, props, report);
|
100
110
|
|
101
111
|
// After a spread element, those indices are unknown.
|
102
112
|
if (rightElement && rightElement.type === "SpreadElement") {
|
@@ -142,13 +152,14 @@ function eachSelfAssignment(left, right, props, report) {
|
|
142
152
|
} else if (
|
143
153
|
left.type === "Property" &&
|
144
154
|
right.type === "Property" &&
|
145
|
-
!left.computed &&
|
146
|
-
!right.computed &&
|
147
155
|
right.kind === "init" &&
|
148
|
-
!right.method
|
149
|
-
left.key.name === right.key.name
|
156
|
+
!right.method
|
150
157
|
) {
|
151
|
-
|
158
|
+
const leftName = astUtils.getStaticPropertyName(left);
|
159
|
+
|
160
|
+
if (leftName !== null && leftName === astUtils.getStaticPropertyName(right)) {
|
161
|
+
eachSelfAssignment(left.value, right.value, props, report);
|
162
|
+
}
|
152
163
|
} else if (
|
153
164
|
props &&
|
154
165
|
left.type === "MemberExpression" &&
|
@@ -105,9 +105,9 @@ module.exports = {
|
|
105
105
|
}
|
106
106
|
}
|
107
107
|
|
108
|
-
const
|
108
|
+
const firstCommaToken = sourceCode.getTokenAfter(node.expressions[0], astUtils.isCommaToken);
|
109
109
|
|
110
|
-
context.report({ node, loc:
|
110
|
+
context.report({ node, loc: firstCommaToken.loc, message: "Unexpected use of comma operator." });
|
111
111
|
}
|
112
112
|
};
|
113
113
|
|
@@ -51,7 +51,7 @@ module.exports = {
|
|
51
51
|
},
|
52
52
|
|
53
53
|
schema: [],
|
54
|
-
fixable:
|
54
|
+
fixable: null,
|
55
55
|
messages: {
|
56
56
|
unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
|
57
57
|
}
|
@@ -70,15 +70,7 @@ module.exports = {
|
|
70
70
|
node,
|
71
71
|
loc: node.left.loc,
|
72
72
|
messageId: "unexpected",
|
73
|
-
data: { operator: node.operator }
|
74
|
-
|
75
|
-
fix(fixer) {
|
76
|
-
const negationToken = sourceCode.getFirstToken(node.left);
|
77
|
-
const fixRange = [negationToken.range[1], node.range[1]];
|
78
|
-
const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
|
79
|
-
|
80
|
-
return fixer.replaceTextRange(fixRange, `(${text})`);
|
81
|
-
}
|
73
|
+
data: { operator: node.operator }
|
82
74
|
});
|
83
75
|
}
|
84
76
|
}
|
@@ -167,7 +167,7 @@ module.exports = {
|
|
167
167
|
if (options.spaced && !firstSpaced) {
|
168
168
|
reportRequiredBeginningSpace(node, first);
|
169
169
|
}
|
170
|
-
if (!options.spaced && firstSpaced) {
|
170
|
+
if (!options.spaced && firstSpaced && second.type !== "Line") {
|
171
171
|
reportNoBeginningSpace(node, first);
|
172
172
|
}
|
173
173
|
}
|