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
@@ -4,6 +4,10 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Requirements
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
7
11
|
const astUtils = require("../ast-utils");
|
8
12
|
|
9
13
|
//------------------------------------------------------------------------------
|
@@ -29,21 +33,6 @@ module.exports = {
|
|
29
33
|
// Helpers
|
30
34
|
//--------------------------------------------------------------------------
|
31
35
|
|
32
|
-
/**
|
33
|
-
* Finds opening bracket token of node's computed property
|
34
|
-
* @param {ASTNode} node - the node to check
|
35
|
-
* @returns {Token} opening bracket token of node's computed property
|
36
|
-
* @private
|
37
|
-
*/
|
38
|
-
function findOpeningBracket(node) {
|
39
|
-
let token = sourceCode.getTokenBefore(node.property);
|
40
|
-
|
41
|
-
while (token.value !== "[") {
|
42
|
-
token = sourceCode.getTokenBefore(token);
|
43
|
-
}
|
44
|
-
return token;
|
45
|
-
}
|
46
|
-
|
47
36
|
/**
|
48
37
|
* Reports whitespace before property token
|
49
38
|
* @param {ASTNode} node - the node to report in the event of an error
|
@@ -87,7 +76,7 @@ module.exports = {
|
|
87
76
|
}
|
88
77
|
|
89
78
|
if (node.computed) {
|
90
|
-
rightToken =
|
79
|
+
rightToken = sourceCode.getTokenBefore(node.property, astUtils.isOpeningBracketToken);
|
91
80
|
leftToken = sourceCode.getTokenBefore(rightToken);
|
92
81
|
} else {
|
93
82
|
rightToken = sourceCode.getFirstToken(node.property);
|
@@ -128,8 +128,8 @@ module.exports = {
|
|
128
128
|
const options = normalizedOptions[node.type];
|
129
129
|
const openBrace = sourceCode.getFirstToken(node);
|
130
130
|
const closeBrace = sourceCode.getLastToken(node);
|
131
|
-
let first = sourceCode.
|
132
|
-
let last = sourceCode.
|
131
|
+
let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
|
132
|
+
let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
133
133
|
const needsLinebreaks = (
|
134
134
|
node.properties.length >= options.minProperties ||
|
135
135
|
(
|
@@ -206,14 +206,8 @@ module.exports = {
|
|
206
206
|
*/
|
207
207
|
function getClosingBraceOfObject(node) {
|
208
208
|
const lastProperty = node.properties[node.properties.length - 1];
|
209
|
-
let token = sourceCode.getTokenAfter(lastProperty);
|
210
209
|
|
211
|
-
|
212
|
-
while (token.type !== "Punctuator" || token.value !== "}") {
|
213
|
-
token = sourceCode.getTokenAfter(token);
|
214
|
-
}
|
215
|
-
|
216
|
-
return token;
|
210
|
+
return sourceCode.getTokenAfter(lastProperty, astUtils.isClosingBraceToken);
|
217
211
|
}
|
218
212
|
|
219
213
|
/**
|
@@ -254,15 +248,9 @@ module.exports = {
|
|
254
248
|
firstSpecifier = node.specifiers[1];
|
255
249
|
}
|
256
250
|
|
257
|
-
const first = sourceCode.getTokenBefore(firstSpecifier)
|
258
|
-
|
259
|
-
|
260
|
-
// to support a trailing comma.
|
261
|
-
if (last.value === ",") {
|
262
|
-
last = sourceCode.getTokenAfter(last);
|
263
|
-
}
|
264
|
-
|
265
|
-
const second = sourceCode.getTokenAfter(first),
|
251
|
+
const first = sourceCode.getTokenBefore(firstSpecifier),
|
252
|
+
last = sourceCode.getTokenAfter(lastSpecifier, astUtils.isNotCommaToken),
|
253
|
+
second = sourceCode.getTokenAfter(first),
|
266
254
|
penultimate = sourceCode.getTokenBefore(last);
|
267
255
|
|
268
256
|
validateBraceSpacing(node, first, second, penultimate, last);
|
@@ -280,15 +268,9 @@ module.exports = {
|
|
280
268
|
|
281
269
|
const firstSpecifier = node.specifiers[0],
|
282
270
|
lastSpecifier = node.specifiers[node.specifiers.length - 1],
|
283
|
-
first = sourceCode.getTokenBefore(firstSpecifier)
|
284
|
-
|
285
|
-
|
286
|
-
// to support a trailing comma.
|
287
|
-
if (last.value === ",") {
|
288
|
-
last = sourceCode.getTokenAfter(last);
|
289
|
-
}
|
290
|
-
|
291
|
-
const second = sourceCode.getTokenAfter(first),
|
271
|
+
first = sourceCode.getTokenBefore(firstSpecifier),
|
272
|
+
last = sourceCode.getTokenAfter(lastSpecifier, astUtils.isNotCommaToken),
|
273
|
+
second = sourceCode.getTokenAfter(first),
|
292
274
|
penultimate = sourceCode.getTokenBefore(last);
|
293
275
|
|
294
276
|
validateBraceSpacing(node, first, second, penultimate, last);
|
@@ -34,9 +34,9 @@ module.exports = {
|
|
34
34
|
|
35
35
|
create(context) {
|
36
36
|
const allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine);
|
37
|
-
const errorMessage = allowSameLine
|
38
|
-
"Object properties must go on a new line if they aren't all on the same line."
|
39
|
-
"Object properties must go on a new line.";
|
37
|
+
const errorMessage = allowSameLine
|
38
|
+
? "Object properties must go on a new line if they aren't all on the same line."
|
39
|
+
: "Object properties must go on a new line.";
|
40
40
|
|
41
41
|
const sourceCode = context.getSourceCode();
|
42
42
|
|
@@ -215,8 +215,8 @@ module.exports = {
|
|
215
215
|
* @returns {Object} A fix for this node
|
216
216
|
*/
|
217
217
|
function makeFunctionShorthand(fixer, node) {
|
218
|
-
const firstKeyToken = node.computed ? sourceCode.
|
219
|
-
const lastKeyToken = node.computed ? sourceCode.
|
218
|
+
const firstKeyToken = node.computed ? sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken) : sourceCode.getFirstToken(node.key);
|
219
|
+
const lastKeyToken = node.computed ? sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken) : sourceCode.getLastToken(node.key);
|
220
220
|
const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
|
221
221
|
let keyPrefix = "";
|
222
222
|
|
@@ -231,15 +231,15 @@ module.exports = {
|
|
231
231
|
const tokenBeforeParams = node.value.generator ? sourceCode.getTokenAfter(functionToken) : functionToken;
|
232
232
|
|
233
233
|
return fixer.replaceTextRange([firstKeyToken.range[0], tokenBeforeParams.range[1]], keyPrefix + keyText);
|
234
|
-
} else {
|
235
|
-
const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>");
|
236
|
-
const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken);
|
237
|
-
const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")";
|
238
|
-
const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]);
|
239
|
-
const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`;
|
240
|
-
|
241
|
-
return fixer.replaceTextRange([firstKeyToken.range[0], arrowToken.range[1]], keyPrefix + keyText + newParamText);
|
242
234
|
}
|
235
|
+
const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>");
|
236
|
+
const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken);
|
237
|
+
const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")";
|
238
|
+
const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]);
|
239
|
+
const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`;
|
240
|
+
|
241
|
+
return fixer.replaceTextRange([firstKeyToken.range[0], arrowToken.range[1]], keyPrefix + keyText + newParamText);
|
242
|
+
|
243
243
|
}
|
244
244
|
|
245
245
|
/**
|
@@ -27,7 +27,7 @@ function isCommutativeOperatorWithShorthand(operator) {
|
|
27
27
|
* a shorthand form.
|
28
28
|
*/
|
29
29
|
function isNonCommutativeOperatorWithShorthand(operator) {
|
30
|
-
return ["+", "-", "/", "%", "<<", ">>", ">>>"].indexOf(operator) >= 0;
|
30
|
+
return ["+", "-", "/", "%", "<<", ">>", ">>>", "**"].indexOf(operator) >= 0;
|
31
31
|
}
|
32
32
|
|
33
33
|
//------------------------------------------------------------------------------
|
@@ -108,7 +108,7 @@ module.exports = {
|
|
108
108
|
* @returns {Token} The operator token in the node
|
109
109
|
*/
|
110
110
|
function getOperatorToken(node) {
|
111
|
-
return sourceCode.
|
111
|
+
return sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
|
112
112
|
}
|
113
113
|
|
114
114
|
/**
|
@@ -5,14 +5,16 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
8
12
|
const astUtils = require("../ast-utils");
|
9
13
|
|
10
14
|
//------------------------------------------------------------------------------
|
11
15
|
// Rule Definition
|
12
16
|
//------------------------------------------------------------------------------
|
13
17
|
|
14
|
-
const LINEBREAK_REGEX = /\r\n|\r|\n|\u2028|\u2029/g;
|
15
|
-
|
16
18
|
module.exports = {
|
17
19
|
meta: {
|
18
20
|
docs: {
|
@@ -85,7 +87,7 @@ module.exports = {
|
|
85
87
|
if (hasLinebreakBefore !== hasLinebreakAfter && desiredStyle !== "none") {
|
86
88
|
|
87
89
|
// If there is a comment before and after the operator, don't do a fix.
|
88
|
-
if (sourceCode.
|
90
|
+
if (sourceCode.getTokenBefore(operatorToken, { includeComments: true }) !== tokenBefore && sourceCode.getTokenAfter(operatorToken, { includeComments: true }) !== tokenAfter) {
|
89
91
|
return null;
|
90
92
|
}
|
91
93
|
|
@@ -100,6 +102,7 @@ module.exports = {
|
|
100
102
|
newTextBefore = textAfter;
|
101
103
|
newTextAfter = textBefore;
|
102
104
|
} else {
|
105
|
+
const LINEBREAK_REGEX = astUtils.createGlobalLinebreakMatcher();
|
103
106
|
|
104
107
|
// Otherwise, if no linebreak is desired and no comments interfere, replace the linebreaks with empty strings.
|
105
108
|
newTextBefore = desiredStyle === "before" || textBefore.trim() ? textBefore : textBefore.replace(LINEBREAK_REGEX, "");
|
@@ -129,19 +132,14 @@ module.exports = {
|
|
129
132
|
* @returns {void}
|
130
133
|
*/
|
131
134
|
function validateNode(node, leftSide) {
|
132
|
-
let leftToken = sourceCode.getLastToken(leftSide);
|
133
|
-
let operatorToken = sourceCode.getTokenAfter(leftToken);
|
134
135
|
|
135
136
|
// When the left part of a binary expression is a single expression wrapped in
|
136
137
|
// parentheses (ex: `(a) + b`), leftToken will be the last token of the expression
|
137
138
|
// and operatorToken will be the closing parenthesis.
|
138
139
|
// The leftToken should be the last closing parenthesis, and the operatorToken
|
139
140
|
// should be the token right after that.
|
140
|
-
|
141
|
-
|
142
|
-
operatorToken = sourceCode.getTokenAfter(operatorToken);
|
143
|
-
}
|
144
|
-
|
141
|
+
const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken);
|
142
|
+
const leftToken = sourceCode.getTokenBefore(operatorToken);
|
145
143
|
const rightToken = sourceCode.getTokenAfter(operatorToken);
|
146
144
|
const operator = operatorToken.value;
|
147
145
|
const operatorStyleOverride = styleOverrides[operator];
|
@@ -101,7 +101,7 @@ module.exports = {
|
|
101
101
|
let first = token;
|
102
102
|
|
103
103
|
do {
|
104
|
-
first = sourceCode.
|
104
|
+
first = sourceCode.getTokenAfter(first, { includeComments: true });
|
105
105
|
} while (isComment(first) && first.loc.start.line === tokenStartLine);
|
106
106
|
|
107
107
|
const firstLine = first.loc.start.line;
|
@@ -120,7 +120,7 @@ module.exports = {
|
|
120
120
|
let last = token;
|
121
121
|
|
122
122
|
do {
|
123
|
-
last = sourceCode.
|
123
|
+
last = sourceCode.getTokenBefore(last, { includeComments: true });
|
124
124
|
} while (isComment(last) && last.loc.end.line === blockEnd);
|
125
125
|
|
126
126
|
const lastLine = last.loc.end.line;
|
@@ -182,7 +182,7 @@ module.exports = {
|
|
182
182
|
}
|
183
183
|
} else {
|
184
184
|
if (blockHasTopPadding) {
|
185
|
-
const nextToken = sourceCode.
|
185
|
+
const nextToken = sourceCode.getTokenAfter(openBrace, { includeComments: true });
|
186
186
|
|
187
187
|
context.report({
|
188
188
|
node,
|
@@ -195,7 +195,7 @@ module.exports = {
|
|
195
195
|
}
|
196
196
|
|
197
197
|
if (blockHasBottomPadding) {
|
198
|
-
const previousToken = sourceCode.
|
198
|
+
const previousToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
199
199
|
|
200
200
|
context.report({
|
201
201
|
node,
|
@@ -0,0 +1,124 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview restrict values that can be used as Promise rejection reasons
|
3
|
+
* @author Teddy Katz
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const astUtils = require("../ast-utils");
|
8
|
+
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Rule Definition
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
module.exports = {
|
14
|
+
meta: {
|
15
|
+
docs: {
|
16
|
+
description: "require using Error objects as Promise rejection reasons",
|
17
|
+
category: "Best Practices",
|
18
|
+
recommended: false
|
19
|
+
},
|
20
|
+
fixable: null,
|
21
|
+
schema: [
|
22
|
+
{
|
23
|
+
type: "object",
|
24
|
+
properties: {
|
25
|
+
allowEmptyReject: { type: "boolean" }
|
26
|
+
},
|
27
|
+
additionalProperties: false
|
28
|
+
}
|
29
|
+
]
|
30
|
+
},
|
31
|
+
|
32
|
+
create(context) {
|
33
|
+
|
34
|
+
const ALLOW_EMPTY_REJECT = context.options.length && context.options[0].allowEmptyReject;
|
35
|
+
|
36
|
+
//----------------------------------------------------------------------
|
37
|
+
// Helpers
|
38
|
+
//----------------------------------------------------------------------
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
|
42
|
+
* @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
|
43
|
+
* @returns {void}
|
44
|
+
*/
|
45
|
+
function checkRejectCall(callExpression) {
|
46
|
+
if (!callExpression.arguments.length && ALLOW_EMPTY_REJECT) {
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
if (
|
50
|
+
!callExpression.arguments.length ||
|
51
|
+
!astUtils.couldBeError(callExpression.arguments[0]) ||
|
52
|
+
callExpression.arguments[0].type === "Identifier" && callExpression.arguments[0].name === "undefined"
|
53
|
+
) {
|
54
|
+
context.report({
|
55
|
+
node: callExpression,
|
56
|
+
message: "Expected the Promise rejection reason to be an Error."
|
57
|
+
});
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Determines whether a function call is a Promise.reject() call
|
63
|
+
* @param {ASTNode} node A CallExpression node
|
64
|
+
* @returns {boolean} `true` if the call is a Promise.reject() call
|
65
|
+
*/
|
66
|
+
function isPromiseRejectCall(node) {
|
67
|
+
return node.callee.type === "MemberExpression" &&
|
68
|
+
node.callee.object.type === "Identifier" && node.callee.object.name === "Promise" &&
|
69
|
+
node.callee.property.type === "Identifier" && node.callee.property.name === "reject";
|
70
|
+
}
|
71
|
+
|
72
|
+
//----------------------------------------------------------------------
|
73
|
+
// Public
|
74
|
+
//----------------------------------------------------------------------
|
75
|
+
|
76
|
+
return {
|
77
|
+
|
78
|
+
// Check `Promise.reject(value)` calls.
|
79
|
+
CallExpression(node) {
|
80
|
+
if (isPromiseRejectCall(node)) {
|
81
|
+
checkRejectCall(node);
|
82
|
+
}
|
83
|
+
},
|
84
|
+
|
85
|
+
/*
|
86
|
+
* Check for `new Promise((resolve, reject) => {})`, and check for reject() calls.
|
87
|
+
* This function is run on "NewExpression:exit" instead of "NewExpression" to ensure that
|
88
|
+
* the nodes in the expression already have the `parent` property.
|
89
|
+
*/
|
90
|
+
"NewExpression:exit"(node) {
|
91
|
+
if (
|
92
|
+
node.callee.type === "Identifier" && node.callee.name === "Promise" &&
|
93
|
+
node.arguments.length && astUtils.isFunction(node.arguments[0]) &&
|
94
|
+
node.arguments[0].params.length > 1 && node.arguments[0].params[1].type === "Identifier"
|
95
|
+
) {
|
96
|
+
context.getDeclaredVariables(node.arguments[0])
|
97
|
+
|
98
|
+
/*
|
99
|
+
* Find the first variable that matches the second parameter's name.
|
100
|
+
* If the first parameter has the same name as the second parameter, then the variable will actually
|
101
|
+
* be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
|
102
|
+
* by the second parameter. It's not possible for an expression with the variable to be evaluated before
|
103
|
+
* the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
|
104
|
+
* default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
|
105
|
+
* this case.
|
106
|
+
*/
|
107
|
+
.find(variable => variable.name === node.arguments[0].params[1].name)
|
108
|
+
|
109
|
+
// Get the references to that variable.
|
110
|
+
.references
|
111
|
+
|
112
|
+
// Only check the references that read the parameter's value.
|
113
|
+
.filter(ref => ref.isRead())
|
114
|
+
|
115
|
+
// Only check the references that are used as the callee in a function call, e.g. `reject(foo)`.
|
116
|
+
.filter(ref => ref.identifier.parent.type === "CallExpression" && ref.identifier === ref.identifier.parent.callee)
|
117
|
+
|
118
|
+
// Check the argument of the function call to determine whether it's an Error.
|
119
|
+
.forEach(ref => checkRejectCall(ref.identifier.parent));
|
120
|
+
}
|
121
|
+
}
|
122
|
+
};
|
123
|
+
}
|
124
|
+
};
|
@@ -108,7 +108,7 @@ module.exports = {
|
|
108
108
|
return null;
|
109
109
|
}
|
110
110
|
|
111
|
-
const propertyDot = sourceCode.
|
111
|
+
const propertyDot = sourceCode.getFirstTokenBetween(applied, node.callee.property, token => token.value === ".");
|
112
112
|
|
113
113
|
return fixer.replaceTextRange([propertyDot.range[0], node.range[1]], `(...${sourceCode.getText(node.arguments[1])})`);
|
114
114
|
}
|
@@ -157,7 +157,7 @@ module.exports = {
|
|
157
157
|
}
|
158
158
|
|
159
159
|
if (isConcatenation(currentNode) && hasStringLiteral(currentNode) && hasNonStringLiteral(currentNode)) {
|
160
|
-
const plusSign = sourceCode.
|
160
|
+
const plusSign = sourceCode.getFirstTokenBetween(currentNode.left, currentNode.right, token => token.value === "+");
|
161
161
|
const textBeforePlus = getTextBetween(currentNode.left, plusSign);
|
162
162
|
const textAfterPlus = getTextBetween(plusSign, currentNode.right);
|
163
163
|
const leftEndsWithCurly = endsWithTemplateCurly(currentNode.left);
|
package/lib/rules/quotes.js
CHANGED
@@ -33,6 +33,9 @@ const QUOTE_SETTINGS = {
|
|
33
33
|
}
|
34
34
|
};
|
35
35
|
|
36
|
+
// An unescaped newline is a newline preceded by an even number of backslashes.
|
37
|
+
const UNESCAPED_LINEBREAK_PATTERN = new RegExp(String.raw`(^|[^\\])(\\\\)*[${Array.from(astUtils.LINEBREAKS).join("")}]`);
|
38
|
+
|
36
39
|
/**
|
37
40
|
* Switches quoting of javascript string between ' " and `
|
38
41
|
* escaping and unescaping as necessary.
|
@@ -254,22 +257,23 @@ module.exports = {
|
|
254
257
|
TemplateLiteral(node) {
|
255
258
|
|
256
259
|
// If backticks are expected or it's a tagged template, then this shouldn't throw an errors
|
257
|
-
if (
|
260
|
+
if (
|
261
|
+
allowTemplateLiterals ||
|
262
|
+
quoteOption === "backtick" ||
|
263
|
+
node.parent.type === "TaggedTemplateExpression" && node === node.parent.quasi
|
264
|
+
) {
|
258
265
|
return;
|
259
266
|
}
|
260
267
|
|
261
|
-
|
262
|
-
|
263
|
-
* An unescaped newline is a newline preceded by an even number of backslashes.
|
264
|
-
*/
|
265
|
-
const shouldWarn = node.quasis.length === 1 && !/(^|[^\\])(\\\\)*[\r\n\u2028\u2029]/.test(node.quasis[0].value.raw);
|
268
|
+
// A warning should be produced if the template literal only has one TemplateElement, and has no unescaped newlines.
|
269
|
+
const shouldWarn = node.quasis.length === 1 && !UNESCAPED_LINEBREAK_PATTERN.test(node.quasis[0].value.raw);
|
266
270
|
|
267
271
|
if (shouldWarn) {
|
268
272
|
context.report({
|
269
273
|
node,
|
270
274
|
message: "Strings must use {{description}}.",
|
271
275
|
data: {
|
272
|
-
description: settings.description
|
276
|
+
description: settings.description
|
273
277
|
},
|
274
278
|
fix(fixer) {
|
275
279
|
if (isPartOfDirectivePrologue(node)) {
|
@@ -206,6 +206,10 @@ module.exports = {
|
|
206
206
|
DebuggerStatement: checkNode,
|
207
207
|
ReturnStatement: checkNode,
|
208
208
|
ThrowStatement: checkNode,
|
209
|
+
ImportDeclaration: checkNode,
|
210
|
+
ExportNamedDeclaration: checkNode,
|
211
|
+
ExportAllDeclaration: checkNode,
|
212
|
+
ExportDefaultDeclaration: checkNode,
|
209
213
|
ForStatement(node) {
|
210
214
|
if (node.init) {
|
211
215
|
checkSemicolonSpacing(sourceCode.getTokenAfter(node.init), node);
|
@@ -71,9 +71,9 @@ module.exports = {
|
|
71
71
|
return "all";
|
72
72
|
} else if (node.specifiers.length === 1) {
|
73
73
|
return "single";
|
74
|
-
} else {
|
75
|
-
return "multiple";
|
76
74
|
}
|
75
|
+
return "multiple";
|
76
|
+
|
77
77
|
}
|
78
78
|
|
79
79
|
/**
|
@@ -93,9 +93,9 @@ module.exports = {
|
|
93
93
|
function getFirstLocalMemberName(node) {
|
94
94
|
if (node.specifiers[0]) {
|
95
95
|
return node.specifiers[0].local.name;
|
96
|
-
} else {
|
97
|
-
return null;
|
98
96
|
}
|
97
|
+
return null;
|
98
|
+
|
99
99
|
}
|
100
100
|
|
101
101
|
return {
|
package/lib/rules/sort-keys.js
CHANGED
@@ -64,7 +64,7 @@ const isValidOrders = {
|
|
64
64
|
},
|
65
65
|
descIN(a, b) {
|
66
66
|
return isValidOrders.ascIN(b, a);
|
67
|
-
}
|
67
|
+
}
|
68
68
|
};
|
69
69
|
|
70
70
|
//------------------------------------------------------------------------------
|
@@ -147,7 +147,7 @@ module.exports = {
|
|
147
147
|
prevName,
|
148
148
|
order,
|
149
149
|
insensitive: insensitive ? "insensitive " : "",
|
150
|
-
natual: natual ? "natural " : ""
|
150
|
+
natual: natual ? "natural " : ""
|
151
151
|
}
|
152
152
|
});
|
153
153
|
}
|
package/lib/rules/sort-vars.js
CHANGED
@@ -53,9 +53,9 @@ module.exports = {
|
|
53
53
|
if (currenVariableName < lastVariableName) {
|
54
54
|
context.report({ node: decl, message: "Variables within the same declaration block should be sorted alphabetically." });
|
55
55
|
return memo;
|
56
|
-
} else {
|
57
|
-
return decl;
|
58
56
|
}
|
57
|
+
return decl;
|
58
|
+
|
59
59
|
}, node.declarations[0]);
|
60
60
|
}
|
61
61
|
};
|
@@ -4,6 +4,12 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Requirements
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
const astUtils = require("../ast-utils");
|
12
|
+
|
7
13
|
//------------------------------------------------------------------------------
|
8
14
|
// Rule Definition
|
9
15
|
//------------------------------------------------------------------------------
|
@@ -104,7 +110,7 @@ module.exports = {
|
|
104
110
|
const isAnonymousGenerator = node.generator && !isNamed;
|
105
111
|
const isNormalArrow = isArrow && !node.async;
|
106
112
|
const isArrowWithoutParens = isArrow && sourceCode.getFirstToken(node, 1).value !== "(";
|
107
|
-
let forbidSpacing, requireSpacing
|
113
|
+
let forbidSpacing, requireSpacing;
|
108
114
|
|
109
115
|
// isAnonymousGenerator → `generator-star-spacing` should warn it. E.g. `function* () {}`
|
110
116
|
// isNormalArrow → ignore always.
|
@@ -124,10 +130,7 @@ module.exports = {
|
|
124
130
|
requireSpacing = requireAnonymousFunctionSpacing;
|
125
131
|
}
|
126
132
|
|
127
|
-
rightToken = sourceCode.getFirstToken(node);
|
128
|
-
while (rightToken.value !== "(") {
|
129
|
-
rightToken = sourceCode.getTokenAfter(rightToken);
|
130
|
-
}
|
133
|
+
const rightToken = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
|
131
134
|
const leftToken = sourceCode.getTokenBefore(rightToken);
|
132
135
|
const location = leftToken.loc.end;
|
133
136
|
|
@@ -159,7 +162,7 @@ module.exports = {
|
|
159
162
|
return {
|
160
163
|
FunctionDeclaration: validateSpacingBeforeParentheses,
|
161
164
|
FunctionExpression: validateSpacingBeforeParentheses,
|
162
|
-
ArrowFunctionExpression: validateSpacingBeforeParentheses
|
165
|
+
ArrowFunctionExpression: validateSpacingBeforeParentheses
|
163
166
|
};
|
164
167
|
}
|
165
168
|
};
|
@@ -132,9 +132,9 @@ module.exports = {
|
|
132
132
|
return false;
|
133
133
|
}
|
134
134
|
return !isOpenerException(right);
|
135
|
-
} else {
|
136
|
-
return isOpenerException(right);
|
137
135
|
}
|
136
|
+
return isOpenerException(right);
|
137
|
+
|
138
138
|
}
|
139
139
|
|
140
140
|
/**
|
@@ -154,9 +154,9 @@ module.exports = {
|
|
154
154
|
|
155
155
|
if (ALWAYS) {
|
156
156
|
return !isCloserException(left);
|
157
|
-
} else {
|
158
|
-
return isCloserException(left);
|
159
157
|
}
|
158
|
+
return isCloserException(left);
|
159
|
+
|
160
160
|
}
|
161
161
|
|
162
162
|
/**
|
@@ -180,9 +180,9 @@ module.exports = {
|
|
180
180
|
|
181
181
|
if (ALWAYS) {
|
182
182
|
return isOpenerException(right);
|
183
|
-
} else {
|
184
|
-
return !isOpenerException(right);
|
185
183
|
}
|
184
|
+
return !isOpenerException(right);
|
185
|
+
|
186
186
|
}
|
187
187
|
|
188
188
|
/**
|
@@ -206,9 +206,9 @@ module.exports = {
|
|
206
206
|
|
207
207
|
if (ALWAYS) {
|
208
208
|
return isCloserException(left);
|
209
|
-
} else {
|
210
|
-
return !isCloserException(left);
|
211
209
|
}
|
210
|
+
return !isCloserException(left);
|
211
|
+
|
212
212
|
}
|
213
213
|
|
214
214
|
//--------------------------------------------------------------------------
|