eslint 3.14.0 → 3.16.1
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 +68 -0
- package/README.md +1 -1
- package/conf/{eslint.json → eslint-recommended.js} +86 -71
- package/lib/ast-utils.js +192 -24
- package/lib/cli.js +2 -2
- package/lib/code-path-analysis/code-path-state.js +2 -2
- package/lib/config/autoconfig.js +3 -3
- package/lib/config/config-file.js +31 -24
- package/lib/config/config-initializer.js +1 -1
- 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/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/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 +42 -22
- package/lib/rules/capitalized-comments.js +6 -6
- package/lib/rules/comma-spacing.js +16 -16
- 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 +10 -13
- 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 +3 -3
- package/lib/rules/max-lines.js +2 -2
- package/lib/rules/max-statements-per-line.js +7 -6
- 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-cond-assign.js +3 -3
- 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 +8 -0
- package/lib/rules/no-extra-parens.js +29 -8
- 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-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-sequences.js +7 -6
- 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 +8 -3
- 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 +1 -7
- package/lib/rules/no-var.js +11 -0
- 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 +7 -4
- package/lib/rules/prefer-spread.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/quotes.js +10 -6
- package/lib/rules/semi-spacing.js +4 -0
- package/lib/rules/sort-imports.js +4 -4
- package/lib/rules/sort-vars.js +2 -2
- package/lib/rules/space-before-function-paren.js +8 -5
- 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 +25 -18
- 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/glob.js +1 -1
- package/lib/util/source-code-fixer.js +46 -44
- 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
@@ -21,22 +21,17 @@ const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/;
|
|
21
21
|
function parseOptions(options) {
|
22
22
|
let functions = true;
|
23
23
|
let classes = true;
|
24
|
+
let variables = true;
|
24
25
|
|
25
26
|
if (typeof options === "string") {
|
26
27
|
functions = (options !== "nofunc");
|
27
28
|
} else if (typeof options === "object" && options !== null) {
|
28
29
|
functions = options.functions !== false;
|
29
30
|
classes = options.classes !== false;
|
31
|
+
variables = options.variables !== false;
|
30
32
|
}
|
31
33
|
|
32
|
-
return { functions, classes };
|
33
|
-
}
|
34
|
-
|
35
|
-
/**
|
36
|
-
* @returns {boolean} `false`.
|
37
|
-
*/
|
38
|
-
function alwaysFalse() {
|
39
|
-
return false;
|
34
|
+
return { functions, classes, variables };
|
40
35
|
}
|
41
36
|
|
42
37
|
/**
|
@@ -64,14 +59,16 @@ function isOuterClass(variable, reference) {
|
|
64
59
|
}
|
65
60
|
|
66
61
|
/**
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
62
|
+
* Checks whether or not a given variable is a variable declaration in an upper function scope.
|
63
|
+
* @param {escope.Variable} variable - A variable to check.
|
64
|
+
* @param {escope.Reference} reference - A reference to check.
|
65
|
+
* @returns {boolean} `true` if the variable is a variable declaration.
|
66
|
+
*/
|
67
|
+
function isOuterVariable(variable, reference) {
|
68
|
+
return (
|
69
|
+
variable.defs[0].type === "Variable" &&
|
70
|
+
variable.scope.variableScope !== reference.from.variableScope
|
71
|
+
);
|
75
72
|
}
|
76
73
|
|
77
74
|
/**
|
@@ -155,7 +152,8 @@ module.exports = {
|
|
155
152
|
type: "object",
|
156
153
|
properties: {
|
157
154
|
functions: { type: "boolean" },
|
158
|
-
classes: { type: "boolean" }
|
155
|
+
classes: { type: "boolean" },
|
156
|
+
variables: { type: "boolean" }
|
159
157
|
},
|
160
158
|
additionalProperties: false
|
161
159
|
}
|
@@ -167,17 +165,23 @@ module.exports = {
|
|
167
165
|
create(context) {
|
168
166
|
const options = parseOptions(context.options[0]);
|
169
167
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
168
|
+
/**
|
169
|
+
* Determines whether a given use-before-define case should be reportedaccording to the options.
|
170
|
+
* @param {escope.Variable} variable The variable that gets used before being defined
|
171
|
+
* @param {escope.Reference} reference The reference to the variable
|
172
|
+
* @returns {boolean} `true` if the usage should be reported
|
173
|
+
*/
|
174
|
+
function isForbidden(variable, reference) {
|
175
|
+
if (isFunction(variable)) {
|
176
|
+
return options.functions;
|
177
|
+
}
|
178
|
+
if (isOuterClass(variable, reference)) {
|
179
|
+
return options.classes;
|
180
|
+
}
|
181
|
+
if (isOuterVariable(variable, reference)) {
|
182
|
+
return options.variables;
|
183
|
+
}
|
184
|
+
return true;
|
181
185
|
}
|
182
186
|
|
183
187
|
/**
|
@@ -200,7 +204,7 @@ module.exports = {
|
|
200
204
|
!variable ||
|
201
205
|
variable.identifiers.length === 0 ||
|
202
206
|
(variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) ||
|
203
|
-
|
207
|
+
!isForbidden(variable, reference)
|
204
208
|
) {
|
205
209
|
return;
|
206
210
|
}
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -40,9 +46,8 @@ module.exports = {
|
|
40
46
|
message: MESSAGE_UNNECESSARY_COMPUTED,
|
41
47
|
data: { property: sourceCode.getText(key) },
|
42
48
|
fix(fixer) {
|
43
|
-
const leftSquareBracket = sourceCode.getFirstToken(node,
|
44
|
-
const rightSquareBracket = sourceCode.
|
45
|
-
|
49
|
+
const leftSquareBracket = sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken);
|
50
|
+
const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken);
|
46
51
|
const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1);
|
47
52
|
|
48
53
|
if (tokensBetween.slice(0, -1).some((token, index) => sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) {
|
@@ -23,6 +23,15 @@ function isConcatenation(node) {
|
|
23
23
|
return node.type === "BinaryExpression" && node.operator === "+";
|
24
24
|
}
|
25
25
|
|
26
|
+
/**
|
27
|
+
* Checks if the given token is a `+` token or not.
|
28
|
+
* @param {Token} token - The token to check.
|
29
|
+
* @returns {boolean} `true` if the token is a `+` token.
|
30
|
+
*/
|
31
|
+
function isConcatOperatorToken(token) {
|
32
|
+
return token.value === "+" && token.type === "Punctuator";
|
33
|
+
}
|
34
|
+
|
26
35
|
/**
|
27
36
|
* Get's the right most node on the left side of a BinaryExpression with + operator.
|
28
37
|
* @param {ASTNode} node - A BinaryExpression node to check.
|
@@ -85,13 +94,7 @@ module.exports = {
|
|
85
94
|
astUtils.isStringLiteral(right) &&
|
86
95
|
astUtils.isTokenOnSameLine(left, right)
|
87
96
|
) {
|
88
|
-
|
89
|
-
// move warning location to operator
|
90
|
-
let operatorToken = sourceCode.getTokenAfter(left);
|
91
|
-
|
92
|
-
while (operatorToken.value !== "+") {
|
93
|
-
operatorToken = sourceCode.getTokenAfter(operatorToken);
|
94
|
-
}
|
97
|
+
const operatorToken = sourceCode.getFirstTokenBetween(left, right, isConcatOperatorToken);
|
95
98
|
|
96
99
|
context.report({
|
97
100
|
node,
|
@@ -24,7 +24,7 @@ function union(setA, setB) {
|
|
24
24
|
}());
|
25
25
|
}
|
26
26
|
|
27
|
-
const VALID_STRING_ESCAPES = new Set("\\nrvtbfux
|
27
|
+
const VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS);
|
28
28
|
const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnrsStvwWxu0123456789]");
|
29
29
|
const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()B"));
|
30
30
|
|
@@ -45,13 +45,7 @@ function remove(array, element) {
|
|
45
45
|
* @returns {boolean} `true` if the node is removeable.
|
46
46
|
*/
|
47
47
|
function isRemovable(node) {
|
48
|
-
|
49
|
-
|
50
|
-
return (
|
51
|
-
parent.type === "Program" ||
|
52
|
-
parent.type === "BlockStatement" ||
|
53
|
-
parent.type === "SwitchCase"
|
54
|
-
);
|
48
|
+
return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type);
|
55
49
|
}
|
56
50
|
|
57
51
|
/**
|
package/lib/rules/no-var.js
CHANGED
@@ -209,6 +209,7 @@ module.exports = {
|
|
209
209
|
* - A variable is used from a closure within a loop.
|
210
210
|
* - A variable might be used before it is assigned within a loop.
|
211
211
|
* - A variable might be used in TDZ.
|
212
|
+
* - A variable is declared in statement position (e.g. a single-line `IfStatement`)
|
212
213
|
*
|
213
214
|
* ## A variable is declared on a SwitchCase node.
|
214
215
|
*
|
@@ -270,6 +271,16 @@ module.exports = {
|
|
270
271
|
}
|
271
272
|
}
|
272
273
|
|
274
|
+
if (
|
275
|
+
!isLoopAssignee(node) &&
|
276
|
+
!(node.parent.type === "ForStatement" && node.parent.init === node) &&
|
277
|
+
!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)
|
278
|
+
) {
|
279
|
+
|
280
|
+
// If the declaration is not in a block, e.g. `if (foo) var bar = 1;`, then it can't be fixed.
|
281
|
+
return false;
|
282
|
+
}
|
283
|
+
|
273
284
|
return true;
|
274
285
|
}
|
275
286
|
|
@@ -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,12 +182,15 @@ 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,
|
189
189
|
loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column },
|
190
190
|
fix(fixer) {
|
191
|
+
|
192
|
+
// FIXME: The start of this range is sometimes larger than the end.
|
193
|
+
// https://github.com/eslint/eslint/issues/8116
|
191
194
|
return fixer.replaceTextRange([openBrace.end, nextToken.start - nextToken.loc.start.column], "\n");
|
192
195
|
},
|
193
196
|
message: NEVER_MESSAGE
|
@@ -195,7 +198,7 @@ module.exports = {
|
|
195
198
|
}
|
196
199
|
|
197
200
|
if (blockHasBottomPadding) {
|
198
|
-
const previousToken = sourceCode.
|
201
|
+
const previousToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
199
202
|
|
200
203
|
context.report({
|
201
204
|
node,
|
@@ -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,15 +257,16 @@ 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({
|
@@ -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-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
|
|