eslint 3.13.1 → 3.16.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 +81 -0
- package/README.md +1 -1
- package/conf/{eslint.json → eslint-recommended.js} +88 -71
- package/lib/ast-utils.js +247 -28
- package/lib/cli.js +2 -2
- package/lib/code-path-analysis/code-path-state.js +2 -2
- package/lib/config/autoconfig.js +24 -20
- package/lib/config/config-file.js +31 -24
- package/lib/config/config-initializer.js +2 -2
- package/lib/config/config-rule.js +15 -16
- package/lib/config/config-validator.js +6 -6
- package/lib/config.js +3 -2
- package/lib/eslint.js +18 -18
- package/lib/formatters/checkstyle.js +2 -2
- package/lib/formatters/codeframe.js +1 -1
- package/lib/formatters/compact.js +2 -2
- package/lib/formatters/junit.js +2 -2
- package/lib/formatters/tap.js +2 -2
- package/lib/formatters/unix.js +2 -2
- package/lib/formatters/visualstudio.js +2 -2
- package/lib/internal-rules/internal-consistent-docs-description.js +1 -1
- package/lib/rule-context.js +2 -2
- package/lib/rules/arrow-body-style.js +7 -4
- package/lib/rules/arrow-spacing.js +7 -6
- package/lib/rules/block-spacing.js +2 -2
- package/lib/rules/brace-style.js +93 -202
- package/lib/rules/capitalized-comments.js +6 -6
- package/lib/rules/comma-dangle.js +6 -6
- package/lib/rules/comma-spacing.js +16 -16
- package/lib/rules/comma-style.js +1 -1
- package/lib/rules/consistent-return.js +1 -1
- package/lib/rules/constructor-super.js +3 -3
- package/lib/rules/curly.js +11 -7
- package/lib/rules/default-case.js +3 -3
- package/lib/rules/eqeqeq.js +15 -6
- package/lib/rules/func-call-spacing.js +12 -15
- package/lib/rules/func-name-matching.js +1 -1
- package/lib/rules/generator-star-spacing.js +18 -19
- package/lib/rules/global-require.js +2 -2
- package/lib/rules/id-blacklist.js +2 -2
- package/lib/rules/id-length.js +3 -3
- package/lib/rules/id-match.js +2 -2
- package/lib/rules/indent.js +21 -20
- package/lib/rules/key-spacing.js +20 -23
- package/lib/rules/keyword-spacing.js +2 -13
- package/lib/rules/line-comment-position.js +1 -1
- package/lib/rules/linebreak-style.js +7 -1
- package/lib/rules/lines-around-comment.js +4 -4
- package/lib/rules/lines-around-directive.js +4 -4
- package/lib/rules/max-lines.js +3 -3
- package/lib/rules/max-statements-per-line.js +8 -7
- package/lib/rules/new-cap.js +2 -2
- package/lib/rules/newline-after-var.js +7 -2
- package/lib/rules/newline-before-return.js +2 -2
- package/lib/rules/newline-per-chained-call.js +3 -1
- package/lib/rules/no-await-in-loop.js +5 -5
- package/lib/rules/no-cond-assign.js +3 -3
- package/lib/rules/no-dupe-keys.js +1 -1
- package/lib/rules/no-else-return.js +88 -25
- package/lib/rules/no-extend-native.js +3 -3
- package/lib/rules/no-extra-bind.js +3 -4
- package/lib/rules/no-extra-boolean-cast.js +22 -1
- package/lib/rules/no-extra-parens.js +57 -9
- package/lib/rules/no-inner-declarations.js +4 -4
- package/lib/rules/no-irregular-whitespace.js +7 -1
- package/lib/rules/no-lone-blocks.js +10 -10
- package/lib/rules/no-mixed-operators.js +1 -7
- package/lib/rules/no-mixed-requires.js +4 -4
- package/lib/rules/no-multi-assign.js +41 -0
- package/lib/rules/no-multi-spaces.js +4 -1
- package/lib/rules/no-multi-str.js +7 -3
- package/lib/rules/no-redeclare.js +7 -7
- package/lib/rules/no-return-assign.js +7 -14
- package/lib/rules/no-return-await.js +2 -2
- package/lib/rules/no-sequences.js +7 -6
- package/lib/rules/no-throw-literal.js +2 -39
- package/lib/rules/no-trailing-spaces.js +8 -2
- package/lib/rules/no-undefined.js +45 -6
- package/lib/rules/no-unexpected-multiline.js +9 -8
- package/lib/rules/no-unneeded-ternary.js +5 -1
- package/lib/rules/no-unused-labels.js +17 -2
- package/lib/rules/no-unused-vars.js +34 -19
- package/lib/rules/no-use-before-define.js +33 -29
- package/lib/rules/no-useless-computed-key.js +9 -4
- package/lib/rules/no-useless-concat.js +10 -7
- package/lib/rules/no-useless-escape.js +1 -1
- package/lib/rules/no-useless-return.js +5 -11
- package/lib/rules/no-var.js +69 -3
- package/lib/rules/no-whitespace-before-property.js +5 -16
- package/lib/rules/object-curly-newline.js +2 -2
- package/lib/rules/object-curly-spacing.js +7 -25
- package/lib/rules/object-property-newline.js +3 -3
- package/lib/rules/object-shorthand.js +10 -10
- package/lib/rules/operator-assignment.js +2 -2
- package/lib/rules/operator-linebreak.js +8 -10
- package/lib/rules/padded-blocks.js +4 -4
- package/lib/rules/prefer-promise-reject-errors.js +124 -0
- package/lib/rules/prefer-spread.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/quotes.js +11 -7
- package/lib/rules/require-await.js +1 -1
- package/lib/rules/semi-spacing.js +4 -0
- package/lib/rules/sort-imports.js +4 -4
- package/lib/rules/sort-keys.js +2 -2
- package/lib/rules/sort-vars.js +2 -2
- package/lib/rules/space-before-function-paren.js +9 -6
- package/lib/rules/space-in-parens.js +8 -8
- package/lib/rules/spaced-comment.js +10 -10
- package/lib/rules/strict.js +2 -2
- package/lib/rules/template-tag-spacing.js +77 -0
- package/lib/rules/unicode-bom.js +1 -1
- package/lib/rules/wrap-iife.js +5 -5
- package/lib/rules/yoda.js +2 -7
- package/lib/rules.js +2 -2
- package/lib/testers/rule-tester.js +28 -21
- package/lib/token-store/backward-token-comment-cursor.js +57 -0
- package/lib/token-store/backward-token-cursor.js +56 -0
- package/lib/token-store/cursor.js +76 -0
- package/lib/token-store/cursors.js +92 -0
- package/lib/token-store/decorative-cursor.js +39 -0
- package/lib/token-store/filter-cursor.js +43 -0
- package/lib/token-store/forward-token-comment-cursor.js +57 -0
- package/lib/token-store/forward-token-cursor.js +61 -0
- package/lib/token-store/index.js +604 -0
- package/lib/token-store/limit-cursor.js +40 -0
- package/lib/token-store/padded-token-cursor.js +38 -0
- package/lib/token-store/skip-cursor.js +42 -0
- package/lib/token-store/utils.js +100 -0
- package/lib/util/comment-event-generator.js +17 -16
- package/lib/util/glob-util.js +1 -1
- package/lib/util/glob.js +1 -1
- package/lib/util/rule-fixer.js +3 -8
- package/lib/util/source-code-fixer.js +41 -45
- package/lib/util/source-code.js +35 -19
- package/messages/extend-config-missing.txt +3 -0
- package/package.json +3 -3
- package/lib/token-store.js +0 -203
@@ -17,7 +17,9 @@ module.exports = {
|
|
17
17
|
recommended: false
|
18
18
|
},
|
19
19
|
|
20
|
-
schema: []
|
20
|
+
schema: [],
|
21
|
+
|
22
|
+
fixable: "code"
|
21
23
|
},
|
22
24
|
|
23
25
|
create(context) {
|
@@ -33,7 +35,60 @@ module.exports = {
|
|
33
35
|
* @returns {void}
|
34
36
|
*/
|
35
37
|
function displayReport(node) {
|
36
|
-
context.report({
|
38
|
+
context.report({
|
39
|
+
node,
|
40
|
+
message: "Unnecessary 'else' after 'return'.",
|
41
|
+
fix: fixer => {
|
42
|
+
const sourceCode = context.getSourceCode();
|
43
|
+
const startToken = sourceCode.getFirstToken(node);
|
44
|
+
const elseToken = sourceCode.getTokenBefore(startToken);
|
45
|
+
const source = sourceCode.getText(node);
|
46
|
+
const lastIfToken = sourceCode.getTokenBefore(elseToken);
|
47
|
+
let fixedSource, firstTokenOfElseBlock;
|
48
|
+
|
49
|
+
if (startToken.type === "Punctuator" && startToken.value === "{") {
|
50
|
+
firstTokenOfElseBlock = sourceCode.getTokenAfter(startToken);
|
51
|
+
} else {
|
52
|
+
firstTokenOfElseBlock = startToken;
|
53
|
+
}
|
54
|
+
|
55
|
+
// If the if block does not have curly braces and does not end in a semicolon
|
56
|
+
// and the else block starts with (, [, /, +, ` or -, then it is not
|
57
|
+
// safe to remove the else keyword, because ASI will not add a semicolon
|
58
|
+
// after the if block
|
59
|
+
const ifBlockMaybeUnsafe = node.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";";
|
60
|
+
const elseBlockUnsafe = /^[([/+`-]/.test(firstTokenOfElseBlock.value);
|
61
|
+
|
62
|
+
if (ifBlockMaybeUnsafe && elseBlockUnsafe) {
|
63
|
+
return null;
|
64
|
+
}
|
65
|
+
|
66
|
+
const endToken = sourceCode.getLastToken(node);
|
67
|
+
const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken);
|
68
|
+
|
69
|
+
if (lastTokenOfElseBlock.value !== ";") {
|
70
|
+
const nextToken = sourceCode.getTokenAfter(endToken);
|
71
|
+
|
72
|
+
const nextTokenUnsafe = nextToken && /^[([/+`-]/.test(nextToken.value);
|
73
|
+
const nextTokenOnSameLine = nextToken && nextToken.loc.start.line === lastTokenOfElseBlock.loc.start.line;
|
74
|
+
|
75
|
+
// If the else block contents does not end in a semicolon,
|
76
|
+
// and the else block starts with (, [, /, +, ` or -, then it is not
|
77
|
+
// safe to remove the else block, because ASI will not add a semicolon
|
78
|
+
// after the remaining else block contents
|
79
|
+
if (nextTokenUnsafe || (nextTokenOnSameLine && nextToken.value !== "}")) {
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
if (startToken.type === "Punctuator" && startToken.value === "{") {
|
85
|
+
fixedSource = source.slice(1, -1);
|
86
|
+
} else {
|
87
|
+
fixedSource = source;
|
88
|
+
}
|
89
|
+
return fixer.replaceTextRange([elseToken.start, node.end], fixedSource);
|
90
|
+
}
|
91
|
+
});
|
37
92
|
}
|
38
93
|
|
39
94
|
/**
|
@@ -121,35 +176,43 @@ module.exports = {
|
|
121
176
|
return checkForReturnOrIf(node);
|
122
177
|
}
|
123
178
|
|
179
|
+
/**
|
180
|
+
* Check the if statement
|
181
|
+
* @returns {void}
|
182
|
+
* @param {Node} node The node for the if statement to check
|
183
|
+
* @private
|
184
|
+
*/
|
185
|
+
function IfStatement(node) {
|
186
|
+
const parent = context.getAncestors().pop();
|
187
|
+
let consequents,
|
188
|
+
alternate;
|
189
|
+
|
190
|
+
// Only "top-level" if statements are checked, meaning the first `if`
|
191
|
+
// in a `if-else-if-...` chain.
|
192
|
+
if (parent.type === "IfStatement" && parent.alternate === node) {
|
193
|
+
return;
|
194
|
+
}
|
195
|
+
|
196
|
+
for (consequents = []; node.type === "IfStatement"; node = node.alternate) {
|
197
|
+
if (!node.alternate) {
|
198
|
+
return;
|
199
|
+
}
|
200
|
+
consequents.push(node.consequent);
|
201
|
+
alternate = node.alternate;
|
202
|
+
}
|
203
|
+
|
204
|
+
if (consequents.every(alwaysReturns)) {
|
205
|
+
displayReport(alternate);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
124
209
|
//--------------------------------------------------------------------------
|
125
210
|
// Public API
|
126
211
|
//--------------------------------------------------------------------------
|
127
212
|
|
128
213
|
return {
|
129
214
|
|
130
|
-
IfStatement
|
131
|
-
const parent = context.getAncestors().pop();
|
132
|
-
let consequents,
|
133
|
-
alternate;
|
134
|
-
|
135
|
-
// Only "top-level" if statements are checked, meaning the first `if`
|
136
|
-
// in a `if-else-if-...` chain.
|
137
|
-
if (parent.type === "IfStatement" && parent.alternate === node) {
|
138
|
-
return;
|
139
|
-
}
|
140
|
-
|
141
|
-
for (consequents = []; node.type === "IfStatement"; node = node.alternate) {
|
142
|
-
if (!node.alternate) {
|
143
|
-
return;
|
144
|
-
}
|
145
|
-
consequents.push(node.consequent);
|
146
|
-
alternate = node.alternate;
|
147
|
-
}
|
148
|
-
|
149
|
-
if (consequents.every(alwaysReturns)) {
|
150
|
-
displayReport(alternate);
|
151
|
-
}
|
152
|
-
}
|
215
|
+
"IfStatement:exit": IfStatement
|
153
216
|
|
154
217
|
};
|
155
218
|
|
@@ -60,9 +60,9 @@ module.exports = {
|
|
60
60
|
return;
|
61
61
|
}
|
62
62
|
|
63
|
-
const affectsProto = lhs.object.computed
|
64
|
-
lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype"
|
65
|
-
lhs.object.property.name === "prototype";
|
63
|
+
const affectsProto = lhs.object.computed
|
64
|
+
? lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype"
|
65
|
+
: lhs.object.property.name === "prototype";
|
66
66
|
|
67
67
|
if (!affectsProto) {
|
68
68
|
return;
|
@@ -8,7 +8,7 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const
|
11
|
+
const astUtils = require("../ast-utils");
|
12
12
|
|
13
13
|
//------------------------------------------------------------------------------
|
14
14
|
// Rule Definition
|
@@ -44,8 +44,7 @@ module.exports = {
|
|
44
44
|
loc: node.parent.property.loc.start,
|
45
45
|
fix(fixer) {
|
46
46
|
const firstTokenToRemove = context.getSourceCode()
|
47
|
-
.
|
48
|
-
.find(token => token.value !== ")");
|
47
|
+
.getFirstTokenBetween(node.parent.object, node.parent.property, astUtils.isNotClosingParenToken);
|
49
48
|
|
50
49
|
return fixer.removeRange([firstTokenToRemove.range[0], node.parent.parent.range[1]]);
|
51
50
|
}
|
@@ -73,7 +72,7 @@ module.exports = {
|
|
73
72
|
grandparent.arguments.length === 1 &&
|
74
73
|
parent.type === "MemberExpression" &&
|
75
74
|
parent.object === node &&
|
76
|
-
|
75
|
+
astUtils.getStaticPropertyName(parent) === "bind"
|
77
76
|
);
|
78
77
|
}
|
79
78
|
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -91,7 +97,22 @@ module.exports = {
|
|
91
97
|
context.report({
|
92
98
|
node,
|
93
99
|
message: "Redundant Boolean call.",
|
94
|
-
fix: fixer =>
|
100
|
+
fix: fixer => {
|
101
|
+
if (!node.arguments.length) {
|
102
|
+
return fixer.replaceText(parent, "true");
|
103
|
+
}
|
104
|
+
|
105
|
+
if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement") {
|
106
|
+
return null;
|
107
|
+
}
|
108
|
+
|
109
|
+
const argument = node.arguments[0];
|
110
|
+
|
111
|
+
if (astUtils.getPrecedence(argument) < astUtils.getPrecedence(node.parent)) {
|
112
|
+
return fixer.replaceText(node, `(${sourceCode.getText(argument)})`);
|
113
|
+
}
|
114
|
+
return fixer.replaceText(node, sourceCode.getText(argument));
|
115
|
+
}
|
95
116
|
});
|
96
117
|
}
|
97
118
|
}
|
@@ -44,7 +44,8 @@ module.exports = {
|
|
44
44
|
properties: {
|
45
45
|
conditionalAssign: { type: "boolean" },
|
46
46
|
nestedBinaryExpressions: { type: "boolean" },
|
47
|
-
returnAssign: { type: "boolean" }
|
47
|
+
returnAssign: { type: "boolean" },
|
48
|
+
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] }
|
48
49
|
},
|
49
50
|
additionalProperties: false
|
50
51
|
}
|
@@ -65,6 +66,7 @@ module.exports = {
|
|
65
66
|
const EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false;
|
66
67
|
const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false;
|
67
68
|
const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false;
|
69
|
+
const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX;
|
68
70
|
|
69
71
|
/**
|
70
72
|
* Determines if this rule should be enforced for a node given the current configuration.
|
@@ -73,6 +75,31 @@ module.exports = {
|
|
73
75
|
* @private
|
74
76
|
*/
|
75
77
|
function ruleApplies(node) {
|
78
|
+
if (node.type === "JSXElement") {
|
79
|
+
const isSingleLine = node.loc.start.line === node.loc.end.line;
|
80
|
+
|
81
|
+
switch (IGNORE_JSX) {
|
82
|
+
|
83
|
+
// Exclude this JSX element from linting
|
84
|
+
case "all":
|
85
|
+
return false;
|
86
|
+
|
87
|
+
// Exclude this JSX element if it is multi-line element
|
88
|
+
case "multi-line":
|
89
|
+
return isSingleLine;
|
90
|
+
|
91
|
+
// Exclude this JSX element if it is single-line element
|
92
|
+
case "single-line":
|
93
|
+
return !isSingleLine;
|
94
|
+
|
95
|
+
// Nothing special to be done for JSX elements
|
96
|
+
case "none":
|
97
|
+
break;
|
98
|
+
|
99
|
+
// no default
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
76
103
|
return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
77
104
|
}
|
78
105
|
|
@@ -140,6 +167,19 @@ module.exports = {
|
|
140
167
|
return false;
|
141
168
|
}
|
142
169
|
|
170
|
+
/**
|
171
|
+
* Determines if a constructor function is newed-up with parens
|
172
|
+
* @param {ASTNode} newExpression - The NewExpression node to be checked.
|
173
|
+
* @returns {boolean} True if the constructor is called with parens.
|
174
|
+
* @private
|
175
|
+
*/
|
176
|
+
function isNewExpressionWithParens(newExpression) {
|
177
|
+
const lastToken = sourceCode.getLastToken(newExpression);
|
178
|
+
const penultimateToken = sourceCode.getTokenBefore(lastToken);
|
179
|
+
|
180
|
+
return newExpression.arguments.length > 0 || penultimateToken.value === "(" && lastToken.value === ")";
|
181
|
+
}
|
182
|
+
|
143
183
|
/**
|
144
184
|
* Determines if a node is or contains an assignment expression
|
145
185
|
* @param {ASTNode} node - The node to be checked.
|
@@ -175,9 +215,9 @@ module.exports = {
|
|
175
215
|
return node.argument && containsAssignment(node.argument);
|
176
216
|
} else if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") {
|
177
217
|
return containsAssignment(node.body);
|
178
|
-
} else {
|
179
|
-
return containsAssignment(node);
|
180
218
|
}
|
219
|
+
return containsAssignment(node);
|
220
|
+
|
181
221
|
}
|
182
222
|
|
183
223
|
/**
|
@@ -326,6 +366,10 @@ module.exports = {
|
|
326
366
|
* @private
|
327
367
|
*/
|
328
368
|
function dryUnaryUpdate(node) {
|
369
|
+
if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") {
|
370
|
+
return;
|
371
|
+
}
|
372
|
+
|
329
373
|
if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) {
|
330
374
|
report(node.argument);
|
331
375
|
}
|
@@ -340,7 +384,8 @@ module.exports = {
|
|
340
384
|
function dryCallNew(node) {
|
341
385
|
if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !(
|
342
386
|
node.type === "CallExpression" &&
|
343
|
-
node.callee.type === "FunctionExpression"
|
387
|
+
(node.callee.type === "FunctionExpression" ||
|
388
|
+
node.callee.type === "NewExpression" && !isNewExpressionWithParens(node.callee)) &&
|
344
389
|
|
345
390
|
// One set of parentheses are allowed for a function expression
|
346
391
|
!hasDoubleExcessParens(node.callee)
|
@@ -368,13 +413,17 @@ module.exports = {
|
|
368
413
|
*/
|
369
414
|
function dryBinaryLogical(node) {
|
370
415
|
const prec = precedence(node);
|
371
|
-
const
|
416
|
+
const leftPrecedence = precedence(node.left);
|
417
|
+
const rightPrecedence = precedence(node.right);
|
418
|
+
const isExponentiation = node.operator === "**";
|
419
|
+
const shouldSkipLeft = (NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression")) ||
|
420
|
+
node.left.type === "UnaryExpression" && isExponentiation;
|
372
421
|
const shouldSkipRight = NESTED_BINARY && (node.right.type === "BinaryExpression" || node.right.type === "LogicalExpression");
|
373
422
|
|
374
|
-
if (!shouldSkipLeft && hasExcessParens(node.left) &&
|
423
|
+
if (!shouldSkipLeft && hasExcessParens(node.left) && (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation))) {
|
375
424
|
report(node.left);
|
376
425
|
}
|
377
|
-
if (!shouldSkipRight && hasExcessParens(node.right) &&
|
426
|
+
if (!shouldSkipRight && hasExcessParens(node.right) && (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation))) {
|
378
427
|
report(node.right);
|
379
428
|
}
|
380
429
|
}
|
@@ -508,8 +557,7 @@ module.exports = {
|
|
508
557
|
!(
|
509
558
|
(node.object.type === "Literal" &&
|
510
559
|
typeof node.object.value === "number" &&
|
511
|
-
astUtils.isDecimalInteger(node.object))
|
512
|
-
||
|
560
|
+
astUtils.isDecimalInteger(node.object)) ||
|
513
561
|
|
514
562
|
// RegExp literal is allowed to have parens (#1589)
|
515
563
|
(node.object.type === "Literal" && node.object.regex)
|
@@ -64,10 +64,10 @@ module.exports = {
|
|
64
64
|
|
65
65
|
if (!valid) {
|
66
66
|
context.report({ node, message: "Move {{type}} declaration to {{body}} root.", data: {
|
67
|
-
type: (node.type === "FunctionDeclaration"
|
68
|
-
"function" : "variable"),
|
69
|
-
body: (body.type === "Program"
|
70
|
-
"program" : "function body")
|
67
|
+
type: (node.type === "FunctionDeclaration"
|
68
|
+
? "function" : "variable"),
|
69
|
+
body: (body.type === "Program"
|
70
|
+
? "program" : "function body")
|
71
71
|
} });
|
72
72
|
}
|
73
73
|
}
|
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Requirements
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
const astUtils = require("../ast-utils");
|
14
|
+
|
9
15
|
//------------------------------------------------------------------------------
|
10
16
|
// Constants
|
11
17
|
//------------------------------------------------------------------------------
|
@@ -13,7 +19,7 @@
|
|
13
19
|
const ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/;
|
14
20
|
const IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg;
|
15
21
|
const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg;
|
16
|
-
const LINE_BREAK =
|
22
|
+
const LINE_BREAK = astUtils.createGlobalLinebreakMatcher();
|
17
23
|
|
18
24
|
//------------------------------------------------------------------------------
|
19
25
|
// Rule Definition
|
@@ -32,22 +32,22 @@ module.exports = {
|
|
32
32
|
* @returns {void}
|
33
33
|
*/
|
34
34
|
function report(node) {
|
35
|
-
const
|
35
|
+
const message = node.parent.type === "BlockStatement" ? "Nested block is redundant." : "Block is redundant.";
|
36
36
|
|
37
|
-
context.report({ node, message
|
38
|
-
"Block is redundant." :
|
39
|
-
"Nested block is redundant."
|
40
|
-
});
|
37
|
+
context.report({ node, message });
|
41
38
|
}
|
42
39
|
|
43
40
|
/**
|
44
|
-
* Checks for any ocurrence of BlockStatement
|
45
|
-
* @
|
41
|
+
* Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear
|
42
|
+
* @param {ASTNode} node The node to check
|
43
|
+
* @returns {boolean} True if the node is a lone block.
|
46
44
|
*/
|
47
|
-
function isLoneBlock() {
|
48
|
-
|
45
|
+
function isLoneBlock(node) {
|
46
|
+
return node.parent.type === "BlockStatement" ||
|
47
|
+
node.parent.type === "Program" ||
|
49
48
|
|
50
|
-
|
49
|
+
// Don't report blocks in switch cases if the block is the only statement of the case.
|
50
|
+
node.parent.type === "SwitchCase" && !(node.parent.consequent[0] === node && node.parent.consequent.length === 1);
|
51
51
|
}
|
52
52
|
|
53
53
|
/**
|
@@ -148,13 +148,7 @@ module.exports = {
|
|
148
148
|
* @returns {Token} The operator token of the node.
|
149
149
|
*/
|
150
150
|
function getOperatorToken(node) {
|
151
|
-
|
152
|
-
|
153
|
-
while (token.value === ")") {
|
154
|
-
token = sourceCode.getTokenAfter(token);
|
155
|
-
}
|
156
|
-
|
157
|
-
return token;
|
151
|
+
return sourceCode.getTokenAfter(node.left, astUtils.isNotClosingParenToken);
|
158
152
|
}
|
159
153
|
|
160
154
|
/**
|
@@ -153,11 +153,11 @@ module.exports = {
|
|
153
153
|
|
154
154
|
// "var utils = require('./utils');"
|
155
155
|
return REQ_FILE;
|
156
|
-
} else {
|
157
|
-
|
158
|
-
// "var async = require('async');"
|
159
|
-
return REQ_MODULE;
|
160
156
|
}
|
157
|
+
|
158
|
+
// "var async = require('async');"
|
159
|
+
return REQ_MODULE;
|
160
|
+
|
161
161
|
}
|
162
162
|
|
163
163
|
/**
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to check use of chained assignment expressions
|
3
|
+
* @author Stewart Rand
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Rule Definition
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
module.exports = {
|
14
|
+
meta: {
|
15
|
+
docs: {
|
16
|
+
description: "disallow use of chained assignment expressions",
|
17
|
+
category: "Stylistic Issues",
|
18
|
+
recommended: false
|
19
|
+
},
|
20
|
+
schema: []
|
21
|
+
},
|
22
|
+
|
23
|
+
create(context) {
|
24
|
+
|
25
|
+
//--------------------------------------------------------------------------
|
26
|
+
// Public
|
27
|
+
//--------------------------------------------------------------------------
|
28
|
+
|
29
|
+
return {
|
30
|
+
AssignmentExpression(node) {
|
31
|
+
if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) {
|
32
|
+
context.report({
|
33
|
+
node,
|
34
|
+
message: "Unexpected chained assignment."
|
35
|
+
});
|
36
|
+
}
|
37
|
+
}
|
38
|
+
};
|
39
|
+
|
40
|
+
}
|
41
|
+
};
|
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
const astUtils = require("../ast-utils");
|
9
|
+
|
8
10
|
//------------------------------------------------------------------------------
|
9
11
|
// Rule Definition
|
10
12
|
//------------------------------------------------------------------------------
|
@@ -93,7 +95,8 @@ module.exports = {
|
|
93
95
|
const sourceCode = context.getSourceCode(),
|
94
96
|
source = sourceCode.getText(),
|
95
97
|
allComments = sourceCode.getAllComments(),
|
96
|
-
|
98
|
+
JOINED_LINEBEAKS = Array.from(astUtils.LINEBREAKS).join(""),
|
99
|
+
pattern = new RegExp(String.raw`[^ \t${JOINED_LINEBEAKS}].? {2,}`, "g"); // note: repeating space
|
97
100
|
let parent;
|
98
101
|
|
99
102
|
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -39,9 +45,7 @@ module.exports = {
|
|
39
45
|
return {
|
40
46
|
|
41
47
|
Literal(node) {
|
42
|
-
|
43
|
-
|
44
|
-
if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) {
|
48
|
+
if (astUtils.LINEBREAK_MATCHER.test(node.raw) && !isJSXElement(node.parent)) {
|
45
49
|
context.report({ node, message: "Multiline support is limited to browsers supporting ES5 only." });
|
46
50
|
}
|
47
51
|
}
|
@@ -89,13 +89,13 @@ module.exports = {
|
|
89
89
|
BlockStatement: checkForBlock,
|
90
90
|
SwitchStatement: checkForBlock
|
91
91
|
};
|
92
|
-
} else {
|
93
|
-
return {
|
94
|
-
Program: checkForGlobal,
|
95
|
-
FunctionDeclaration: checkForBlock,
|
96
|
-
FunctionExpression: checkForBlock,
|
97
|
-
ArrowFunctionExpression: checkForBlock
|
98
|
-
};
|
99
92
|
}
|
93
|
+
return {
|
94
|
+
Program: checkForGlobal,
|
95
|
+
FunctionDeclaration: checkForBlock,
|
96
|
+
FunctionExpression: checkForBlock,
|
97
|
+
ArrowFunctionExpression: checkForBlock
|
98
|
+
};
|
99
|
+
|
100
100
|
}
|
101
101
|
};
|
@@ -5,23 +5,16 @@
|
|
5
5
|
"use strict";
|
6
6
|
|
7
7
|
//------------------------------------------------------------------------------
|
8
|
-
//
|
8
|
+
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const
|
11
|
+
const astUtils = require("../ast-utils");
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
* @param {sourceCode} sourceCode - The ESLint SourceCode object.
|
17
|
-
* @returns {boolean} Whether or not the node is enclosed in parentheses.
|
18
|
-
*/
|
19
|
-
function isEnclosedInParens(node, sourceCode) {
|
20
|
-
const prevToken = sourceCode.getTokenBefore(node);
|
21
|
-
const nextToken = sourceCode.getTokenAfter(node);
|
13
|
+
//------------------------------------------------------------------------------
|
14
|
+
// Helpers
|
15
|
+
//------------------------------------------------------------------------------
|
22
16
|
|
23
|
-
|
24
|
-
}
|
17
|
+
const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/;
|
25
18
|
|
26
19
|
//------------------------------------------------------------------------------
|
27
20
|
// Rule Definition
|
@@ -48,7 +41,7 @@ module.exports = {
|
|
48
41
|
|
49
42
|
return {
|
50
43
|
AssignmentExpression(node) {
|
51
|
-
if (!always &&
|
44
|
+
if (!always && astUtils.isParenthesised(sourceCode, node)) {
|
52
45
|
return;
|
53
46
|
}
|
54
47
|
|
@@ -35,7 +35,7 @@ module.exports = {
|
|
35
35
|
context.report({
|
36
36
|
node: context.getSourceCode().getFirstToken(node),
|
37
37
|
loc: node.loc,
|
38
|
-
message
|
38
|
+
message
|
39
39
|
});
|
40
40
|
}
|
41
41
|
|
@@ -88,7 +88,7 @@ module.exports = {
|
|
88
88
|
if (isInTailCallPosition(node) && !hasErrorHandler(node)) {
|
89
89
|
reportUnnecessaryAwait(node);
|
90
90
|
}
|
91
|
-
}
|
91
|
+
}
|
92
92
|
};
|
93
93
|
}
|
94
94
|
};
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -57,12 +63,7 @@ module.exports = {
|
|
57
63
|
* @returns {boolean} True if the node has a paren on each side.
|
58
64
|
*/
|
59
65
|
function isParenthesised(node) {
|
60
|
-
|
61
|
-
nextToken = sourceCode.getTokenAfter(node);
|
62
|
-
|
63
|
-
return previousToken && nextToken &&
|
64
|
-
previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
|
65
|
-
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
|
66
|
+
return astUtils.isParenthesised(sourceCode, node);
|
66
67
|
}
|
67
68
|
|
68
69
|
/**
|