eslint 3.15.0 → 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 +32 -0
- package/conf/{eslint.json → eslint-recommended.js} +85 -71
- package/lib/ast-utils.js +185 -19
- package/lib/code-path-analysis/code-path-state.js +2 -2
- package/lib/config/autoconfig.js +3 -3
- package/lib/config/config-file.js +14 -7
- package/lib/config/config-initializer.js +1 -1
- package/lib/config.js +3 -2
- package/lib/eslint.js +4 -4
- 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 +2 -6
- package/lib/rules/capitalized-comments.js +6 -6
- package/lib/rules/comma-spacing.js +3 -3
- 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/generator-star-spacing.js +18 -19
- 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 +7 -6
- package/lib/rules/key-spacing.js +12 -16
- 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/newline-after-var.js +7 -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 +1 -2
- 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-multi-spaces.js +4 -1
- package/lib/rules/no-multi-str.js +7 -3
- 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 +2 -16
- 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 +1 -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 +2 -2
- package/lib/rules/operator-assignment.js +1 -1
- package/lib/rules/operator-linebreak.js +8 -10
- package/lib/rules/padded-blocks.js +4 -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/space-before-function-paren.js +8 -5
- package/lib/rules/spaced-comment.js +2 -2
- package/lib/rules/strict.js +2 -2
- 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/testers/rule-tester.js +13 -6
- 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/source-code-fixer.js +35 -39
- package/lib/util/source-code.js +31 -15
- package/messages/extend-config-missing.txt +3 -0
- package/package.json +2 -2
- package/lib/token-store.js +0 -203
@@ -6,6 +6,8 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
const astUtils = require("../ast-utils");
|
10
|
+
|
9
11
|
//------------------------------------------------------------------------------
|
10
12
|
// Rule Definition
|
11
13
|
//------------------------------------------------------------------------------
|
@@ -47,7 +49,7 @@ module.exports = {
|
|
47
49
|
*/
|
48
50
|
function getPropertyText(node) {
|
49
51
|
const prefix = node.computed ? "[" : ".";
|
50
|
-
const lines = sourceCode.getText(node.property).split(
|
52
|
+
const lines = sourceCode.getText(node.property).split(astUtils.LINEBREAK_MATCHER);
|
51
53
|
const suffix = node.computed && lines.length === 1 ? "]" : "";
|
52
54
|
|
53
55
|
return prefix + lines[0] + suffix;
|
@@ -101,9 +101,9 @@ module.exports = {
|
|
101
101
|
function testForAssign(node) {
|
102
102
|
if (node.test &&
|
103
103
|
(node.test.type === "AssignmentExpression") &&
|
104
|
-
(node.type === "ForStatement"
|
105
|
-
!isParenthesised(node.test)
|
106
|
-
!isParenthesisedTwice(node.test)
|
104
|
+
(node.type === "ForStatement"
|
105
|
+
? !isParenthesised(node.test)
|
106
|
+
: !isParenthesisedTwice(node.test)
|
107
107
|
)
|
108
108
|
) {
|
109
109
|
|
@@ -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
|
|
@@ -98,6 +98,14 @@ module.exports = {
|
|
98
98
|
node,
|
99
99
|
message: "Redundant Boolean call.",
|
100
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
|
+
|
101
109
|
const argument = node.arguments[0];
|
102
110
|
|
103
111
|
if (astUtils.getPrecedence(argument) < astUtils.getPrecedence(node.parent)) {
|
@@ -557,8 +557,7 @@ module.exports = {
|
|
557
557
|
!(
|
558
558
|
(node.object.type === "Literal" &&
|
559
559
|
typeof node.object.value === "number" &&
|
560
|
-
astUtils.isDecimalInteger(node.object))
|
561
|
-
||
|
560
|
+
astUtils.isDecimalInteger(node.object)) ||
|
562
561
|
|
563
562
|
// RegExp literal is allowed to have parens (#1589)
|
564
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
|
/**
|
@@ -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
|
}
|
@@ -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
|
|
@@ -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
|
/**
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -34,7 +40,7 @@ module.exports = {
|
|
34
40
|
create(context) {
|
35
41
|
const sourceCode = context.getSourceCode();
|
36
42
|
|
37
|
-
const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\
|
43
|
+
const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u3000]",
|
38
44
|
SKIP_BLANK = `^${BLANK_CLASS}*$`,
|
39
45
|
NONBLANK = `${BLANK_CLASS}+$`;
|
40
46
|
|
@@ -81,7 +87,7 @@ module.exports = {
|
|
81
87
|
const re = new RegExp(NONBLANK),
|
82
88
|
skipMatch = new RegExp(SKIP_BLANK),
|
83
89
|
lines = sourceCode.lines,
|
84
|
-
linebreaks = sourceCode.getText().match(
|
90
|
+
linebreaks = sourceCode.getText().match(astUtils.createGlobalLinebreakMatcher());
|
85
91
|
let totalLength = 0,
|
86
92
|
fixRange = [];
|
87
93
|
|
@@ -21,15 +21,54 @@ module.exports = {
|
|
21
21
|
|
22
22
|
create(context) {
|
23
23
|
|
24
|
+
/**
|
25
|
+
* Report an invalid "undefined" identifier node.
|
26
|
+
* @param {ASTNode} node The node to report.
|
27
|
+
* @returns {void}
|
28
|
+
*/
|
29
|
+
function report(node) {
|
30
|
+
context.report({
|
31
|
+
node,
|
32
|
+
message: "Unexpected use of undefined."
|
33
|
+
});
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Checks the given scope for references to `undefined` and reports
|
38
|
+
* all references found.
|
39
|
+
* @param {escope.Scope} scope The scope to check.
|
40
|
+
* @returns {void}
|
41
|
+
*/
|
42
|
+
function checkScope(scope) {
|
43
|
+
const undefinedVar = scope.set.get("undefined");
|
44
|
+
|
45
|
+
if (!undefinedVar) {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
|
49
|
+
const references = undefinedVar.references;
|
50
|
+
|
51
|
+
const defs = undefinedVar.defs;
|
52
|
+
|
53
|
+
// Report non-initializing references (those are covered in defs below)
|
54
|
+
references
|
55
|
+
.filter(ref => !ref.init)
|
56
|
+
.forEach(ref => report(ref.identifier));
|
57
|
+
|
58
|
+
defs.forEach(def => report(def.name));
|
59
|
+
}
|
60
|
+
|
24
61
|
return {
|
62
|
+
"Program:exit"() {
|
63
|
+
const globalScope = context.getScope();
|
64
|
+
|
65
|
+
const stack = [globalScope];
|
25
66
|
|
26
|
-
|
27
|
-
|
28
|
-
const parent = context.getAncestors().pop();
|
67
|
+
while (stack.length) {
|
68
|
+
const scope = stack.pop();
|
29
69
|
|
30
|
-
|
31
|
-
|
32
|
-
}
|
70
|
+
stack.push.apply(stack, scope.childScopes);
|
71
|
+
checkScope(scope);
|
33
72
|
}
|
34
73
|
}
|
35
74
|
};
|
@@ -4,9 +4,16 @@
|
|
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
|
//------------------------------------------------------------------------------
|
16
|
+
|
10
17
|
module.exports = {
|
11
18
|
meta: {
|
12
19
|
docs: {
|
@@ -35,14 +42,8 @@ module.exports = {
|
|
35
42
|
* @private
|
36
43
|
*/
|
37
44
|
function checkForBreakAfter(node, msg) {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
// Move along until the end of the wrapped expression
|
42
|
-
while (openParen.value === ")") {
|
43
|
-
nodeExpressionEnd = openParen;
|
44
|
-
openParen = sourceCode.getTokenAfter(nodeExpressionEnd);
|
45
|
-
}
|
45
|
+
const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);
|
46
|
+
const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
|
46
47
|
|
47
48
|
if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
|
48
49
|
context.report({ node, loc: openParen.loc.start, message: msg, data: { char: openParen.value } });
|
@@ -67,7 +67,11 @@ module.exports = {
|
|
67
67
|
*/
|
68
68
|
function invertExpression(node) {
|
69
69
|
if (node.type === "BinaryExpression" && Object.prototype.hasOwnProperty.call(OPERATOR_INVERSES, node.operator)) {
|
70
|
-
const operatorToken = sourceCode.
|
70
|
+
const operatorToken = sourceCode.getFirstTokenBetween(
|
71
|
+
node.left,
|
72
|
+
node.right,
|
73
|
+
token => token.value === node.operator
|
74
|
+
);
|
71
75
|
|
72
76
|
return sourceCode.getText().slice(node.range[0], operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + sourceCode.getText().slice(operatorToken.range[1], node.range[1]);
|
73
77
|
}
|
@@ -17,10 +17,13 @@ module.exports = {
|
|
17
17
|
recommended: true
|
18
18
|
},
|
19
19
|
|
20
|
-
schema: []
|
20
|
+
schema: [],
|
21
|
+
|
22
|
+
fixable: "code"
|
21
23
|
},
|
22
24
|
|
23
25
|
create(context) {
|
26
|
+
const sourceCode = context.getSourceCode();
|
24
27
|
let scopeInfo = null;
|
25
28
|
|
26
29
|
/**
|
@@ -49,7 +52,19 @@ module.exports = {
|
|
49
52
|
context.report({
|
50
53
|
node: node.label,
|
51
54
|
message: "'{{name}}:' is defined but never used.",
|
52
|
-
data: node.label
|
55
|
+
data: node.label,
|
56
|
+
fix(fixer) {
|
57
|
+
|
58
|
+
/*
|
59
|
+
* Only perform a fix if there are no comments between the label and the body. This will be the case
|
60
|
+
* when there is exactly one token/comment (the ":") between the label and the body.
|
61
|
+
*/
|
62
|
+
if (sourceCode.getTokenAfter(node.label, { includeComments: true }) === sourceCode.getTokenBefore(node.body, { includeComments: true })) {
|
63
|
+
return fixer.removeRange([node.range[0], node.body.range[0]]);
|
64
|
+
}
|
65
|
+
|
66
|
+
return null;
|
67
|
+
}
|
53
68
|
});
|
54
69
|
}
|
55
70
|
|
@@ -62,6 +62,7 @@ module.exports = {
|
|
62
62
|
},
|
63
63
|
|
64
64
|
create(context) {
|
65
|
+
const sourceCode = context.getSourceCode();
|
65
66
|
|
66
67
|
const DEFINED_MESSAGE = "'{{name}}' is defined but never used.";
|
67
68
|
const ASSIGNED_MESSAGE = "'{{name}}' is assigned a value but never used.";
|
@@ -566,23 +567,8 @@ module.exports = {
|
|
566
567
|
*/
|
567
568
|
function getLocation(variable) {
|
568
569
|
const comment = variable.eslintExplicitGlobalComment;
|
569
|
-
const baseLoc = comment.loc.start;
|
570
|
-
let column = getColumnInComment(variable, comment);
|
571
|
-
const prefix = comment.value.slice(0, column);
|
572
|
-
const lineInComment = (prefix.match(/\n/g) || []).length;
|
573
570
|
|
574
|
-
|
575
|
-
column -= 1 + prefix.lastIndexOf("\n");
|
576
|
-
} else {
|
577
|
-
|
578
|
-
// 2 is for `/*`
|
579
|
-
column += baseLoc.column + 2;
|
580
|
-
}
|
581
|
-
|
582
|
-
return {
|
583
|
-
line: baseLoc.line + lineInComment,
|
584
|
-
column
|
585
|
-
};
|
571
|
+
return astUtils.getLocationFromRangeIndex(sourceCode, comment.range[0] + 2 + getColumnInComment(variable, comment));
|
586
572
|
}
|
587
573
|
|
588
574
|
//--------------------------------------------------------------------------
|
@@ -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
@@ -274,9 +274,7 @@ module.exports = {
|
|
274
274
|
if (
|
275
275
|
!isLoopAssignee(node) &&
|
276
276
|
!(node.parent.type === "ForStatement" && node.parent.init === node) &&
|
277
|
-
node.parent.type
|
278
|
-
node.parent.type !== "Program" &&
|
279
|
-
node.parent.type !== "SwitchCase"
|
277
|
+
!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)
|
280
278
|
) {
|
281
279
|
|
282
280
|
// If the declaration is not in a block, e.g. `if (foo) var bar = 1;`, then it can't be fixed.
|
@@ -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);
|