eslint 6.1.0 → 6.3.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 +67 -0
- package/README.md +8 -4
- package/conf/config-schema.js +2 -0
- package/conf/default-cli-options.js +1 -1
- package/conf/environments.js +72 -15
- package/lib/cli-engine/config-array/config-array.js +13 -0
- package/lib/cli-engine/config-array/extracted-config.js +22 -1
- package/lib/cli-engine/config-array-factory.js +4 -0
- package/lib/cli-engine/formatters/stylish.js +2 -1
- package/lib/init/config-initializer.js +29 -0
- package/lib/init/npm-utils.js +10 -10
- package/lib/linter/apply-disable-directives.js +17 -9
- package/lib/linter/code-path-analysis/code-path-analyzer.js +1 -0
- package/lib/linter/linter.js +70 -17
- package/lib/options.js +1 -1
- package/lib/rules/accessor-pairs.js +195 -35
- package/lib/rules/class-methods-use-this.js +10 -3
- package/lib/rules/dot-notation.js +6 -2
- package/lib/rules/func-call-spacing.js +30 -20
- package/lib/rules/func-name-matching.js +1 -0
- package/lib/rules/func-names.js +4 -0
- package/lib/rules/function-call-argument-newline.js +120 -0
- package/lib/rules/function-paren-newline.js +36 -24
- package/lib/rules/indent.js +13 -2
- package/lib/rules/index.js +1 -0
- package/lib/rules/new-cap.js +2 -1
- package/lib/rules/no-dupe-keys.js +1 -1
- package/lib/rules/no-duplicate-case.js +10 -8
- package/lib/rules/no-extra-bind.js +1 -0
- package/lib/rules/no-extra-boolean-cast.js +54 -5
- package/lib/rules/no-extra-parens.js +62 -23
- package/lib/rules/no-mixed-operators.js +48 -13
- package/lib/rules/no-restricted-syntax.js +2 -2
- package/lib/rules/no-self-assign.js +11 -1
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/prefer-template.js +1 -10
- package/lib/rules/sort-keys.js +11 -3
- package/lib/rules/utils/ast-utils.js +19 -2
- package/lib/rules/yoda.js +12 -3
- package/lib/shared/types.js +4 -0
- package/package.json +5 -5
@@ -0,0 +1,120 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to enforce line breaks between arguments of a function call
|
3
|
+
* @author Alexey Gonchar <https://github.com/finico>
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Rule Definition
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = {
|
13
|
+
meta: {
|
14
|
+
type: "layout",
|
15
|
+
|
16
|
+
docs: {
|
17
|
+
description: "enforce line breaks between arguments of a function call",
|
18
|
+
category: "Stylistic Issues",
|
19
|
+
recommended: false,
|
20
|
+
url: "https://eslint.org/docs/rules/function-call-argument-newline"
|
21
|
+
},
|
22
|
+
|
23
|
+
fixable: "whitespace",
|
24
|
+
|
25
|
+
schema: [
|
26
|
+
{
|
27
|
+
enum: ["always", "never", "consistent"]
|
28
|
+
}
|
29
|
+
],
|
30
|
+
|
31
|
+
messages: {
|
32
|
+
unexpectedLineBreak: "There should be no line break here.",
|
33
|
+
missingLineBreak: "There should be a line break after this argument."
|
34
|
+
}
|
35
|
+
},
|
36
|
+
|
37
|
+
create(context) {
|
38
|
+
const sourceCode = context.getSourceCode();
|
39
|
+
|
40
|
+
const checkers = {
|
41
|
+
unexpected: {
|
42
|
+
messageId: "unexpectedLineBreak",
|
43
|
+
check: (prevToken, currentToken) => prevToken.loc.start.line !== currentToken.loc.start.line,
|
44
|
+
createFix: (token, tokenBefore) => fixer =>
|
45
|
+
fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ")
|
46
|
+
},
|
47
|
+
missing: {
|
48
|
+
messageId: "missingLineBreak",
|
49
|
+
check: (prevToken, currentToken) => prevToken.loc.start.line === currentToken.loc.start.line,
|
50
|
+
createFix: (token, tokenBefore) => fixer =>
|
51
|
+
fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n")
|
52
|
+
}
|
53
|
+
};
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Check all arguments for line breaks in the CallExpression
|
57
|
+
* @param {CallExpression} node node to evaluate
|
58
|
+
* @param {{ messageId: string, check: Function }} checker selected checker
|
59
|
+
* @returns {void}
|
60
|
+
* @private
|
61
|
+
*/
|
62
|
+
function checkArguments(node, checker) {
|
63
|
+
for (let i = 1; i < node.arguments.length; i++) {
|
64
|
+
const prevArgToken = sourceCode.getFirstToken(node.arguments[i - 1]);
|
65
|
+
const currentArgToken = sourceCode.getFirstToken(node.arguments[i]);
|
66
|
+
|
67
|
+
if (checker.check(prevArgToken, currentArgToken)) {
|
68
|
+
const tokenBefore = sourceCode.getTokenBefore(
|
69
|
+
currentArgToken,
|
70
|
+
{ includeComments: true }
|
71
|
+
);
|
72
|
+
|
73
|
+
context.report({
|
74
|
+
node,
|
75
|
+
loc: {
|
76
|
+
start: tokenBefore.loc.end,
|
77
|
+
end: currentArgToken.loc.start
|
78
|
+
},
|
79
|
+
messageId: checker.messageId,
|
80
|
+
fix: checker.createFix(currentArgToken, tokenBefore)
|
81
|
+
});
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Check if open space is present in a function name
|
88
|
+
* @param {CallExpression} node node to evaluate
|
89
|
+
* @returns {void}
|
90
|
+
* @private
|
91
|
+
*/
|
92
|
+
function check(node) {
|
93
|
+
if (node.arguments.length < 2) {
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
|
97
|
+
const option = context.options[0] || "always";
|
98
|
+
|
99
|
+
if (option === "never") {
|
100
|
+
checkArguments(node, checkers.unexpected);
|
101
|
+
} else if (option === "always") {
|
102
|
+
checkArguments(node, checkers.missing);
|
103
|
+
} else if (option === "consistent") {
|
104
|
+
const firstArgToken = sourceCode.getFirstToken(node.arguments[0]);
|
105
|
+
const secondArgToken = sourceCode.getFirstToken(node.arguments[1]);
|
106
|
+
|
107
|
+
if (firstArgToken.loc.start.line === secondArgToken.loc.start.line) {
|
108
|
+
checkArguments(node, checkers.unexpected);
|
109
|
+
} else {
|
110
|
+
checkArguments(node, checkers.missing);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
return {
|
116
|
+
CallExpression: check,
|
117
|
+
NewExpression: check
|
118
|
+
};
|
119
|
+
}
|
120
|
+
};
|
@@ -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
|
|
@@ -232,25 +232,15 @@ module.exports = {
|
|
232
232
|
};
|
233
233
|
}
|
234
234
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
}
|
239
|
-
|
240
|
-
/**
|
241
|
-
* Validates the parentheses for a node
|
242
|
-
* @param {ASTNode} node The node with parens
|
243
|
-
* @returns {void}
|
244
|
-
*/
|
245
|
-
function validateNode(node) {
|
246
|
-
const parens = getParenTokens(node);
|
247
|
-
|
248
|
-
if (parens) {
|
249
|
-
validateParens(parens, astUtils.isFunction(node) ? node.params : node.arguments);
|
235
|
+
case "ImportExpression": {
|
236
|
+
const leftParen = sourceCode.getFirstToken(node, 1);
|
237
|
+
const rightParen = sourceCode.getLastToken(node);
|
250
238
|
|
251
|
-
|
252
|
-
validateArguments(parens, astUtils.isFunction(node) ? node.params : node.arguments);
|
239
|
+
return { leftParen, rightParen };
|
253
240
|
}
|
241
|
+
|
242
|
+
default:
|
243
|
+
throw new TypeError(`unexpected node with type ${node.type}`);
|
254
244
|
}
|
255
245
|
}
|
256
246
|
|
@@ -259,11 +249,33 @@ module.exports = {
|
|
259
249
|
//----------------------------------------------------------------------
|
260
250
|
|
261
251
|
return {
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
252
|
+
[[
|
253
|
+
"ArrowFunctionExpression",
|
254
|
+
"CallExpression",
|
255
|
+
"FunctionDeclaration",
|
256
|
+
"FunctionExpression",
|
257
|
+
"ImportExpression",
|
258
|
+
"NewExpression"
|
259
|
+
]](node) {
|
260
|
+
const parens = getParenTokens(node);
|
261
|
+
let params;
|
262
|
+
|
263
|
+
if (node.type === "ImportExpression") {
|
264
|
+
params = [node.source];
|
265
|
+
} else if (astUtils.isFunction(node)) {
|
266
|
+
params = node.params;
|
267
|
+
} else {
|
268
|
+
params = node.arguments;
|
269
|
+
}
|
270
|
+
|
271
|
+
if (parens) {
|
272
|
+
validateParens(parens, params);
|
273
|
+
|
274
|
+
if (multilineArgumentsOption) {
|
275
|
+
validateArguments(parens, params);
|
276
|
+
}
|
277
|
+
}
|
278
|
+
}
|
267
279
|
};
|
268
280
|
}
|
269
281
|
};
|
package/lib/rules/indent.js
CHANGED
@@ -99,7 +99,8 @@ const KNOWN_NODES = new Set([
|
|
99
99
|
"ImportDeclaration",
|
100
100
|
"ImportSpecifier",
|
101
101
|
"ImportDefaultSpecifier",
|
102
|
-
"ImportNamespaceSpecifier"
|
102
|
+
"ImportNamespaceSpecifier",
|
103
|
+
"ImportExpression"
|
103
104
|
]);
|
104
105
|
|
105
106
|
/*
|
@@ -1109,7 +1110,6 @@ module.exports = {
|
|
1109
1110
|
|
1110
1111
|
CallExpression: addFunctionCallIndent,
|
1111
1112
|
|
1112
|
-
|
1113
1113
|
"ClassDeclaration[superClass], ClassExpression[superClass]"(node) {
|
1114
1114
|
const classToken = sourceCode.getFirstToken(node);
|
1115
1115
|
const extendsToken = sourceCode.getTokenBefore(node.superClass, astUtils.isNotOpeningParenToken);
|
@@ -1236,6 +1236,17 @@ module.exports = {
|
|
1236
1236
|
}
|
1237
1237
|
},
|
1238
1238
|
|
1239
|
+
ImportExpression(node) {
|
1240
|
+
const openingParen = sourceCode.getFirstToken(node, 1);
|
1241
|
+
const closingParen = sourceCode.getLastToken(node);
|
1242
|
+
|
1243
|
+
parameterParens.add(openingParen);
|
1244
|
+
parameterParens.add(closingParen);
|
1245
|
+
offsets.setDesiredOffset(openingParen, sourceCode.getTokenBefore(openingParen), 0);
|
1246
|
+
|
1247
|
+
addElementListIndent([node.source], openingParen, closingParen, options.CallExpression.arguments);
|
1248
|
+
},
|
1249
|
+
|
1239
1250
|
"MemberExpression, JSXMemberExpression, MetaProperty"(node) {
|
1240
1251
|
const object = node.type === "MetaProperty" ? node.meta : node.object;
|
1241
1252
|
const firstNonObjectToken = sourceCode.getFirstTokenBetween(object, node.property, astUtils.isNotClosingParenToken);
|
package/lib/rules/index.js
CHANGED
@@ -46,6 +46,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
46
46
|
"func-name-matching": () => require("./func-name-matching"),
|
47
47
|
"func-names": () => require("./func-names"),
|
48
48
|
"func-style": () => require("./func-style"),
|
49
|
+
"function-call-argument-newline": () => require("./function-call-argument-newline"),
|
49
50
|
"function-paren-newline": () => require("./function-paren-newline"),
|
50
51
|
"generator-star-spacing": () => require("./generator-star-spacing"),
|
51
52
|
"getter-return": () => require("./getter-return"),
|
package/lib/rules/new-cap.js
CHANGED
@@ -33,17 +33,19 @@ module.exports = {
|
|
33
33
|
|
34
34
|
return {
|
35
35
|
SwitchStatement(node) {
|
36
|
-
const
|
36
|
+
const previousKeys = new Set();
|
37
37
|
|
38
|
-
node.cases
|
39
|
-
|
38
|
+
for (const switchCase of node.cases) {
|
39
|
+
if (switchCase.test) {
|
40
|
+
const key = sourceCode.getText(switchCase.test);
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
if (previousKeys.has(key)) {
|
43
|
+
context.report({ node: switchCase, messageId: "unexpected" });
|
44
|
+
} else {
|
45
|
+
previousKeys.add(key);
|
46
|
+
}
|
45
47
|
}
|
46
|
-
}
|
48
|
+
}
|
47
49
|
}
|
48
50
|
};
|
49
51
|
}
|
@@ -98,6 +98,7 @@ module.exports = {
|
|
98
98
|
grandparent.type === "CallExpression" &&
|
99
99
|
grandparent.callee === parent &&
|
100
100
|
grandparent.arguments.length === 1 &&
|
101
|
+
grandparent.arguments[0].type !== "SpreadElement" &&
|
101
102
|
parent.type === "MemberExpression" &&
|
102
103
|
parent.object === node &&
|
103
104
|
astUtils.getStaticPropertyName(parent) === "bind"
|
@@ -50,8 +50,8 @@ module.exports = {
|
|
50
50
|
/**
|
51
51
|
* Check if a node is in a context where its value would be coerced to a boolean at runtime.
|
52
52
|
*
|
53
|
-
* @param {
|
54
|
-
* @param {
|
53
|
+
* @param {ASTNode} node The node
|
54
|
+
* @param {ASTNode} parent Its parent
|
55
55
|
* @returns {boolean} If it is in a boolean context
|
56
56
|
*/
|
57
57
|
function isInBooleanContext(node, parent) {
|
@@ -65,6 +65,15 @@ module.exports = {
|
|
65
65
|
);
|
66
66
|
}
|
67
67
|
|
68
|
+
/**
|
69
|
+
* Check if a node has comments inside.
|
70
|
+
*
|
71
|
+
* @param {ASTNode} node The node to check.
|
72
|
+
* @returns {boolean} `true` if it has comments inside.
|
73
|
+
*/
|
74
|
+
function hasCommentsInside(node) {
|
75
|
+
return Boolean(sourceCode.getCommentsInside(node).length);
|
76
|
+
}
|
68
77
|
|
69
78
|
return {
|
70
79
|
UnaryExpression(node) {
|
@@ -89,7 +98,22 @@ module.exports = {
|
|
89
98
|
context.report({
|
90
99
|
node,
|
91
100
|
messageId: "unexpectedNegation",
|
92
|
-
fix: fixer =>
|
101
|
+
fix: fixer => {
|
102
|
+
if (hasCommentsInside(parent)) {
|
103
|
+
return null;
|
104
|
+
}
|
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));
|
116
|
+
}
|
93
117
|
});
|
94
118
|
}
|
95
119
|
},
|
@@ -106,10 +130,35 @@ module.exports = {
|
|
106
130
|
messageId: "unexpectedCall",
|
107
131
|
fix: fixer => {
|
108
132
|
if (!node.arguments.length) {
|
109
|
-
|
133
|
+
if (parent.type === "UnaryExpression" && parent.operator === "!") {
|
134
|
+
|
135
|
+
// !Boolean() -> true
|
136
|
+
|
137
|
+
if (hasCommentsInside(parent)) {
|
138
|
+
return null;
|
139
|
+
}
|
140
|
+
|
141
|
+
const replacement = "true";
|
142
|
+
let prefix = "";
|
143
|
+
const tokenBefore = sourceCode.getTokenBefore(parent);
|
144
|
+
|
145
|
+
if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
|
146
|
+
!astUtils.canTokensBeAdjacent(tokenBefore, replacement)) {
|
147
|
+
prefix = " ";
|
148
|
+
}
|
149
|
+
|
150
|
+
return fixer.replaceText(parent, prefix + replacement);
|
151
|
+
}
|
152
|
+
|
153
|
+
// Boolean() -> false
|
154
|
+
if (hasCommentsInside(node)) {
|
155
|
+
return null;
|
156
|
+
}
|
157
|
+
return fixer.replaceText(node, "false");
|
110
158
|
}
|
111
159
|
|
112
|
-
if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement"
|
160
|
+
if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement" ||
|
161
|
+
hasCommentsInside(node)) {
|
113
162
|
return null;
|
114
163
|
}
|
115
164
|
|
@@ -8,6 +8,7 @@
|
|
8
8
|
// Rule Definition
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
+
const { isParenthesized: isParenthesizedRaw } = require("eslint-utils");
|
11
12
|
const astUtils = require("./utils/ast-utils.js");
|
12
13
|
|
13
14
|
module.exports = {
|
@@ -48,7 +49,8 @@ module.exports = {
|
|
48
49
|
nestedBinaryExpressions: { type: "boolean" },
|
49
50
|
returnAssign: { type: "boolean" },
|
50
51
|
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] },
|
51
|
-
enforceForArrowConditionals: { type: "boolean" }
|
52
|
+
enforceForArrowConditionals: { type: "boolean" },
|
53
|
+
enforceForSequenceExpressions: { type: "boolean" }
|
52
54
|
},
|
53
55
|
additionalProperties: false
|
54
56
|
}
|
@@ -68,7 +70,6 @@ module.exports = {
|
|
68
70
|
const sourceCode = context.getSourceCode();
|
69
71
|
|
70
72
|
const tokensToIgnore = new WeakSet();
|
71
|
-
const isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode);
|
72
73
|
const precedence = astUtils.getPrecedence;
|
73
74
|
const ALL_NODES = context.options[0] !== "functions";
|
74
75
|
const EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false;
|
@@ -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,9 +118,23 @@ 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
|
|
128
|
+
/**
|
129
|
+
* Determines if a node is surrounded by parentheses.
|
130
|
+
* @param {ASTNode} node - The node to be checked.
|
131
|
+
* @returns {boolean} True if the node is parenthesised.
|
132
|
+
* @private
|
133
|
+
*/
|
134
|
+
function isParenthesised(node) {
|
135
|
+
return isParenthesizedRaw(1, node, sourceCode);
|
136
|
+
}
|
137
|
+
|
121
138
|
/**
|
122
139
|
* Determines if a node is surrounded by parentheses twice.
|
123
140
|
* @param {ASTNode} node - The node to be checked.
|
@@ -125,12 +142,7 @@ module.exports = {
|
|
125
142
|
* @private
|
126
143
|
*/
|
127
144
|
function isParenthesisedTwice(node) {
|
128
|
-
|
129
|
-
nextToken = sourceCode.getTokenAfter(node, 1);
|
130
|
-
|
131
|
-
return isParenthesised(node) && previousToken && nextToken &&
|
132
|
-
astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
|
133
|
-
astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
|
145
|
+
return isParenthesizedRaw(2, node, sourceCode);
|
134
146
|
}
|
135
147
|
|
136
148
|
/**
|
@@ -406,15 +418,9 @@ module.exports = {
|
|
406
418
|
report(node.callee);
|
407
419
|
}
|
408
420
|
}
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
}
|
413
|
-
} else {
|
414
|
-
node.arguments
|
415
|
-
.filter(arg => hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
|
416
|
-
.forEach(report);
|
417
|
-
}
|
421
|
+
node.arguments
|
422
|
+
.filter(arg => hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
|
423
|
+
.forEach(report);
|
418
424
|
}
|
419
425
|
|
420
426
|
/**
|
@@ -686,6 +692,13 @@ module.exports = {
|
|
686
692
|
|
687
693
|
CallExpression: checkCallNew,
|
688
694
|
|
695
|
+
ClassBody(node) {
|
696
|
+
node.body
|
697
|
+
.filter(member => member.type === "MethodDefinition" && member.computed &&
|
698
|
+
member.key && hasExcessParens(member.key) && precedence(member.key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
|
699
|
+
.forEach(member => report(member.key));
|
700
|
+
},
|
701
|
+
|
689
702
|
ConditionalExpression(node) {
|
690
703
|
if (isReturnAssignException(node)) {
|
691
704
|
return;
|
@@ -705,7 +718,7 @@ module.exports = {
|
|
705
718
|
},
|
706
719
|
|
707
720
|
DoWhileStatement(node) {
|
708
|
-
if (
|
721
|
+
if (hasExcessParens(node.test) && !isCondAssignException(node)) {
|
709
722
|
report(node.test);
|
710
723
|
}
|
711
724
|
},
|
@@ -830,11 +843,23 @@ module.exports = {
|
|
830
843
|
},
|
831
844
|
|
832
845
|
IfStatement(node) {
|
833
|
-
if (
|
846
|
+
if (hasExcessParens(node.test) && !isCondAssignException(node)) {
|
834
847
|
report(node.test);
|
835
848
|
}
|
836
849
|
},
|
837
850
|
|
851
|
+
ImportExpression(node) {
|
852
|
+
const { source } = node;
|
853
|
+
|
854
|
+
if (source.type === "SequenceExpression") {
|
855
|
+
if (hasDoubleExcessParens(source)) {
|
856
|
+
report(source);
|
857
|
+
}
|
858
|
+
} else if (hasExcessParens(source)) {
|
859
|
+
report(source);
|
860
|
+
}
|
861
|
+
},
|
862
|
+
|
838
863
|
LogicalExpression: checkBinaryLogical,
|
839
864
|
|
840
865
|
MemberExpression(node) {
|
@@ -917,7 +942,7 @@ module.exports = {
|
|
917
942
|
},
|
918
943
|
|
919
944
|
SwitchStatement(node) {
|
920
|
-
if (
|
945
|
+
if (hasExcessParens(node.discriminant)) {
|
921
946
|
report(node.discriminant);
|
922
947
|
}
|
923
948
|
},
|
@@ -945,13 +970,13 @@ module.exports = {
|
|
945
970
|
},
|
946
971
|
|
947
972
|
WhileStatement(node) {
|
948
|
-
if (
|
973
|
+
if (hasExcessParens(node.test) && !isCondAssignException(node)) {
|
949
974
|
report(node.test);
|
950
975
|
}
|
951
976
|
},
|
952
977
|
|
953
978
|
WithStatement(node) {
|
954
|
-
if (
|
979
|
+
if (hasExcessParens(node.object)) {
|
955
980
|
report(node.object);
|
956
981
|
}
|
957
982
|
},
|
@@ -973,7 +998,21 @@ module.exports = {
|
|
973
998
|
|
974
999
|
SpreadElement: checkSpreadOperator,
|
975
1000
|
SpreadProperty: checkSpreadOperator,
|
976
|
-
ExperimentalSpreadProperty: checkSpreadOperator
|
1001
|
+
ExperimentalSpreadProperty: checkSpreadOperator,
|
1002
|
+
|
1003
|
+
TemplateLiteral(node) {
|
1004
|
+
node.expressions
|
1005
|
+
.filter(e => e && hasExcessParens(e))
|
1006
|
+
.forEach(report);
|
1007
|
+
},
|
1008
|
+
|
1009
|
+
AssignmentPattern(node) {
|
1010
|
+
const { right } = node;
|
1011
|
+
|
1012
|
+
if (right && hasExcessParens(right) && precedence(right) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
1013
|
+
report(right);
|
1014
|
+
}
|
1015
|
+
}
|
977
1016
|
};
|
978
1017
|
|
979
1018
|
}
|