eslint 3.15.0 → 3.17.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 +79 -0
- package/conf/{eslint.json → eslint-recommended.js} +87 -71
- package/lib/ast-utils.js +182 -80
- 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/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 +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 +8 -7
- package/lib/rules/comma-spacing.js +3 -3
- package/lib/rules/complexity.js +14 -8
- package/lib/rules/consistent-return.js +18 -11
- 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-names.js +20 -5
- 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 +21 -17
- package/lib/rules/line-comment-position.js +16 -6
- package/lib/rules/linebreak-style.js +7 -1
- package/lib/rules/lines-around-comment.js +23 -4
- package/lib/rules/lines-around-directive.js +3 -3
- package/lib/rules/max-lines.js +2 -2
- package/lib/rules/max-params.js +17 -4
- package/lib/rules/max-statements-per-line.js +7 -6
- package/lib/rules/max-statements.js +11 -10
- package/lib/rules/newline-after-var.js +7 -2
- package/lib/rules/newline-per-chained-call.js +3 -1
- package/lib/rules/no-compare-neg-zero.js +53 -0
- package/lib/rules/no-cond-assign.js +3 -3
- package/lib/rules/no-else-return.js +13 -1
- package/lib/rules/no-empty-function.js +9 -16
- 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-extra-semi.js +13 -1
- package/lib/rules/no-inner-declarations.js +4 -4
- package/lib/rules/no-invalid-regexp.js +2 -1
- 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-multiple-empty-lines.js +2 -4
- package/lib/rules/no-param-reassign.js +29 -6
- package/lib/rules/no-restricted-properties.js +2 -0
- package/lib/rules/no-return-assign.js +7 -14
- package/lib/rules/no-return-await.js +1 -1
- 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 +13 -27
- package/lib/rules/no-use-before-define.js +1 -1
- 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 +2 -2
- package/lib/rules/no-useless-return.js +14 -9
- package/lib/rules/no-var.js +1 -3
- package/lib/rules/no-whitespace-before-property.js +5 -16
- package/lib/rules/nonblock-statement-body-position.js +114 -0
- 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 +4 -3
- package/lib/rules/operator-assignment.js +2 -2
- package/lib/rules/operator-linebreak.js +8 -10
- package/lib/rules/padded-blocks.js +39 -30
- package/lib/rules/prefer-destructuring.js +1 -1
- 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/semi.js +13 -1
- package/lib/rules/space-before-function-paren.js +8 -5
- package/lib/rules/space-unary-ops.js +19 -1
- package/lib/rules/spaced-comment.js +2 -2
- package/lib/rules/strict.js +10 -4
- package/lib/rules/unicode-bom.js +1 -1
- package/lib/rules/wrap-iife.js +5 -5
- package/lib/rules/yoda.js +4 -9
- package/lib/testers/rule-tester.js +46 -9
- 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/fix-tracker.js +121 -0
- package/lib/util/source-code-fixer.js +35 -39
- package/lib/util/source-code.js +129 -16
- package/messages/extend-config-missing.txt +3 -0
- package/package.json +5 -6
- package/lib/token-store.js +0 -203
package/lib/config/autoconfig.js
CHANGED
@@ -13,7 +13,7 @@ const lodash = require("lodash"),
|
|
13
13
|
eslint = require("../eslint"),
|
14
14
|
configRule = require("./config-rule"),
|
15
15
|
ConfigOps = require("./config-ops"),
|
16
|
-
recConfig = require("../../conf/eslint
|
16
|
+
recConfig = require("../../conf/eslint-recommended");
|
17
17
|
|
18
18
|
const debug = require("debug")("eslint:autoconfig");
|
19
19
|
|
@@ -300,8 +300,8 @@ class Registry {
|
|
300
300
|
// (https://github.com/eslint/eslint/issues/5992)
|
301
301
|
// (https://github.com/eslint/eslint/issues/7860)
|
302
302
|
if (
|
303
|
-
lintedRegistry.rules[result.ruleId]
|
304
|
-
|
303
|
+
lintedRegistry.rules[result.ruleId] &&
|
304
|
+
lintedRegistry.rules[result.ruleId][ruleSetIdx]
|
305
305
|
) {
|
306
306
|
lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1;
|
307
307
|
}
|
@@ -23,7 +23,7 @@ const fs = require("fs"),
|
|
23
23
|
stripBom = require("strip-bom"),
|
24
24
|
stripComments = require("strip-json-comments"),
|
25
25
|
stringify = require("json-stable-stringify"),
|
26
|
-
defaultOptions = require("../../conf/eslint
|
26
|
+
defaultOptions = require("../../conf/eslint-recommended"),
|
27
27
|
requireUncached = require("require-uncached");
|
28
28
|
|
29
29
|
const debug = require("debug")("eslint:config-file");
|
@@ -364,10 +364,10 @@ function applyExtends(config, filePath, relativeTo) {
|
|
364
364
|
if (parentPath === "eslint:recommended") {
|
365
365
|
|
366
366
|
/*
|
367
|
-
* Add an explicit substitution for eslint:recommended to
|
368
|
-
*
|
367
|
+
* Add an explicit substitution for eslint:recommended to
|
368
|
+
* conf/eslint-recommended.js.
|
369
369
|
*/
|
370
|
-
parentPath = path.resolve(__dirname, "../../conf/eslint.
|
370
|
+
parentPath = path.resolve(__dirname, "../../conf/eslint-recommended.js");
|
371
371
|
} else if (parentPath === "eslint:all") {
|
372
372
|
|
373
373
|
/*
|
@@ -380,9 +380,9 @@ function applyExtends(config, filePath, relativeTo) {
|
|
380
380
|
* If the `extends` path is relative, use the directory of the current configuration
|
381
381
|
* file as the reference point. Otherwise, use as-is.
|
382
382
|
*/
|
383
|
-
parentPath = (!path.isAbsolute(parentPath)
|
384
|
-
path.join(relativeTo || path.dirname(filePath), parentPath)
|
385
|
-
parentPath
|
383
|
+
parentPath = (!path.isAbsolute(parentPath)
|
384
|
+
? path.join(relativeTo || path.dirname(filePath), parentPath)
|
385
|
+
: parentPath
|
386
386
|
);
|
387
387
|
}
|
388
388
|
|
@@ -390,6 +390,13 @@ function applyExtends(config, filePath, relativeTo) {
|
|
390
390
|
debug(`Loading ${parentPath}`);
|
391
391
|
return ConfigOps.merge(load(parentPath, false, relativeTo), previousValue);
|
392
392
|
} catch (e) {
|
393
|
+
if (parentPath.indexOf("plugin:") === 0 || parentPath.indexOf("eslint:") === 0) {
|
394
|
+
e.message = `Failed to load config "${parentPath}" to extend from.`;
|
395
|
+
e.messageTemplate = "extend-config-missing";
|
396
|
+
e.messageData = {
|
397
|
+
configName: parentPath
|
398
|
+
};
|
399
|
+
}
|
393
400
|
|
394
401
|
/*
|
395
402
|
* If the file referenced by `extends` failed to load, add the path
|
@@ -17,7 +17,7 @@ const util = require("util"),
|
|
17
17
|
ConfigOps = require("./config-ops"),
|
18
18
|
getSourceCodeOfFiles = require("../util/source-code-util").getSourceCodeOfFiles,
|
19
19
|
npmUtil = require("../util/npm-util"),
|
20
|
-
recConfig = require("../../conf/eslint
|
20
|
+
recConfig = require("../../conf/eslint-recommended"),
|
21
21
|
log = require("../logging");
|
22
22
|
|
23
23
|
const debug = require("debug")("eslint:config-initializer");
|
package/lib/config.js
CHANGED
@@ -234,8 +234,9 @@ class Config {
|
|
234
234
|
}
|
235
235
|
|
236
236
|
/**
|
237
|
-
* Build a config object merging the base config (conf/eslint
|
238
|
-
* environments config (conf/environments.js) and eventually the user
|
237
|
+
* Build a config object merging the base config (conf/eslint-recommended),
|
238
|
+
* the environments config (conf/environments.js) and eventually the user
|
239
|
+
* config.
|
239
240
|
* @param {string} filePath a file in whose directory we start looking for a local config
|
240
241
|
* @returns {Object} config object
|
241
242
|
*/
|
package/lib/eslint.js
CHANGED
@@ -14,7 +14,7 @@ const assert = require("assert"),
|
|
14
14
|
escope = require("escope"),
|
15
15
|
levn = require("levn"),
|
16
16
|
blankScriptAST = require("../conf/blank-script.json"),
|
17
|
-
DEFAULT_PARSER = require("../conf/eslint
|
17
|
+
DEFAULT_PARSER = require("../conf/eslint-recommended").parser,
|
18
18
|
replacements = require("../conf/replacements.json"),
|
19
19
|
CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
|
20
20
|
ConfigOps = require("./config/config-ops"),
|
@@ -864,8 +864,8 @@ module.exports = (function() {
|
|
864
864
|
(parseResult && parseResult.services ? parseResult.services : {})
|
865
865
|
);
|
866
866
|
|
867
|
-
const rule = ruleCreator.create ? ruleCreator.create(ruleContext)
|
868
|
-
ruleCreator(ruleContext);
|
867
|
+
const rule = ruleCreator.create ? ruleCreator.create(ruleContext)
|
868
|
+
: ruleCreator(ruleContext);
|
869
869
|
|
870
870
|
// add all the node types as listeners
|
871
871
|
Object.keys(rule).forEach(nodeType => {
|
@@ -1192,7 +1192,7 @@ module.exports = (function() {
|
|
1192
1192
|
* @returns {Object} Object mapping rule IDs to their default configurations
|
1193
1193
|
*/
|
1194
1194
|
api.defaults = function() {
|
1195
|
-
return require("../conf/eslint
|
1195
|
+
return require("../conf/eslint-recommended");
|
1196
1196
|
};
|
1197
1197
|
|
1198
1198
|
/**
|
@@ -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
|
}
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -136,10 +142,7 @@ module.exports = {
|
|
136
142
|
loc: arrowBody.loc.start,
|
137
143
|
message: "Expected block statement surrounding arrow body.",
|
138
144
|
fix(fixer) {
|
139
|
-
const lastTokenBeforeBody = sourceCode.
|
140
|
-
.reverse()
|
141
|
-
.find(token => token.value !== "(");
|
142
|
-
|
145
|
+
const lastTokenBeforeBody = sourceCode.getLastTokenBetween(sourceCode.getFirstToken(node), arrowBody, astUtils.isNotOpeningParenToken);
|
143
146
|
const firstBodyToken = sourceCode.getTokenAfter(lastTokenBeforeBody);
|
144
147
|
|
145
148
|
return fixer.replaceTextRange(
|
@@ -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
|
//------------------------------------------------------------------------------
|
@@ -51,12 +57,7 @@ module.exports = {
|
|
51
57
|
* @returns {Object} Tokens of arrow and before/after arrow.
|
52
58
|
*/
|
53
59
|
function getTokens(node) {
|
54
|
-
|
55
|
-
|
56
|
-
// skip '(' tokens.
|
57
|
-
while (arrow.value !== "=>") {
|
58
|
-
arrow = sourceCode.getTokenBefore(arrow);
|
59
|
-
}
|
60
|
+
const arrow = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken);
|
60
61
|
|
61
62
|
return {
|
62
63
|
before: sourceCode.getTokenBefore(arrow),
|
@@ -74,8 +74,8 @@ module.exports = {
|
|
74
74
|
// Gets braces and the first/last token of content.
|
75
75
|
const openBrace = getOpenBrace(node);
|
76
76
|
const closeBrace = sourceCode.getLastToken(node);
|
77
|
-
const firstToken = sourceCode.
|
78
|
-
const lastToken = sourceCode.
|
77
|
+
const firstToken = sourceCode.getTokenAfter(openBrace, { includeComments: true });
|
78
|
+
const lastToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
79
79
|
|
80
80
|
// Skip if the node is invalid or empty.
|
81
81
|
if (openBrace.type !== "Punctuator" ||
|
package/lib/rules/brace-style.js
CHANGED
@@ -62,7 +62,7 @@ module.exports = {
|
|
62
62
|
function removeNewlineBetween(firstToken, secondToken) {
|
63
63
|
const textRange = [firstToken.range[1], secondToken.range[0]];
|
64
64
|
const textBetween = sourceCode.text.slice(textRange[0], textRange[1]);
|
65
|
-
const NEWLINE_REGEX =
|
65
|
+
const NEWLINE_REGEX = astUtils.createGlobalLinebreakMatcher();
|
66
66
|
|
67
67
|
// Don't do a fix if there is a comment between the tokens
|
68
68
|
return fixer => fixer.replaceTextRange(textRange, textBetween.trim() ? null : textBetween.replace(NEWLINE_REGEX, ""));
|
@@ -144,11 +144,7 @@ module.exports = {
|
|
144
144
|
|
145
145
|
return {
|
146
146
|
BlockStatement(node) {
|
147
|
-
if (
|
148
|
-
node.parent.type !== "BlockStatement" &&
|
149
|
-
node.parent.type !== "SwitchCase" &&
|
150
|
-
node.parent.type !== "Program"
|
151
|
-
) {
|
147
|
+
if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
|
152
148
|
validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
|
153
149
|
}
|
154
150
|
},
|
@@ -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 = {
|
@@ -163,8 +164,8 @@ module.exports = {
|
|
163
164
|
* otherwise.
|
164
165
|
*/
|
165
166
|
function isInlineComment(comment) {
|
166
|
-
const previousToken = sourceCode.
|
167
|
-
nextToken = sourceCode.
|
167
|
+
const previousToken = sourceCode.getTokenBefore(comment, { includeComments: true }),
|
168
|
+
nextToken = sourceCode.getTokenAfter(comment, { includeComments: true });
|
168
169
|
|
169
170
|
return Boolean(
|
170
171
|
previousToken &&
|
@@ -181,7 +182,7 @@ module.exports = {
|
|
181
182
|
* @returns {boolean} True if the comment follows a valid comment.
|
182
183
|
*/
|
183
184
|
function isConsecutiveComment(comment) {
|
184
|
-
const previousTokenOrComment = sourceCode.
|
185
|
+
const previousTokenOrComment = sourceCode.getTokenBefore(comment, { includeComments: true });
|
185
186
|
|
186
187
|
return Boolean(
|
187
188
|
previousTokenOrComment &&
|
@@ -264,9 +265,9 @@ module.exports = {
|
|
264
265
|
commentValid = isCommentValid(comment, options);
|
265
266
|
|
266
267
|
if (!commentValid) {
|
267
|
-
const message = capitalize === "always"
|
268
|
-
ALWAYS_MESSAGE
|
269
|
-
NEVER_MESSAGE;
|
268
|
+
const message = capitalize === "always"
|
269
|
+
? ALWAYS_MESSAGE
|
270
|
+
: NEVER_MESSAGE;
|
270
271
|
|
271
272
|
context.report({
|
272
273
|
node: null, // Intentionally using loc instead
|
@@ -96,9 +96,9 @@ module.exports = {
|
|
96
96
|
return fixer.replaceTextRange([start, end], newText);
|
97
97
|
|
98
98
|
},
|
99
|
-
message: options[dir]
|
100
|
-
"A space is required {{dir}} ','."
|
101
|
-
"There should be no space {{dir}} ','.",
|
99
|
+
message: options[dir]
|
100
|
+
? "A space is required {{dir}} ','."
|
101
|
+
: "There should be no space {{dir}} ','.",
|
102
102
|
data: {
|
103
103
|
dir
|
104
104
|
}
|
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
|
-
loc = context.getSourceCode().getTokenBefore(node.body).loc.start;
|
108
|
-
type = "function";
|
109
|
+
loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start;
|
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) {
|
@@ -209,9 +209,9 @@ module.exports = {
|
|
209
209
|
|
210
210
|
if (!calledInEveryPaths) {
|
211
211
|
context.report({
|
212
|
-
message: calledInSomePaths
|
213
|
-
"Lacked a call of 'super()' in some code paths."
|
214
|
-
"Expected to call 'super()'.",
|
212
|
+
message: calledInSomePaths
|
213
|
+
? "Lacked a call of 'super()' in some code paths."
|
214
|
+
: "Expected to call 'super()'.",
|
215
215
|
node: node.parent
|
216
216
|
});
|
217
217
|
}
|
package/lib/rules/curly.js
CHANGED
@@ -94,19 +94,23 @@ module.exports = {
|
|
94
94
|
return first.loc.start.line === last.loc.end.line;
|
95
95
|
}
|
96
96
|
|
97
|
+
/**
|
98
|
+
* Checks if the given token is an `else` token or not.
|
99
|
+
*
|
100
|
+
* @param {Token} token - The token to check.
|
101
|
+
* @returns {boolean} `true` if the token is an `else` token.
|
102
|
+
*/
|
103
|
+
function isElseKeywordToken(token) {
|
104
|
+
return token.value === "else" && token.type === "Keyword";
|
105
|
+
}
|
106
|
+
|
97
107
|
/**
|
98
108
|
* Gets the `else` keyword token of a given `IfStatement` node.
|
99
109
|
* @param {ASTNode} node - A `IfStatement` node to get.
|
100
110
|
* @returns {Token} The `else` keyword token.
|
101
111
|
*/
|
102
112
|
function getElseKeyword(node) {
|
103
|
-
|
104
|
-
|
105
|
-
while (token.type !== "Keyword" || token.value !== "else") {
|
106
|
-
token = sourceCode.getTokenAfter(token);
|
107
|
-
}
|
108
|
-
|
109
|
-
return token;
|
113
|
+
return node.alternate && sourceCode.getFirstTokenBetween(node.consequent, node.alternate, isElseKeywordToken);
|
110
114
|
}
|
111
115
|
|
112
116
|
/**
|
@@ -31,9 +31,9 @@ module.exports = {
|
|
31
31
|
|
32
32
|
create(context) {
|
33
33
|
const options = context.options[0] || {};
|
34
|
-
const commentPattern = options.commentPattern
|
35
|
-
new RegExp(options.commentPattern)
|
36
|
-
DEFAULT_COMMENT_PATTERN;
|
34
|
+
const commentPattern = options.commentPattern
|
35
|
+
? new RegExp(options.commentPattern)
|
36
|
+
: DEFAULT_COMMENT_PATTERN;
|
37
37
|
|
38
38
|
const sourceCode = context.getSourceCode();
|
39
39
|
|
package/lib/rules/eqeqeq.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
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -57,9 +63,9 @@ module.exports = {
|
|
57
63
|
const options = context.options[1] || {};
|
58
64
|
const sourceCode = context.getSourceCode();
|
59
65
|
|
60
|
-
const nullOption = (config === "always")
|
61
|
-
options.null || "always"
|
62
|
-
"ignore";
|
66
|
+
const nullOption = (config === "always")
|
67
|
+
? options.null || "always"
|
68
|
+
: "ignore";
|
63
69
|
const enforceRuleForNull = (nullOption === "always");
|
64
70
|
const enforceInverseRuleForNull = (nullOption === "never");
|
65
71
|
|
@@ -100,8 +106,7 @@ module.exports = {
|
|
100
106
|
* @private
|
101
107
|
*/
|
102
108
|
function isNullCheck(node) {
|
103
|
-
return (node.right
|
104
|
-
(node.left.type === "Literal" && node.left.value === null);
|
109
|
+
return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
|
105
110
|
}
|
106
111
|
|
107
112
|
/**
|
@@ -134,7 +139,11 @@ module.exports = {
|
|
134
139
|
|
135
140
|
// If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
|
136
141
|
if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
|
137
|
-
const operatorToken = sourceCode.
|
142
|
+
const operatorToken = sourceCode.getFirstTokenBetween(
|
143
|
+
node.left,
|
144
|
+
node.right,
|
145
|
+
token => token.value === node.operator
|
146
|
+
);
|
138
147
|
|
139
148
|
return fixer.replaceText(operatorToken, expectedOperator);
|
140
149
|
}
|