eslint 3.16.1 → 3.19.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 +103 -0
- package/README.md +1 -0
- package/conf/eslint-recommended.js +2 -0
- package/lib/ast-utils.js +3 -67
- package/lib/code-path-analysis/code-path-analyzer.js +2 -7
- package/lib/code-path-analysis/debug-helpers.js +17 -16
- package/lib/config/config-file.js +68 -38
- package/lib/config/config-rule.js +14 -10
- package/lib/config/plugins.js +19 -8
- package/lib/eslint.js +11 -10
- package/lib/formatters/codeframe.js +4 -9
- package/lib/formatters/stylish.js +5 -4
- package/lib/ignored-paths.js +6 -0
- package/lib/internal-rules/internal-no-invalid-meta.js +2 -40
- package/lib/rules/array-callback-return.js +15 -5
- package/lib/rules/arrow-body-style.js +2 -2
- package/lib/rules/arrow-parens.js +9 -3
- package/lib/rules/capitalized-comments.js +2 -1
- package/lib/rules/comma-dangle.js +3 -2
- package/lib/rules/comma-spacing.js +4 -14
- package/lib/rules/comma-style.js +8 -14
- package/lib/rules/complexity.js +14 -8
- package/lib/rules/consistent-return.js +17 -10
- package/lib/rules/curly.js +2 -2
- package/lib/rules/dot-notation.js +12 -6
- package/lib/rules/func-name-matching.js +18 -7
- package/lib/rules/func-names.js +20 -5
- package/lib/rules/keyword-spacing.js +19 -4
- package/lib/rules/line-comment-position.js +15 -5
- package/lib/rules/lines-around-comment.js +19 -0
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/max-params.js +17 -4
- package/lib/rules/max-statements.js +11 -10
- package/lib/rules/new-parens.js +7 -21
- package/lib/rules/no-compare-neg-zero.js +53 -0
- package/lib/rules/no-cond-assign.js +4 -17
- package/lib/rules/no-else-return.js +19 -4
- package/lib/rules/no-empty-function.js +9 -16
- package/lib/rules/no-extra-parens.js +110 -121
- package/lib/rules/no-extra-semi.js +16 -3
- package/lib/rules/no-global-assign.js +1 -1
- package/lib/rules/no-implicit-coercion.js +21 -8
- package/lib/rules/no-invalid-regexp.js +2 -1
- package/lib/rules/no-multiple-empty-lines.js +2 -4
- package/lib/rules/no-native-reassign.js +1 -1
- package/lib/rules/no-negated-in-lhs.js +1 -1
- package/lib/rules/no-new-func.js +6 -8
- package/lib/rules/no-new.js +2 -6
- package/lib/rules/no-param-reassign.js +37 -7
- package/lib/rules/no-process-exit.js +2 -10
- package/lib/rules/no-restricted-properties.js +2 -0
- package/lib/rules/no-restricted-syntax.js +32 -21
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sequences.js +2 -2
- package/lib/rules/no-sync.js +8 -13
- package/lib/rules/no-unsafe-negation.js +1 -1
- package/lib/rules/no-unused-expressions.js +10 -1
- package/lib/rules/no-unused-vars.js +12 -12
- package/lib/rules/no-use-before-define.js +1 -1
- package/lib/rules/no-useless-computed-key.js +12 -1
- package/lib/rules/no-useless-escape.js +8 -2
- package/lib/rules/no-useless-return.js +13 -2
- package/lib/rules/nonblock-statement-body-position.js +114 -0
- package/lib/rules/object-curly-spacing.js +2 -2
- package/lib/rules/object-shorthand.js +10 -3
- package/lib/rules/operator-assignment.js +20 -3
- package/lib/rules/padded-blocks.js +37 -31
- package/lib/rules/prefer-const.js +1 -1
- package/lib/rules/prefer-destructuring.js +1 -1
- package/lib/rules/quotes.js +1 -0
- package/lib/rules/semi-spacing.js +2 -15
- package/lib/rules/semi.js +17 -13
- package/lib/rules/sort-vars.js +3 -5
- package/lib/rules/space-before-function-paren.js +53 -77
- package/lib/rules/space-in-parens.js +4 -8
- package/lib/rules/space-unary-ops.js +19 -1
- package/lib/rules/strict.js +8 -2
- package/lib/rules/yoda.js +2 -2
- package/lib/testers/rule-tester.js +44 -13
- package/lib/util/fix-tracker.js +121 -0
- package/lib/util/glob-util.js +1 -1
- package/lib/util/node-event-generator.js +274 -4
- package/lib/util/source-code-fixer.js +3 -9
- package/lib/util/source-code.js +99 -2
- package/lib/util/traverser.js +16 -25
- package/package.json +34 -34
@@ -4,6 +4,8 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
const astUtils = require("../ast-utils");
|
8
|
+
|
7
9
|
//------------------------------------------------------------------------------
|
8
10
|
// Rule Definition
|
9
11
|
//------------------------------------------------------------------------------
|
@@ -33,6 +35,9 @@ module.exports = {
|
|
33
35
|
},
|
34
36
|
applyDefaultPatterns: {
|
35
37
|
type: "boolean"
|
38
|
+
},
|
39
|
+
applyDefaultIgnorePatterns: {
|
40
|
+
type: "boolean"
|
36
41
|
}
|
37
42
|
},
|
38
43
|
additionalProperties: false
|
@@ -43,12 +48,11 @@ module.exports = {
|
|
43
48
|
},
|
44
49
|
|
45
50
|
create(context) {
|
46
|
-
const DEFAULT_IGNORE_PATTERN = "^\\s*(?:eslint|jshint\\s+|jslint\\s+|istanbul\\s+|globals?\\s+|exported\\s+|jscs|falls?\\s?through)";
|
47
51
|
const options = context.options[0];
|
48
52
|
|
49
53
|
let above,
|
50
54
|
ignorePattern,
|
51
|
-
|
55
|
+
applyDefaultIgnorePatterns = true;
|
52
56
|
|
53
57
|
if (!options || typeof options === "string") {
|
54
58
|
above = !options || options === "above";
|
@@ -56,10 +60,16 @@ module.exports = {
|
|
56
60
|
} else {
|
57
61
|
above = options.position === "above";
|
58
62
|
ignorePattern = options.ignorePattern;
|
59
|
-
|
63
|
+
|
64
|
+
if (options.hasOwnProperty("applyDefaultIgnorePatterns")) {
|
65
|
+
applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false;
|
66
|
+
} else {
|
67
|
+
applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false;
|
68
|
+
}
|
60
69
|
}
|
61
70
|
|
62
|
-
const defaultIgnoreRegExp =
|
71
|
+
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
|
72
|
+
const fallThroughRegExp = /^\s*falls?\s?through/;
|
63
73
|
const customIgnoreRegExp = new RegExp(ignorePattern);
|
64
74
|
const sourceCode = context.getSourceCode();
|
65
75
|
|
@@ -69,7 +79,7 @@ module.exports = {
|
|
69
79
|
|
70
80
|
return {
|
71
81
|
LineComment(node) {
|
72
|
-
if (
|
82
|
+
if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) {
|
73
83
|
return;
|
74
84
|
}
|
75
85
|
|
@@ -93,6 +93,12 @@ module.exports = {
|
|
93
93
|
},
|
94
94
|
allowArrayEnd: {
|
95
95
|
type: "boolean"
|
96
|
+
},
|
97
|
+
ignorePattern: {
|
98
|
+
type: "string"
|
99
|
+
},
|
100
|
+
applyDefaultIgnorePatterns: {
|
101
|
+
type: "boolean"
|
96
102
|
}
|
97
103
|
},
|
98
104
|
additionalProperties: false
|
@@ -103,6 +109,11 @@ module.exports = {
|
|
103
109
|
create(context) {
|
104
110
|
|
105
111
|
const options = context.options[0] ? Object.assign({}, context.options[0]) : {};
|
112
|
+
const ignorePattern = options.ignorePattern;
|
113
|
+
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
|
114
|
+
const customIgnoreRegExp = new RegExp(ignorePattern);
|
115
|
+
const applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false;
|
116
|
+
|
106
117
|
|
107
118
|
options.beforeLineComment = options.beforeLineComment || false;
|
108
119
|
options.afterLineComment = options.afterLineComment || false;
|
@@ -270,6 +281,14 @@ module.exports = {
|
|
270
281
|
* @returns {void}
|
271
282
|
*/
|
272
283
|
function checkForEmptyLine(node, opts) {
|
284
|
+
if (applyDefaultIgnorePatterns && defaultIgnoreRegExp.test(node.value)) {
|
285
|
+
return;
|
286
|
+
}
|
287
|
+
|
288
|
+
if (ignorePattern && customIgnoreRegExp.test(node.value)) {
|
289
|
+
return;
|
290
|
+
}
|
291
|
+
|
273
292
|
let after = opts.after,
|
274
293
|
before = opts.before;
|
275
294
|
|
@@ -74,7 +74,7 @@ module.exports = {
|
|
74
74
|
const lastToken = sourceCode.getLastToken(node);
|
75
75
|
const secondToLastToken = sourceCode.getTokenBefore(lastToken);
|
76
76
|
|
77
|
-
return
|
77
|
+
return astUtils.isSemicolonToken(lastToken) && lastToken.loc.start.line > secondToLastToken.loc.end.line
|
78
78
|
? secondToLastToken
|
79
79
|
: lastToken;
|
80
80
|
}
|
package/lib/rules/max-params.js
CHANGED
@@ -5,6 +5,14 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const lodash = require("lodash");
|
13
|
+
|
14
|
+
const astUtils = require("../ast-utils");
|
15
|
+
|
8
16
|
//------------------------------------------------------------------------------
|
9
17
|
// Rule Definition
|
10
18
|
//------------------------------------------------------------------------------
|
@@ -66,10 +74,15 @@ module.exports = {
|
|
66
74
|
*/
|
67
75
|
function checkFunction(node) {
|
68
76
|
if (node.params.length > numParams) {
|
69
|
-
context.report({
|
70
|
-
|
71
|
-
|
72
|
-
|
77
|
+
context.report({
|
78
|
+
node,
|
79
|
+
message: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}.",
|
80
|
+
data: {
|
81
|
+
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(node)),
|
82
|
+
count: node.params.length,
|
83
|
+
max: numParams
|
84
|
+
}
|
85
|
+
});
|
73
86
|
}
|
74
87
|
}
|
75
88
|
|
@@ -5,6 +5,14 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const lodash = require("lodash");
|
13
|
+
|
14
|
+
const astUtils = require("../ast-utils");
|
15
|
+
|
8
16
|
//------------------------------------------------------------------------------
|
9
17
|
// Rule Definition
|
10
18
|
//------------------------------------------------------------------------------
|
@@ -84,19 +92,12 @@ module.exports = {
|
|
84
92
|
*/
|
85
93
|
function reportIfTooManyStatements(node, count, max) {
|
86
94
|
if (count > max) {
|
87
|
-
const
|
88
|
-
let name = "This function";
|
89
|
-
|
90
|
-
if (node.id) {
|
91
|
-
name = `Function '${node.id.name}'`;
|
92
|
-
} else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") {
|
93
|
-
name = `Function '${context.getSource(node.parent.key)}'`;
|
94
|
-
}
|
95
|
+
const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
|
95
96
|
|
96
97
|
context.report({
|
97
98
|
node,
|
98
|
-
message: name
|
99
|
-
data: { count, max }
|
99
|
+
message: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}.",
|
100
|
+
data: { name, count, max }
|
100
101
|
});
|
101
102
|
}
|
102
103
|
}
|
package/lib/rules/new-parens.js
CHANGED
@@ -6,28 +6,14 @@
|
|
6
6
|
"use strict";
|
7
7
|
|
8
8
|
//------------------------------------------------------------------------------
|
9
|
-
//
|
9
|
+
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
|
13
|
-
* Checks whether the given token is an opening parenthesis or not.
|
14
|
-
*
|
15
|
-
* @param {Token} token - The token to check.
|
16
|
-
* @returns {boolean} `true` if the token is an opening parenthesis.
|
17
|
-
*/
|
18
|
-
function isOpeningParen(token) {
|
19
|
-
return token.type === "Punctuator" && token.value === "(";
|
20
|
-
}
|
12
|
+
const astUtils = require("../ast-utils");
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
* @param {Token} token - The token to check.
|
26
|
-
* @returns {boolean} `true` if the token is an closing parenthesis.
|
27
|
-
*/
|
28
|
-
function isClosingParen(token) {
|
29
|
-
return token.type === "Punctuator" && token.value === ")";
|
30
|
-
}
|
14
|
+
//------------------------------------------------------------------------------
|
15
|
+
// Helpers
|
16
|
+
//------------------------------------------------------------------------------
|
31
17
|
|
32
18
|
//------------------------------------------------------------------------------
|
33
19
|
// Rule Definition
|
@@ -56,8 +42,8 @@ module.exports = {
|
|
56
42
|
}
|
57
43
|
|
58
44
|
const lastToken = sourceCode.getLastToken(node);
|
59
|
-
const hasLastParen = lastToken &&
|
60
|
-
const hasParens = hasLastParen &&
|
45
|
+
const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken);
|
46
|
+
const hasParens = hasLastParen && astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken));
|
61
47
|
|
62
48
|
if (!hasParens) {
|
63
49
|
context.report({
|
@@ -0,0 +1,53 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview The rule should warn against code that tries to compare against -0.
|
3
|
+
* @author Aladdin-ADD <hh_2013@foxmail.com>
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Rule Definition
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = {
|
12
|
+
meta: {
|
13
|
+
docs: {
|
14
|
+
description: "disallow comparing against -0",
|
15
|
+
category: "Possible Errors",
|
16
|
+
recommended: false
|
17
|
+
},
|
18
|
+
fixable: null,
|
19
|
+
schema: []
|
20
|
+
},
|
21
|
+
|
22
|
+
create(context) {
|
23
|
+
|
24
|
+
//--------------------------------------------------------------------------
|
25
|
+
// Helpers
|
26
|
+
//--------------------------------------------------------------------------
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Checks a given node is -0
|
30
|
+
*
|
31
|
+
* @param {ASTNode} node - A node to check.
|
32
|
+
* @returns {boolean} `true` if the node is -0.
|
33
|
+
*/
|
34
|
+
function isNegZero(node) {
|
35
|
+
return node.type === "UnaryExpression" && node.operator === "-" && node.argument.type === "Literal" && node.argument.value === 0;
|
36
|
+
}
|
37
|
+
const OPERATORS_TO_CHECK = new Set([">", ">=", "<", "<=", "==", "===", "!=", "!=="]);
|
38
|
+
|
39
|
+
return {
|
40
|
+
BinaryExpression(node) {
|
41
|
+
if (OPERATORS_TO_CHECK.has(node.operator)) {
|
42
|
+
if (isNegZero(node.left) || isNegZero(node.right)) {
|
43
|
+
context.report({
|
44
|
+
node,
|
45
|
+
message: "Do not use the '{{operator}}' operator to compare against -0.",
|
46
|
+
data: { operator: node.operator }
|
47
|
+
});
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
};
|
52
|
+
}
|
53
|
+
};
|
@@ -66,19 +66,6 @@ module.exports = {
|
|
66
66
|
return null;
|
67
67
|
}
|
68
68
|
|
69
|
-
/**
|
70
|
-
* Check whether the code represented by an AST node is enclosed in parentheses.
|
71
|
-
* @param {!Object} node The node to test.
|
72
|
-
* @returns {boolean} `true` if the code is enclosed in parentheses; otherwise, `false`.
|
73
|
-
*/
|
74
|
-
function isParenthesised(node) {
|
75
|
-
const previousToken = sourceCode.getTokenBefore(node),
|
76
|
-
nextToken = sourceCode.getTokenAfter(node);
|
77
|
-
|
78
|
-
return previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
|
79
|
-
nextToken.value === ")" && nextToken.range[0] >= node.range[1];
|
80
|
-
}
|
81
|
-
|
82
69
|
/**
|
83
70
|
* Check whether the code represented by an AST node is enclosed in two sets of parentheses.
|
84
71
|
* @param {!Object} node The node to test.
|
@@ -88,9 +75,9 @@ module.exports = {
|
|
88
75
|
const previousToken = sourceCode.getTokenBefore(node, 1),
|
89
76
|
nextToken = sourceCode.getTokenAfter(node, 1);
|
90
77
|
|
91
|
-
return isParenthesised(node) &&
|
92
|
-
|
93
|
-
nextToken
|
78
|
+
return astUtils.isParenthesised(sourceCode, node) &&
|
79
|
+
astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
|
80
|
+
astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
|
94
81
|
}
|
95
82
|
|
96
83
|
/**
|
@@ -102,7 +89,7 @@ module.exports = {
|
|
102
89
|
if (node.test &&
|
103
90
|
(node.test.type === "AssignmentExpression") &&
|
104
91
|
(node.type === "ForStatement"
|
105
|
-
? !isParenthesised(node.test)
|
92
|
+
? !astUtils.isParenthesised(sourceCode, node.test)
|
106
93
|
: !isParenthesisedTwice(node.test)
|
107
94
|
)
|
108
95
|
) {
|
@@ -5,6 +5,13 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
const FixTracker = require("../util/fix-tracker");
|
14
|
+
|
8
15
|
//------------------------------------------------------------------------------
|
9
16
|
// Rule Definition
|
10
17
|
//------------------------------------------------------------------------------
|
@@ -86,7 +93,13 @@ module.exports = {
|
|
86
93
|
} else {
|
87
94
|
fixedSource = source;
|
88
95
|
}
|
89
|
-
|
96
|
+
|
97
|
+
// Extend the replacement range to include the entire
|
98
|
+
// function to avoid conflicting with no-useless-return.
|
99
|
+
// https://github.com/eslint/eslint/issues/8026
|
100
|
+
return new FixTracker(fixer, sourceCode)
|
101
|
+
.retainEnclosingFunction(node)
|
102
|
+
.replaceTextRange([elseToken.start, node.end], fixedSource);
|
90
103
|
}
|
91
104
|
});
|
92
105
|
}
|
@@ -187,9 +200,11 @@ module.exports = {
|
|
187
200
|
let consequents,
|
188
201
|
alternate;
|
189
202
|
|
190
|
-
|
191
|
-
|
192
|
-
|
203
|
+
/*
|
204
|
+
* Fixing this would require splitting one statement into two, so no error should
|
205
|
+
* be reported if this node is in a position where only one statement is allowed.
|
206
|
+
*/
|
207
|
+
if (!astUtils.STATEMENT_LIST_PARENTS.has(parent.type)) {
|
193
208
|
return;
|
194
209
|
}
|
195
210
|
|
@@ -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
|
// Helpers
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -19,18 +25,6 @@ const ALLOW_OPTIONS = Object.freeze([
|
|
19
25
|
"setters",
|
20
26
|
"constructors"
|
21
27
|
]);
|
22
|
-
const SHOW_KIND = Object.freeze({
|
23
|
-
functions: "function",
|
24
|
-
arrowFunctions: "arrow function",
|
25
|
-
generatorFunctions: "generator function",
|
26
|
-
asyncFunctions: "async function",
|
27
|
-
methods: "method",
|
28
|
-
generatorMethods: "generator method",
|
29
|
-
asyncMethods: "async method",
|
30
|
-
getters: "getter",
|
31
|
-
setters: "setter",
|
32
|
-
constructors: "constructor"
|
33
|
-
});
|
34
28
|
|
35
29
|
/**
|
36
30
|
* Gets the kind of a given function node.
|
@@ -137,6 +131,7 @@ module.exports = {
|
|
137
131
|
*/
|
138
132
|
function reportIfEmpty(node) {
|
139
133
|
const kind = getKind(node);
|
134
|
+
const name = astUtils.getFunctionNameWithKind(node);
|
140
135
|
|
141
136
|
if (allowed.indexOf(kind) === -1 &&
|
142
137
|
node.body.type === "BlockStatement" &&
|
@@ -146,10 +141,8 @@ module.exports = {
|
|
146
141
|
context.report({
|
147
142
|
node,
|
148
143
|
loc: node.body.loc.start,
|
149
|
-
message: "Unexpected empty {{
|
150
|
-
data: {
|
151
|
-
kind: SHOW_KIND[kind]
|
152
|
-
}
|
144
|
+
message: "Unexpected empty {{name}}.",
|
145
|
+
data: { name }
|
153
146
|
});
|
154
147
|
}
|
155
148
|
}
|