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
@@ -94,16 +94,6 @@ function hasMetaSchema(metaPropertyNode) {
|
|
94
94
|
return getPropertyFromObject("schema", metaPropertyNode.value);
|
95
95
|
}
|
96
96
|
|
97
|
-
/**
|
98
|
-
* Whether this `meta` ObjectExpression has a `fixable` property defined or not.
|
99
|
-
*
|
100
|
-
* @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
|
101
|
-
* @returns {boolean} `true` if a `fixable` property exists.
|
102
|
-
*/
|
103
|
-
function hasMetaFixable(metaPropertyNode) {
|
104
|
-
return getPropertyFromObject("fixable", metaPropertyNode.value);
|
105
|
-
}
|
106
|
-
|
107
97
|
/**
|
108
98
|
* Checks the validity of the meta definition of this rule and reports any errors found.
|
109
99
|
*
|
@@ -112,7 +102,7 @@ function hasMetaFixable(metaPropertyNode) {
|
|
112
102
|
* @param {boolean} ruleIsFixable whether the rule is fixable or not.
|
113
103
|
* @returns {void}
|
114
104
|
*/
|
115
|
-
function checkMetaValidity(context, exportsNode
|
105
|
+
function checkMetaValidity(context, exportsNode) {
|
116
106
|
const metaProperty = getMetaPropertyFromExportsNode(exportsNode);
|
117
107
|
|
118
108
|
if (!metaProperty) {
|
@@ -142,11 +132,6 @@ function checkMetaValidity(context, exportsNode, ruleIsFixable) {
|
|
142
132
|
|
143
133
|
if (!hasMetaSchema(metaProperty)) {
|
144
134
|
context.report(metaProperty, "Rule is missing a meta.schema property.");
|
145
|
-
return;
|
146
|
-
}
|
147
|
-
|
148
|
-
if (ruleIsFixable && !hasMetaFixable(metaProperty)) {
|
149
|
-
context.report(metaProperty, "Rule is fixable, but is missing a meta.fixable property.");
|
150
135
|
}
|
151
136
|
}
|
152
137
|
|
@@ -177,7 +162,6 @@ module.exports = {
|
|
177
162
|
|
178
163
|
create(context) {
|
179
164
|
let exportsNode;
|
180
|
-
let ruleIsFixable = false;
|
181
165
|
|
182
166
|
return {
|
183
167
|
AssignmentExpression(node) {
|
@@ -191,35 +175,13 @@ module.exports = {
|
|
191
175
|
}
|
192
176
|
},
|
193
177
|
|
194
|
-
CallExpression(node) {
|
195
|
-
|
196
|
-
// If the rule has a call for `context.report` and a property `fix`
|
197
|
-
// is being passed in, then we consider that the rule is fixable.
|
198
|
-
//
|
199
|
-
// Note that we only look for context.report() calls in the new
|
200
|
-
// style (with single MessageDescriptor argument), because only
|
201
|
-
// calls in the new style can specify a fix.
|
202
|
-
if (node.callee.type === "MemberExpression" &&
|
203
|
-
node.callee.object.type === "Identifier" &&
|
204
|
-
node.callee.object.name === "context" &&
|
205
|
-
node.callee.property.type === "Identifier" &&
|
206
|
-
node.callee.property.name === "report" &&
|
207
|
-
node.arguments.length === 1 &&
|
208
|
-
node.arguments[0].type === "ObjectExpression") {
|
209
|
-
|
210
|
-
if (getPropertyFromObject("fix", node.arguments[0])) {
|
211
|
-
ruleIsFixable = true;
|
212
|
-
}
|
213
|
-
}
|
214
|
-
},
|
215
|
-
|
216
178
|
"Program:exit"() {
|
217
179
|
if (!isCorrectExportsFormat(exportsNode)) {
|
218
180
|
context.report({ node: exportsNode, message: "Rule does not export an Object. Make sure the rule follows the new rule format." });
|
219
181
|
return;
|
220
182
|
}
|
221
183
|
|
222
|
-
checkMetaValidity(context, exportsNode
|
184
|
+
checkMetaValidity(context, exportsNode);
|
223
185
|
}
|
224
186
|
};
|
225
187
|
}
|
@@ -9,6 +9,8 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
+
const lodash = require("lodash");
|
13
|
+
|
12
14
|
const astUtils = require("../ast-utils");
|
13
15
|
|
14
16
|
//------------------------------------------------------------------------------
|
@@ -147,7 +149,8 @@ module.exports = {
|
|
147
149
|
upper: null,
|
148
150
|
codePath: null,
|
149
151
|
hasReturn: false,
|
150
|
-
shouldCheck: false
|
152
|
+
shouldCheck: false,
|
153
|
+
node: null
|
151
154
|
};
|
152
155
|
|
153
156
|
/**
|
@@ -168,8 +171,11 @@ module.exports = {
|
|
168
171
|
node,
|
169
172
|
loc: getLocation(node, context.getSourceCode()).loc.start,
|
170
173
|
message: funcInfo.hasReturn
|
171
|
-
? "Expected to return a value at the end of
|
172
|
-
: "Expected to return a value in
|
174
|
+
? "Expected to return a value at the end of {{name}}."
|
175
|
+
: "Expected to return a value in {{name}}.",
|
176
|
+
data: {
|
177
|
+
name: astUtils.getFunctionNameWithKind(funcInfo.node)
|
178
|
+
}
|
173
179
|
});
|
174
180
|
}
|
175
181
|
}
|
@@ -187,7 +193,8 @@ module.exports = {
|
|
187
193
|
node.body.type === "BlockStatement" &&
|
188
194
|
isCallbackOfArrayMethod(node) &&
|
189
195
|
!node.async &&
|
190
|
-
!node.generator
|
196
|
+
!node.generator,
|
197
|
+
node
|
191
198
|
};
|
192
199
|
},
|
193
200
|
|
@@ -204,7 +211,10 @@ module.exports = {
|
|
204
211
|
if (!node.argument) {
|
205
212
|
context.report({
|
206
213
|
node,
|
207
|
-
message: "
|
214
|
+
message: "{{name}} expected a return value.",
|
215
|
+
data: {
|
216
|
+
name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
|
217
|
+
}
|
208
218
|
});
|
209
219
|
}
|
210
220
|
}
|
@@ -100,7 +100,7 @@ module.exports = {
|
|
100
100
|
const firstValueToken = sourceCode.getTokenAfter(returnKeyword);
|
101
101
|
let lastValueToken = sourceCode.getLastToken(blockBody[0]);
|
102
102
|
|
103
|
-
if (
|
103
|
+
if (astUtils.isSemicolonToken(lastValueToken)) {
|
104
104
|
|
105
105
|
/* The last token of the returned value is the last token of the ReturnExpression (if
|
106
106
|
* the ReturnExpression has no semicolon), or the second-to-last token (if the ReturnExpression
|
@@ -120,7 +120,7 @@ module.exports = {
|
|
120
120
|
const textBeforeReturn = sourceText.slice(arrowBody.range[0] + 1, returnKeyword.range[0]);
|
121
121
|
const textBetweenReturnAndValue = sourceText.slice(returnKeyword.range[1], firstValueToken.range[0]);
|
122
122
|
const rawReturnValueText = sourceText.slice(firstValueToken.range[0], lastValueToken.range[1]);
|
123
|
-
const returnValueText = firstValueToken
|
123
|
+
const returnValueText = astUtils.isOpeningBraceToken(firstValueToken) ? `(${rawReturnValueText})` : rawReturnValueText;
|
124
124
|
const textAfterValue = sourceText.slice(lastValueToken.range[1], blockBody[0].range[1] - 1);
|
125
125
|
const textAfterReturnStatement = sourceText.slice(blockBody[0].range[1], arrowBody.range[1] - 1);
|
126
126
|
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -62,7 +68,7 @@ module.exports = {
|
|
62
68
|
node.body.type !== "BlockStatement" &&
|
63
69
|
!node.returnType
|
64
70
|
) {
|
65
|
-
if (
|
71
|
+
if (astUtils.isOpeningParenToken(token)) {
|
66
72
|
context.report({
|
67
73
|
node,
|
68
74
|
message: requireForBlockBodyMessage,
|
@@ -84,7 +90,7 @@ module.exports = {
|
|
84
90
|
requireForBlockBody &&
|
85
91
|
node.body.type === "BlockStatement"
|
86
92
|
) {
|
87
|
-
if (
|
93
|
+
if (!astUtils.isOpeningParenToken(token)) {
|
88
94
|
context.report({
|
89
95
|
node,
|
90
96
|
message: requireForBlockBodyNoParensMessage,
|
@@ -103,7 +109,7 @@ module.exports = {
|
|
103
109
|
!node.params[0].typeAnnotation &&
|
104
110
|
!node.returnType
|
105
111
|
) {
|
106
|
-
if (
|
112
|
+
if (astUtils.isOpeningParenToken(token)) {
|
107
113
|
context.report({
|
108
114
|
node,
|
109
115
|
message: asNeededMessage,
|
@@ -9,6 +9,7 @@
|
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
11
|
const LETTER_PATTERN = require("../util/patterns/letters");
|
12
|
+
const astUtils = require("../ast-utils");
|
12
13
|
|
13
14
|
//------------------------------------------------------------------------------
|
14
15
|
// Helpers
|
@@ -16,7 +17,7 @@ const LETTER_PATTERN = require("../util/patterns/letters");
|
|
16
17
|
|
17
18
|
const ALWAYS_MESSAGE = "Comments should not begin with a lowercase character",
|
18
19
|
NEVER_MESSAGE = "Comments should not begin with an uppercase character",
|
19
|
-
DEFAULT_IGNORE_PATTERN =
|
20
|
+
DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
|
20
21
|
WHITESPACE = /\s/g,
|
21
22
|
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern?
|
22
23
|
DEFAULTS = {
|
@@ -10,6 +10,7 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const lodash = require("lodash");
|
13
|
+
const astUtils = require("../ast-utils");
|
13
14
|
|
14
15
|
//------------------------------------------------------------------------------
|
15
16
|
// Helpers
|
@@ -178,7 +179,7 @@ module.exports = {
|
|
178
179
|
default: {
|
179
180
|
const nextToken = sourceCode.getTokenAfter(lastItem);
|
180
181
|
|
181
|
-
if (nextToken
|
182
|
+
if (astUtils.isCommaToken(nextToken)) {
|
182
183
|
return nextToken;
|
183
184
|
}
|
184
185
|
return sourceCode.getLastToken(lastItem);
|
@@ -224,7 +225,7 @@ module.exports = {
|
|
224
225
|
|
225
226
|
const trailingToken = getTrailingToken(node, lastItem);
|
226
227
|
|
227
|
-
if (trailingToken
|
228
|
+
if (astUtils.isCommaToken(trailingToken)) {
|
228
229
|
context.report({
|
229
230
|
node: lastItem,
|
230
231
|
loc: trailingToken.loc.start,
|
@@ -53,16 +53,6 @@ module.exports = {
|
|
53
53
|
// list of comma tokens to ignore for the check of leading whitespace
|
54
54
|
const commaTokensToIgnore = [];
|
55
55
|
|
56
|
-
/**
|
57
|
-
* Determines if a given token is a comma operator.
|
58
|
-
* @param {ASTNode} token The token to check.
|
59
|
-
* @returns {boolean} True if the token is a comma, false if not.
|
60
|
-
* @private
|
61
|
-
*/
|
62
|
-
function isComma(token) {
|
63
|
-
return !!token && (token.type === "Punctuator") && (token.value === ",");
|
64
|
-
}
|
65
|
-
|
66
56
|
/**
|
67
57
|
* Reports a spacing error with an appropriate message.
|
68
58
|
* @param {ASTNode} node The binary expression node to report.
|
@@ -147,7 +137,7 @@ module.exports = {
|
|
147
137
|
if (element === null) {
|
148
138
|
token = sourceCode.getTokenAfter(previousToken);
|
149
139
|
|
150
|
-
if (
|
140
|
+
if (astUtils.isCommaToken(token)) {
|
151
141
|
commaTokensToIgnore.push(token);
|
152
142
|
}
|
153
143
|
} else {
|
@@ -166,7 +156,7 @@ module.exports = {
|
|
166
156
|
"Program:exit"() {
|
167
157
|
tokensAndComments.forEach((token, i) => {
|
168
158
|
|
169
|
-
if (!
|
159
|
+
if (!astUtils.isCommaToken(token)) {
|
170
160
|
return;
|
171
161
|
}
|
172
162
|
|
@@ -179,8 +169,8 @@ module.exports = {
|
|
179
169
|
|
180
170
|
validateCommaItemSpacing({
|
181
171
|
comma: token,
|
182
|
-
left:
|
183
|
-
right:
|
172
|
+
left: astUtils.isCommaToken(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken,
|
173
|
+
right: astUtils.isCommaToken(nextToken) ? null : nextToken
|
184
174
|
}, token);
|
185
175
|
});
|
186
176
|
},
|
package/lib/rules/comma-style.js
CHANGED
@@ -63,16 +63,6 @@ module.exports = {
|
|
63
63
|
// Helpers
|
64
64
|
//--------------------------------------------------------------------------
|
65
65
|
|
66
|
-
/**
|
67
|
-
* Determines if a given token is a comma operator.
|
68
|
-
* @param {ASTNode} token The token to check.
|
69
|
-
* @returns {boolean} True if the token is a comma, false if not.
|
70
|
-
* @private
|
71
|
-
*/
|
72
|
-
function isComma(token) {
|
73
|
-
return !!token && (token.type === "Punctuator") && (token.value === ",");
|
74
|
-
}
|
75
|
-
|
76
66
|
/**
|
77
67
|
* Modified text based on the style
|
78
68
|
* @param {string} styleType Style type
|
@@ -192,7 +182,7 @@ module.exports = {
|
|
192
182
|
tokenBeforeComma = sourceCode.getTokenBefore(commaToken);
|
193
183
|
|
194
184
|
// Check if previous token is wrapped in parentheses
|
195
|
-
if (tokenBeforeComma && tokenBeforeComma
|
185
|
+
if (tokenBeforeComma && astUtils.isClosingParenToken(tokenBeforeComma)) {
|
196
186
|
previousItemToken = tokenBeforeComma;
|
197
187
|
}
|
198
188
|
|
@@ -210,12 +200,16 @@ module.exports = {
|
|
210
200
|
* All comparisons are done based on these tokens directly, so
|
211
201
|
* they are always valid regardless of an undefined item.
|
212
202
|
*/
|
213
|
-
if (
|
203
|
+
if (astUtils.isCommaToken(commaToken)) {
|
214
204
|
validateCommaItemSpacing(previousItemToken, commaToken,
|
215
205
|
currentItemToken, reportItem);
|
216
206
|
}
|
217
207
|
|
218
|
-
|
208
|
+
if (item) {
|
209
|
+
const tokenAfterItem = sourceCode.getTokenAfter(item, astUtils.isNotClosingParenToken);
|
210
|
+
|
211
|
+
previousItemToken = tokenAfterItem ? sourceCode.getTokenBefore(tokenAfterItem) : sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1];
|
212
|
+
}
|
219
213
|
});
|
220
214
|
|
221
215
|
/*
|
@@ -229,7 +223,7 @@ module.exports = {
|
|
229
223
|
const lastToken = sourceCode.getLastToken(node),
|
230
224
|
nextToLastToken = sourceCode.getTokenBefore(lastToken);
|
231
225
|
|
232
|
-
if (
|
226
|
+
if (astUtils.isCommaToken(nextToLastToken)) {
|
233
227
|
validateCommaItemSpacing(
|
234
228
|
sourceCode.getTokenBefore(nextToLastToken),
|
235
229
|
nextToLastToken,
|
package/lib/rules/complexity.js
CHANGED
@@ -6,6 +6,14 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Requirements
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
const lodash = require("lodash");
|
14
|
+
|
15
|
+
const astUtils = require("../ast-utils");
|
16
|
+
|
9
17
|
//------------------------------------------------------------------------------
|
10
18
|
// Rule Definition
|
11
19
|
//------------------------------------------------------------------------------
|
@@ -81,17 +89,15 @@ module.exports = {
|
|
81
89
|
* @private
|
82
90
|
*/
|
83
91
|
function endFunction(node) {
|
92
|
+
const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
|
84
93
|
const complexity = fns.pop();
|
85
|
-
let name = "anonymous";
|
86
|
-
|
87
|
-
if (node.id) {
|
88
|
-
name = node.id.name;
|
89
|
-
} else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") {
|
90
|
-
name = node.parent.key.name;
|
91
|
-
}
|
92
94
|
|
93
95
|
if (complexity > THRESHOLD) {
|
94
|
-
context.report({
|
96
|
+
context.report({
|
97
|
+
node,
|
98
|
+
message: "{{name}} has a complexity of {{complexity}}.",
|
99
|
+
data: { name, complexity }
|
100
|
+
});
|
95
101
|
}
|
96
102
|
}
|
97
103
|
|
@@ -8,6 +8,8 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
+
const lodash = require("lodash");
|
12
|
+
|
11
13
|
const astUtils = require("../ast-utils");
|
12
14
|
|
13
15
|
//------------------------------------------------------------------------------
|
@@ -81,7 +83,7 @@ module.exports = {
|
|
81
83
|
* @returns {void}
|
82
84
|
*/
|
83
85
|
function checkLastSegment(node) {
|
84
|
-
let loc,
|
86
|
+
let loc, name;
|
85
87
|
|
86
88
|
/*
|
87
89
|
* Skip if it expected no return value or unreachable.
|
@@ -100,12 +102,11 @@ module.exports = {
|
|
100
102
|
|
101
103
|
// The head of program.
|
102
104
|
loc = { line: 1, column: 0 };
|
103
|
-
|
105
|
+
name = "program";
|
104
106
|
} else if (node.type === "ArrowFunctionExpression") {
|
105
107
|
|
106
108
|
// `=>` token
|
107
109
|
loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start;
|
108
|
-
type = "function";
|
109
110
|
} else if (
|
110
111
|
node.parent.type === "MethodDefinition" ||
|
111
112
|
(node.parent.type === "Property" && node.parent.method)
|
@@ -113,33 +114,36 @@ module.exports = {
|
|
113
114
|
|
114
115
|
// Method name.
|
115
116
|
loc = node.parent.key.loc.start;
|
116
|
-
type = "method";
|
117
117
|
} else {
|
118
118
|
|
119
119
|
// Function name or `function` keyword.
|
120
120
|
loc = (node.id || node).loc.start;
|
121
|
-
|
121
|
+
}
|
122
|
+
|
123
|
+
if (!name) {
|
124
|
+
name = astUtils.getFunctionNameWithKind(node);
|
122
125
|
}
|
123
126
|
|
124
127
|
// Reports.
|
125
128
|
context.report({
|
126
129
|
node,
|
127
130
|
loc,
|
128
|
-
message: "Expected to return a value at the end of
|
129
|
-
data: {
|
131
|
+
message: "Expected to return a value at the end of {{name}}.",
|
132
|
+
data: { name }
|
130
133
|
});
|
131
134
|
}
|
132
135
|
|
133
136
|
return {
|
134
137
|
|
135
138
|
// Initializes/Disposes state of each code path.
|
136
|
-
onCodePathStart(codePath) {
|
139
|
+
onCodePathStart(codePath, node) {
|
137
140
|
funcInfo = {
|
138
141
|
upper: funcInfo,
|
139
142
|
codePath,
|
140
143
|
hasReturn: false,
|
141
144
|
hasReturnValue: false,
|
142
|
-
message: ""
|
145
|
+
message: "",
|
146
|
+
node
|
143
147
|
};
|
144
148
|
},
|
145
149
|
onCodePathEnd() {
|
@@ -158,8 +162,11 @@ module.exports = {
|
|
158
162
|
if (!funcInfo.hasReturn) {
|
159
163
|
funcInfo.hasReturn = true;
|
160
164
|
funcInfo.hasReturnValue = hasReturnValue;
|
161
|
-
funcInfo.message = "
|
165
|
+
funcInfo.message = "{{name}} expected {{which}} return value.";
|
162
166
|
funcInfo.data = {
|
167
|
+
name: funcInfo.node.type === "Program"
|
168
|
+
? "Program"
|
169
|
+
: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node)),
|
163
170
|
which: hasReturnValue ? "a" : "no"
|
164
171
|
};
|
165
172
|
} else if (funcInfo.hasReturnValue !== hasReturnValue) {
|
package/lib/rules/curly.js
CHANGED
@@ -76,7 +76,7 @@ module.exports = {
|
|
76
76
|
function isCollapsedOneLiner(node) {
|
77
77
|
const before = sourceCode.getTokenBefore(node);
|
78
78
|
const last = sourceCode.getLastToken(node);
|
79
|
-
const lastExcludingSemicolon =
|
79
|
+
const lastExcludingSemicolon = astUtils.isSemicolonToken(last) ? sourceCode.getTokenBefore(last) : last;
|
80
80
|
|
81
81
|
return before.loc.start.line === lastExcludingSemicolon.loc.end.line;
|
82
82
|
}
|
@@ -174,7 +174,7 @@ module.exports = {
|
|
174
174
|
const tokenAfter = sourceCode.getTokenAfter(closingBracket);
|
175
175
|
const lastBlockNode = sourceCode.getNodeByRangeIndex(tokenBefore.range[0]);
|
176
176
|
|
177
|
-
if (tokenBefore
|
177
|
+
if (astUtils.isSemicolonToken(tokenBefore)) {
|
178
178
|
|
179
179
|
// If the last statement already has a semicolon, don't add another one.
|
180
180
|
return false;
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -64,20 +70,20 @@ module.exports = {
|
|
64
70
|
propertyValue: JSON.stringify(node.property.value)
|
65
71
|
},
|
66
72
|
fix(fixer) {
|
67
|
-
const leftBracket = sourceCode.
|
68
|
-
const rightBracket = sourceCode.
|
69
|
-
const textBeforeProperty = sourceCode.text.slice(leftBracket.range[1], node.property.range[0]);
|
70
|
-
const textAfterProperty = sourceCode.text.slice(node.property.range[1], rightBracket.range[0]);
|
73
|
+
const leftBracket = sourceCode.getTokenAfter(node.object, astUtils.isOpeningBracketToken);
|
74
|
+
const rightBracket = sourceCode.getLastToken(node);
|
71
75
|
|
72
|
-
if (
|
76
|
+
if (sourceCode.getFirstTokenBetween(leftBracket, rightBracket, { includeComments: true, filter: astUtils.isCommentToken })) {
|
73
77
|
|
74
78
|
// Don't perform any fixes if there are comments inside the brackets.
|
75
79
|
return null;
|
76
80
|
}
|
77
81
|
|
82
|
+
const textBeforeDot = astUtils.isDecimalInteger(node.object) ? " " : "";
|
83
|
+
|
78
84
|
return fixer.replaceTextRange(
|
79
85
|
[leftBracket.range[0], rightBracket.range[1]],
|
80
|
-
|
86
|
+
`${textBeforeDot}.${node.property.value}`
|
81
87
|
);
|
82
88
|
}
|
83
89
|
});
|
@@ -132,6 +132,15 @@ module.exports = {
|
|
132
132
|
});
|
133
133
|
}
|
134
134
|
|
135
|
+
/**
|
136
|
+
* Determines whether a given node is a string literal
|
137
|
+
* @param {ASTNode} node The node to check
|
138
|
+
* @returns {boolean} `true` if the node is a string literal
|
139
|
+
*/
|
140
|
+
function isStringLiteral(node) {
|
141
|
+
return node.type === "Literal" && typeof node.value === "string";
|
142
|
+
}
|
143
|
+
|
135
144
|
//--------------------------------------------------------------------------
|
136
145
|
// Public
|
137
146
|
//--------------------------------------------------------------------------
|
@@ -139,7 +148,7 @@ module.exports = {
|
|
139
148
|
return {
|
140
149
|
|
141
150
|
VariableDeclarator(node) {
|
142
|
-
if (!node.init || node.init.type !== "FunctionExpression") {
|
151
|
+
if (!node.init || node.init.type !== "FunctionExpression" || node.id.type !== "Identifier") {
|
143
152
|
return;
|
144
153
|
}
|
145
154
|
if (node.init.id && shouldWarn(node.id.name, node.init.id.name)) {
|
@@ -148,10 +157,12 @@ module.exports = {
|
|
148
157
|
},
|
149
158
|
|
150
159
|
AssignmentExpression(node) {
|
151
|
-
if (
|
152
|
-
|
153
|
-
(
|
154
|
-
|
160
|
+
if (
|
161
|
+
node.right.type !== "FunctionExpression" ||
|
162
|
+
(node.left.computed && node.left.property.type !== "Literal") ||
|
163
|
+
(!includeModuleExports && isModuleExports(node.left)) ||
|
164
|
+
(node.left.type !== "Identifier" && node.left.type !== "MemberExpression")
|
165
|
+
) {
|
155
166
|
return;
|
156
167
|
}
|
157
168
|
|
@@ -164,13 +175,13 @@ module.exports = {
|
|
164
175
|
},
|
165
176
|
|
166
177
|
Property(node) {
|
167
|
-
if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && node.key
|
178
|
+
if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && !isStringLiteral(node.key)) {
|
168
179
|
return;
|
169
180
|
}
|
170
181
|
if (node.key.type === "Identifier" && shouldWarn(node.key.name, node.value.id.name)) {
|
171
182
|
report(node, node.key.name, node.value.id.name, true);
|
172
183
|
} else if (
|
173
|
-
node.key
|
184
|
+
isStringLiteral(node.key) &&
|
174
185
|
isIdentifier(node.key.value, ecmaVersion) &&
|
175
186
|
shouldWarn(node.key.value, node.value.id.name)
|
176
187
|
) {
|
package/lib/rules/func-names.js
CHANGED
@@ -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
|
* Checks whether or not a given variable is a function name.
|
10
16
|
* @param {escope.Variable} variable - A variable to check.
|
@@ -82,15 +88,24 @@ module.exports = {
|
|
82
88
|
return;
|
83
89
|
}
|
84
90
|
|
85
|
-
const
|
91
|
+
const hasName = Boolean(node.id && node.id.name);
|
92
|
+
const name = astUtils.getFunctionNameWithKind(node);
|
86
93
|
|
87
94
|
if (never) {
|
88
|
-
if (
|
89
|
-
context.report({
|
95
|
+
if (hasName) {
|
96
|
+
context.report({
|
97
|
+
node,
|
98
|
+
message: "Unexpected named {{name}}.",
|
99
|
+
data: { name }
|
100
|
+
});
|
90
101
|
}
|
91
102
|
} else {
|
92
|
-
if (!
|
93
|
-
context.report({
|
103
|
+
if (!hasName && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) {
|
104
|
+
context.report({
|
105
|
+
node,
|
106
|
+
message: "Unexpected unnamed {{name}}.",
|
107
|
+
data: { name }
|
108
|
+
});
|
94
109
|
}
|
95
110
|
}
|
96
111
|
}
|
@@ -359,7 +359,8 @@ module.exports = {
|
|
359
359
|
const firstToken = node && sourceCode.getFirstToken(node);
|
360
360
|
|
361
361
|
if (firstToken &&
|
362
|
-
(firstToken.type === "Keyword"
|
362
|
+
((firstToken.type === "Keyword" && firstToken.value === "function") ||
|
363
|
+
firstToken.value === "async")
|
363
364
|
) {
|
364
365
|
checkSpacingBefore(firstToken);
|
365
366
|
}
|
@@ -495,11 +496,25 @@ module.exports = {
|
|
495
496
|
node.value.async
|
496
497
|
)
|
497
498
|
) {
|
498
|
-
const token = sourceCode.
|
499
|
-
node,
|
500
|
-
|
499
|
+
const token = sourceCode.getTokenBefore(
|
500
|
+
node.key,
|
501
|
+
tok => {
|
502
|
+
switch (tok.value) {
|
503
|
+
case "get":
|
504
|
+
case "set":
|
505
|
+
case "async":
|
506
|
+
return true;
|
507
|
+
default:
|
508
|
+
return false;
|
509
|
+
}
|
510
|
+
}
|
501
511
|
);
|
502
512
|
|
513
|
+
if (!token) {
|
514
|
+
throw new Error("Failed to find token get, set, or async beside method name");
|
515
|
+
}
|
516
|
+
|
517
|
+
|
503
518
|
checkSpacingAround(token);
|
504
519
|
}
|
505
520
|
}
|