eslint 3.9.0 → 3.10.2
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 +60 -1
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/bin/eslint.js +5 -5
- package/conf/eslint.json +1 -0
- package/lib/ast-utils.js +1 -3
- package/lib/cli-engine.js +9 -11
- package/lib/code-path-analysis/debug-helpers.js +4 -4
- package/lib/config/autoconfig.js +23 -35
- package/lib/config/config-file.js +1 -1
- package/lib/config/config-initializer.js +12 -20
- package/lib/config/config-ops.js +7 -9
- package/lib/config/config-rule.js +14 -18
- package/lib/config/config-validator.js +3 -3
- package/lib/config/environments.js +1 -1
- package/lib/config.js +2 -2
- package/lib/eslint.js +21 -23
- package/lib/file-finder.js +1 -1
- package/lib/formatters/checkstyle.js +2 -2
- package/lib/formatters/compact.js +2 -2
- package/lib/formatters/html.js +9 -11
- package/lib/formatters/jslint-xml.js +2 -2
- package/lib/formatters/junit.js +2 -2
- package/lib/formatters/stylish.js +3 -7
- package/lib/formatters/table.js +4 -6
- package/lib/formatters/tap.js +2 -2
- package/lib/formatters/unix.js +2 -2
- package/lib/formatters/visualstudio.js +2 -2
- package/lib/load-rules.js +1 -1
- package/lib/rules/arrow-body-style.js +1 -1
- package/lib/rules/arrow-parens.js +9 -2
- package/lib/rules/brace-style.js +2 -2
- package/lib/rules/comma-spacing.js +2 -2
- package/lib/rules/comma-style.js +51 -4
- package/lib/rules/consistent-this.js +5 -9
- package/lib/rules/constructor-super.js +1 -1
- package/lib/rules/curly.js +10 -7
- package/lib/rules/default-case.js +1 -3
- package/lib/rules/eqeqeq.js +19 -7
- package/lib/rules/func-names.js +23 -4
- package/lib/rules/global-require.js +3 -7
- package/lib/rules/handle-callback-err.js +1 -3
- package/lib/rules/id-length.js +1 -1
- package/lib/rules/indent.js +10 -25
- package/lib/rules/key-spacing.js +4 -4
- package/lib/rules/keyword-spacing.js +1 -1
- package/lib/rules/lines-around-comment.js +5 -11
- package/lib/rules/lines-around-directive.js +23 -4
- package/lib/rules/max-len.js +5 -11
- package/lib/rules/max-lines.js +4 -12
- package/lib/rules/max-statements.js +11 -2
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-before-return.js +2 -4
- package/lib/rules/no-alert.js +2 -4
- package/lib/rules/no-class-assign.js +1 -1
- package/lib/rules/no-const-assign.js +1 -1
- package/lib/rules/no-control-regex.js +2 -2
- package/lib/rules/no-duplicate-case.js +1 -1
- package/lib/rules/no-ex-assign.js +1 -1
- package/lib/rules/no-extend-native.js +3 -7
- package/lib/rules/no-extra-boolean-cast.js +14 -3
- package/lib/rules/no-extra-parens.js +4 -4
- package/lib/rules/no-func-assign.js +1 -1
- package/lib/rules/no-implicit-globals.js +4 -4
- package/lib/rules/no-irregular-whitespace.js +3 -3
- package/lib/rules/no-mixed-operators.js +1 -3
- package/lib/rules/no-mixed-requires.js +2 -2
- package/lib/rules/no-mixed-spaces-and-tabs.js +3 -3
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-new-symbol.js +1 -1
- package/lib/rules/no-redeclare.js +2 -4
- package/lib/rules/no-restricted-globals.js +2 -2
- package/lib/rules/no-restricted-imports.js +45 -11
- package/lib/rules/no-restricted-modules.js +53 -36
- package/lib/rules/no-restricted-syntax.js +2 -4
- package/lib/rules/no-return-await.js +77 -0
- package/lib/rules/no-tabs.js +1 -1
- package/lib/rules/no-this-before-super.js +2 -2
- package/lib/rules/no-undef.js +1 -1
- package/lib/rules/no-underscore-dangle.js +1 -3
- package/lib/rules/no-unused-vars.js +2 -6
- package/lib/rules/no-use-before-define.js +1 -1
- package/lib/rules/no-useless-escape.js +8 -54
- package/lib/rules/no-useless-return.js +6 -0
- package/lib/rules/no-warning-comments.js +2 -2
- package/lib/rules/object-shorthand.js +21 -10
- package/lib/rules/one-var-declaration-per-line.js +1 -1
- package/lib/rules/prefer-const.js +1 -3
- package/lib/rules/prefer-reflect.js +2 -1
- package/lib/rules/quote-props.js +1 -1
- package/lib/rules/quotes.js +1 -1
- package/lib/rules/radix.js +2 -2
- package/lib/rules/require-jsdoc.js +8 -0
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-in-parens.js +1 -1
- package/lib/rules/space-infix-ops.js +1 -1
- package/lib/rules/spaced-comment.js +1 -1
- package/lib/rules/symbol-description.js +1 -1
- package/lib/rules/valid-jsdoc.js +3 -3
- package/lib/rules.js +2 -2
- package/lib/testers/event-generator-tester.js +5 -5
- package/lib/testers/rule-tester.js +11 -13
- package/lib/timing.js +11 -13
- package/lib/util/comment-event-generator.js +1 -1
- package/lib/util/glob-util.js +3 -5
- package/lib/util/npm-util.js +1 -1
- package/lib/util/source-code-fixer.js +3 -5
- package/lib/util/source-code-util.js +4 -4
- package/lib/util/source-code.js +3 -3
- package/lib/util/traverser.js +1 -3
- package/lib/util/xml-escape.js +1 -1
- package/package.json +3 -3
@@ -141,7 +141,7 @@ module.exports = {
|
|
141
141
|
function addNullElementsToIgnoreList(node) {
|
142
142
|
let previousToken = sourceCode.getFirstToken(node);
|
143
143
|
|
144
|
-
node.elements.forEach(
|
144
|
+
node.elements.forEach(element => {
|
145
145
|
let token;
|
146
146
|
|
147
147
|
if (element === null) {
|
@@ -164,7 +164,7 @@ module.exports = {
|
|
164
164
|
|
165
165
|
return {
|
166
166
|
"Program:exit"() {
|
167
|
-
tokensAndComments.forEach(
|
167
|
+
tokensAndComments.forEach((token, i) => {
|
168
168
|
|
169
169
|
if (!isComma(token)) {
|
170
170
|
return;
|
package/lib/rules/comma-style.js
CHANGED
@@ -41,10 +41,22 @@ module.exports = {
|
|
41
41
|
create(context) {
|
42
42
|
const style = context.options[0] || "last",
|
43
43
|
sourceCode = context.getSourceCode();
|
44
|
-
|
44
|
+
const exceptions = {
|
45
|
+
ArrayPattern: true,
|
46
|
+
ArrowFunctionExpression: true,
|
47
|
+
CallExpression: true,
|
48
|
+
FunctionDeclaration: true,
|
49
|
+
FunctionExpression: true,
|
50
|
+
ImportDeclaration: true,
|
51
|
+
ObjectPattern: true,
|
52
|
+
};
|
45
53
|
|
46
54
|
if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) {
|
47
|
-
|
55
|
+
const keys = Object.keys(context.options[1].exceptions);
|
56
|
+
|
57
|
+
for (let i = 0; i < keys.length; i++) {
|
58
|
+
exceptions[keys[i]] = context.options[1].exceptions[keys[i]];
|
59
|
+
}
|
48
60
|
}
|
49
61
|
|
50
62
|
//--------------------------------------------------------------------------
|
@@ -166,14 +178,14 @@ module.exports = {
|
|
166
178
|
*/
|
167
179
|
function validateComma(node, property) {
|
168
180
|
const items = node[property],
|
169
|
-
arrayLiteral = (node.type === "ArrayExpression");
|
181
|
+
arrayLiteral = (node.type === "ArrayExpression" || node.type === "ArrayPattern");
|
170
182
|
|
171
183
|
if (items.length > 1 || arrayLiteral) {
|
172
184
|
|
173
185
|
// seed as opening [
|
174
186
|
let previousItemToken = sourceCode.getFirstToken(node);
|
175
187
|
|
176
|
-
items.forEach(
|
188
|
+
items.forEach(item => {
|
177
189
|
const commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken,
|
178
190
|
currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken),
|
179
191
|
reportItem = item || currentItemToken,
|
@@ -245,11 +257,46 @@ module.exports = {
|
|
245
257
|
validateComma(node, "properties");
|
246
258
|
};
|
247
259
|
}
|
260
|
+
if (!exceptions.ObjectPattern) {
|
261
|
+
nodes.ObjectPattern = function(node) {
|
262
|
+
validateComma(node, "properties");
|
263
|
+
};
|
264
|
+
}
|
248
265
|
if (!exceptions.ArrayExpression) {
|
249
266
|
nodes.ArrayExpression = function(node) {
|
250
267
|
validateComma(node, "elements");
|
251
268
|
};
|
252
269
|
}
|
270
|
+
if (!exceptions.ArrayPattern) {
|
271
|
+
nodes.ArrayPattern = function(node) {
|
272
|
+
validateComma(node, "elements");
|
273
|
+
};
|
274
|
+
}
|
275
|
+
if (!exceptions.FunctionDeclaration) {
|
276
|
+
nodes.FunctionDeclaration = function(node) {
|
277
|
+
validateComma(node, "params");
|
278
|
+
};
|
279
|
+
}
|
280
|
+
if (!exceptions.FunctionExpression) {
|
281
|
+
nodes.FunctionExpression = function(node) {
|
282
|
+
validateComma(node, "params");
|
283
|
+
};
|
284
|
+
}
|
285
|
+
if (!exceptions.ArrowFunctionExpression) {
|
286
|
+
nodes.ArrowFunctionExpression = function(node) {
|
287
|
+
validateComma(node, "params");
|
288
|
+
};
|
289
|
+
}
|
290
|
+
if (!exceptions.CallExpression) {
|
291
|
+
nodes.CallExpression = function(node) {
|
292
|
+
validateComma(node, "arguments");
|
293
|
+
};
|
294
|
+
}
|
295
|
+
if (!exceptions.ImportDeclaration) {
|
296
|
+
nodes.ImportDeclaration = function(node) {
|
297
|
+
validateComma(node, "specifiers");
|
298
|
+
};
|
299
|
+
}
|
253
300
|
|
254
301
|
return nodes;
|
255
302
|
}
|
@@ -84,16 +84,14 @@ module.exports = {
|
|
84
84
|
return;
|
85
85
|
}
|
86
86
|
|
87
|
-
if (variable.defs.some(
|
88
|
-
|
89
|
-
def.node.init !== null;
|
90
|
-
})) {
|
87
|
+
if (variable.defs.some(def => def.node.type === "VariableDeclarator" &&
|
88
|
+
def.node.init !== null)) {
|
91
89
|
return;
|
92
90
|
}
|
93
91
|
|
94
92
|
// The alias has been declared and not assigned: check it was
|
95
93
|
// assigned later in the same scope.
|
96
|
-
if (!variable.references.some(
|
94
|
+
if (!variable.references.some(reference => {
|
97
95
|
const write = reference.writeExpr;
|
98
96
|
|
99
97
|
return (
|
@@ -102,9 +100,7 @@ module.exports = {
|
|
102
100
|
write.parent.operator === "="
|
103
101
|
);
|
104
102
|
})) {
|
105
|
-
variable.defs.map(
|
106
|
-
return def.node;
|
107
|
-
}).forEach(function(node) {
|
103
|
+
variable.defs.map(def => def.node).forEach(node => {
|
108
104
|
reportBadAssignment(node, alias);
|
109
105
|
});
|
110
106
|
}
|
@@ -117,7 +113,7 @@ module.exports = {
|
|
117
113
|
function ensureWasAssigned() {
|
118
114
|
const scope = context.getScope();
|
119
115
|
|
120
|
-
aliases.forEach(
|
116
|
+
aliases.forEach(alias => {
|
121
117
|
checkWasAssigned(alias, scope);
|
122
118
|
});
|
123
119
|
}
|
package/lib/rules/curly.js
CHANGED
@@ -74,10 +74,11 @@ module.exports = {
|
|
74
74
|
* @private
|
75
75
|
*/
|
76
76
|
function isCollapsedOneLiner(node) {
|
77
|
-
const before = sourceCode.getTokenBefore(node)
|
78
|
-
|
77
|
+
const before = sourceCode.getTokenBefore(node);
|
78
|
+
const last = sourceCode.getLastToken(node);
|
79
|
+
const lastExcludingSemicolon = last.type === "Punctuator" && last.value === ";" ? sourceCode.getTokenBefore(last) : last;
|
79
80
|
|
80
|
-
return before.loc.start.line ===
|
81
|
+
return before.loc.start.line === lastExcludingSemicolon.loc.end.line;
|
81
82
|
}
|
82
83
|
|
83
84
|
/**
|
@@ -289,7 +290,9 @@ module.exports = {
|
|
289
290
|
}
|
290
291
|
} else if (multiOrNest) {
|
291
292
|
if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) {
|
292
|
-
|
293
|
+
const leadingComments = sourceCode.getComments(body.body[0]).leading;
|
294
|
+
|
295
|
+
expected = leadingComments.length > 0;
|
293
296
|
} else if (!isOneLiner(body)) {
|
294
297
|
expected = true;
|
295
298
|
}
|
@@ -337,14 +340,14 @@ module.exports = {
|
|
337
340
|
* all have braces.
|
338
341
|
* If all nodes shouldn't have braces, make sure they don't.
|
339
342
|
*/
|
340
|
-
const expected = preparedChecks.some(
|
343
|
+
const expected = preparedChecks.some(preparedCheck => {
|
341
344
|
if (preparedCheck.expected !== null) {
|
342
345
|
return preparedCheck.expected;
|
343
346
|
}
|
344
347
|
return preparedCheck.actual;
|
345
348
|
});
|
346
349
|
|
347
|
-
preparedChecks.forEach(
|
350
|
+
preparedChecks.forEach(preparedCheck => {
|
348
351
|
preparedCheck.expected = expected;
|
349
352
|
});
|
350
353
|
}
|
@@ -359,7 +362,7 @@ module.exports = {
|
|
359
362
|
return {
|
360
363
|
IfStatement(node) {
|
361
364
|
if (node.parent.type !== "IfStatement") {
|
362
|
-
prepareIfChecks(node).forEach(
|
365
|
+
prepareIfChecks(node).forEach(preparedCheck => {
|
363
366
|
preparedCheck.check();
|
364
367
|
});
|
365
368
|
}
|
package/lib/rules/eqeqeq.js
CHANGED
@@ -47,7 +47,9 @@ module.exports = {
|
|
47
47
|
additionalItems: false
|
48
48
|
}
|
49
49
|
]
|
50
|
-
}
|
50
|
+
},
|
51
|
+
|
52
|
+
fixable: "code"
|
51
53
|
},
|
52
54
|
|
53
55
|
create(context) {
|
@@ -118,16 +120,26 @@ module.exports = {
|
|
118
120
|
/**
|
119
121
|
* Reports a message for this rule.
|
120
122
|
* @param {ASTNode} node The binary expression node that was checked
|
121
|
-
* @param {string}
|
123
|
+
* @param {string} expectedOperator The operator that was expected (either '==', '!=', '===', or '!==')
|
122
124
|
* @returns {void}
|
123
125
|
* @private
|
124
126
|
*/
|
125
|
-
function report(node,
|
127
|
+
function report(node, expectedOperator) {
|
126
128
|
context.report({
|
127
129
|
node,
|
128
130
|
loc: getOperatorLocation(node),
|
129
|
-
message,
|
130
|
-
data: {
|
131
|
+
message: "Expected '{{expectedOperator}}' and instead saw '{{actualOperator}}'.",
|
132
|
+
data: {expectedOperator, actualOperator: node.operator},
|
133
|
+
fix(fixer) {
|
134
|
+
|
135
|
+
// If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
|
136
|
+
if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
|
137
|
+
const operatorToken = sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator);
|
138
|
+
|
139
|
+
return fixer.replaceText(operatorToken, expectedOperator);
|
140
|
+
}
|
141
|
+
return null;
|
142
|
+
}
|
131
143
|
});
|
132
144
|
}
|
133
145
|
|
@@ -137,7 +149,7 @@ module.exports = {
|
|
137
149
|
|
138
150
|
if (node.operator !== "==" && node.operator !== "!=") {
|
139
151
|
if (enforceInverseRuleForNull && isNull) {
|
140
|
-
report(node,
|
152
|
+
report(node, node.operator.slice(0, -1));
|
141
153
|
}
|
142
154
|
return;
|
143
155
|
}
|
@@ -151,7 +163,7 @@ module.exports = {
|
|
151
163
|
return;
|
152
164
|
}
|
153
165
|
|
154
|
-
report(node,
|
166
|
+
report(node, `${node.operator}=`);
|
155
167
|
}
|
156
168
|
};
|
157
169
|
|
package/lib/rules/func-names.js
CHANGED
@@ -28,21 +28,23 @@ module.exports = {
|
|
28
28
|
|
29
29
|
schema: [
|
30
30
|
{
|
31
|
-
enum: ["always", "never"]
|
31
|
+
enum: ["always", "as-needed", "never"]
|
32
32
|
}
|
33
33
|
]
|
34
34
|
},
|
35
35
|
|
36
36
|
create(context) {
|
37
37
|
const never = context.options[0] === "never";
|
38
|
+
const asNeeded = context.options[0] === "as-needed";
|
38
39
|
|
39
40
|
/**
|
40
41
|
* Determines whether the current FunctionExpression node is a get, set, or
|
41
42
|
* shorthand method in an object literal or a class.
|
43
|
+
* @param {ASTNode} node - A node to check.
|
42
44
|
* @returns {boolean} True if the node is a get, set, or shorthand method.
|
43
45
|
*/
|
44
|
-
function isObjectOrClassMethod() {
|
45
|
-
const parent =
|
46
|
+
function isObjectOrClassMethod(node) {
|
47
|
+
const parent = node.parent;
|
46
48
|
|
47
49
|
return (parent.type === "MethodDefinition" || (
|
48
50
|
parent.type === "Property" && (
|
@@ -53,6 +55,23 @@ module.exports = {
|
|
53
55
|
));
|
54
56
|
}
|
55
57
|
|
58
|
+
/**
|
59
|
+
* Determines whether the current FunctionExpression node has a name that would be
|
60
|
+
* inferred from context in a conforming ES6 environment.
|
61
|
+
* @param {ASTNode} node - A node to check.
|
62
|
+
* @returns {boolean} True if the node would have a name assigned automatically.
|
63
|
+
*/
|
64
|
+
function hasInferredName(node) {
|
65
|
+
const parent = node.parent;
|
66
|
+
|
67
|
+
return isObjectOrClassMethod(node) ||
|
68
|
+
(parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node) ||
|
69
|
+
(parent.type === "Property" && parent.value === node) ||
|
70
|
+
(parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) ||
|
71
|
+
(parent.type === "ExportDefaultDeclaration" && parent.declaration === node) ||
|
72
|
+
(parent.type === "AssignmentPattern" && parent.right === node);
|
73
|
+
}
|
74
|
+
|
56
75
|
return {
|
57
76
|
"FunctionExpression:exit"(node) {
|
58
77
|
|
@@ -70,7 +89,7 @@ module.exports = {
|
|
70
89
|
context.report(node, "Unexpected function expression name.");
|
71
90
|
}
|
72
91
|
} else {
|
73
|
-
if (!name && !isObjectOrClassMethod()) {
|
92
|
+
if (!name && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) {
|
74
93
|
context.report(node, "Missing function expression name.");
|
75
94
|
}
|
76
95
|
}
|
@@ -23,10 +23,8 @@ const ACCEPTABLE_PARENTS = [
|
|
23
23
|
* @returns {Reference|null} Returns the found reference or null if none were found.
|
24
24
|
*/
|
25
25
|
function findReference(scope, node) {
|
26
|
-
const references = scope.references.filter(
|
27
|
-
|
28
|
-
reference.identifier.range[1] === node.range[1];
|
29
|
-
});
|
26
|
+
const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] &&
|
27
|
+
reference.identifier.range[1] === node.range[1]);
|
30
28
|
|
31
29
|
/* istanbul ignore else: correctly returns null */
|
32
30
|
if (references.length === 1) {
|
@@ -65,9 +63,7 @@ module.exports = {
|
|
65
63
|
const currentScope = context.getScope();
|
66
64
|
|
67
65
|
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
|
68
|
-
const isGoodRequire = context.getAncestors().every(
|
69
|
-
return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1;
|
70
|
-
});
|
66
|
+
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.indexOf(parent.type) > -1);
|
71
67
|
|
72
68
|
if (!isGoodRequire) {
|
73
69
|
context.report(node, "Unexpected require().");
|
@@ -59,9 +59,7 @@ module.exports = {
|
|
59
59
|
* @returns {array} All parameters of the given scope.
|
60
60
|
*/
|
61
61
|
function getParameters(scope) {
|
62
|
-
return scope.variables.filter(
|
63
|
-
return variable.defs[0] && variable.defs[0].type === "Parameter";
|
64
|
-
});
|
62
|
+
return scope.variables.filter(variable => variable.defs[0] && variable.defs[0].type === "Parameter");
|
65
63
|
}
|
66
64
|
|
67
65
|
/**
|
package/lib/rules/id-length.js
CHANGED
@@ -50,7 +50,7 @@ module.exports = {
|
|
50
50
|
const maxLength = typeof options.max !== "undefined" ? options.max : Infinity;
|
51
51
|
const properties = options.properties !== "never";
|
52
52
|
const exceptions = (options.exceptions ? options.exceptions : [])
|
53
|
-
.reduce(
|
53
|
+
.reduce((obj, item) => {
|
54
54
|
obj[item] = true;
|
55
55
|
|
56
56
|
return obj;
|
package/lib/rules/indent.js
CHANGED
@@ -255,20 +255,18 @@ module.exports = {
|
|
255
255
|
* @param {int} lastNodeCheckEndOffset Number of charecters to skip from the end
|
256
256
|
* @returns {void}
|
257
257
|
*/
|
258
|
-
function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck
|
258
|
+
function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck) {
|
259
259
|
if (gottenSpaces && gottenTabs) {
|
260
260
|
|
261
261
|
// To avoid conflicts with `no-mixed-spaces-and-tabs`, don't report lines that have both spaces and tabs.
|
262
262
|
return;
|
263
263
|
}
|
264
264
|
|
265
|
-
|
266
|
-
|
267
|
-
const desiredIndent = (indentType === "space" ? " " : "\t").repeat(needed - lastNodeCheckEndOffset);
|
265
|
+
const desiredIndent = (indentType === "space" ? " " : "\t").repeat(needed);
|
268
266
|
|
269
267
|
const textRange = isLastNodeCheck
|
270
|
-
? [node.range[1] -
|
271
|
-
: [node.range[0] -
|
268
|
+
? [node.range[1] - node.loc.end.column, node.range[1] - node.loc.end.column + gottenSpaces + gottenTabs]
|
269
|
+
: [node.range[0] - node.loc.start.column, node.range[0] - node.loc.start.column + gottenSpaces + gottenTabs];
|
272
270
|
|
273
271
|
context.report({
|
274
272
|
node,
|
@@ -406,13 +404,11 @@ module.exports = {
|
|
406
404
|
*/
|
407
405
|
function checkLastReturnStatementLineIndent(node, firstLineIndent) {
|
408
406
|
const nodeLastToken = sourceCode.getLastToken(node);
|
409
|
-
let lastNodeCheckEndOffset = 0;
|
410
407
|
let lastToken = nodeLastToken;
|
411
408
|
|
412
409
|
// in case if return statement ends with ');' we have traverse back to ')'
|
413
410
|
// otherwise we'll measure indent for ';' and replace ')'
|
414
411
|
while (lastToken.value !== ")") {
|
415
|
-
lastNodeCheckEndOffset++;
|
416
412
|
lastToken = sourceCode.getTokenBefore(lastToken);
|
417
413
|
}
|
418
414
|
|
@@ -433,8 +429,7 @@ module.exports = {
|
|
433
429
|
endIndent.space,
|
434
430
|
endIndent.tab,
|
435
431
|
{ line: lastToken.loc.start.line, column: lastToken.loc.start.column },
|
436
|
-
true
|
437
|
-
lastNodeCheckEndOffset
|
432
|
+
true
|
438
433
|
);
|
439
434
|
}
|
440
435
|
}
|
@@ -684,9 +679,7 @@ module.exports = {
|
|
684
679
|
let elements = (node.type === "ArrayExpression") ? node.elements : node.properties;
|
685
680
|
|
686
681
|
// filter out empty elements example would be [ , 2] so remove first element as espree considers it as null
|
687
|
-
elements = elements.filter(
|
688
|
-
return elem !== null;
|
689
|
-
});
|
682
|
+
elements = elements.filter(elem => elem !== null);
|
690
683
|
|
691
684
|
let nodeIndent;
|
692
685
|
let elementsIndent;
|
@@ -695,19 +688,11 @@ module.exports = {
|
|
695
688
|
// TODO - come up with a better strategy in future
|
696
689
|
if (isNodeFirstInLine(node)) {
|
697
690
|
const parent = node.parent;
|
698
|
-
let effectiveParent = parent;
|
699
691
|
|
700
|
-
|
701
|
-
if (isNodeFirstInLine(parent)) {
|
702
|
-
effectiveParent = parent.parent.parent;
|
703
|
-
} else {
|
704
|
-
effectiveParent = parent.parent;
|
705
|
-
}
|
706
|
-
}
|
707
|
-
nodeIndent = getNodeIndent(effectiveParent).goodChar;
|
692
|
+
nodeIndent = getNodeIndent(parent).goodChar;
|
708
693
|
if (parentVarNode && parentVarNode.loc.start.line !== node.loc.start.line) {
|
709
694
|
if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
|
710
|
-
if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line ===
|
695
|
+
if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
|
711
696
|
nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
|
712
697
|
} else if (
|
713
698
|
parent.type === "ObjectExpression" ||
|
@@ -720,7 +705,7 @@ module.exports = {
|
|
720
705
|
nodeIndent = nodeIndent + indentSize;
|
721
706
|
}
|
722
707
|
}
|
723
|
-
} else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) &&
|
708
|
+
} else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
|
724
709
|
nodeIndent = nodeIndent + indentSize;
|
725
710
|
}
|
726
711
|
|
@@ -827,7 +812,7 @@ module.exports = {
|
|
827
812
|
* @returns {ASTNode[]} Filtered elements
|
828
813
|
*/
|
829
814
|
function filterOutSameLineVars(node) {
|
830
|
-
return node.declarations.reduce(
|
815
|
+
return node.declarations.reduce((finalCollection, elem) => {
|
831
816
|
const lastElem = finalCollection[finalCollection.length - 1];
|
832
817
|
|
833
818
|
if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
|
package/lib/rules/key-spacing.js
CHANGED
@@ -417,8 +417,8 @@ module.exports = {
|
|
417
417
|
function report(property, side, whitespace, expected, mode) {
|
418
418
|
const diff = whitespace.length - expected,
|
419
419
|
nextColon = getNextColon(property.key),
|
420
|
-
tokenBeforeColon = sourceCode.
|
421
|
-
tokenAfterColon = sourceCode.
|
420
|
+
tokenBeforeColon = sourceCode.getTokenOrCommentBefore(nextColon),
|
421
|
+
tokenAfterColon = sourceCode.getTokenOrCommentAfter(nextColon),
|
422
422
|
isKeySide = side === "key",
|
423
423
|
locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
|
424
424
|
isExtra = diff > 0,
|
@@ -514,7 +514,7 @@ module.exports = {
|
|
514
514
|
return [node.properties];
|
515
515
|
}
|
516
516
|
|
517
|
-
return node.properties.reduce(
|
517
|
+
return node.properties.reduce((groups, property) => {
|
518
518
|
const currentGroup = last(groups),
|
519
519
|
prev = last(currentGroup);
|
520
520
|
|
@@ -579,7 +579,7 @@ module.exports = {
|
|
579
579
|
* @returns {void}
|
580
580
|
*/
|
581
581
|
function verifyAlignment(node) {
|
582
|
-
createGroups(node).forEach(
|
582
|
+
createGroups(node).forEach(group => {
|
583
583
|
verifyGroupAlignment(group.filter(isKeyValueProperty));
|
584
584
|
});
|
585
585
|
}
|
@@ -21,16 +21,10 @@ const lodash = require("lodash"),
|
|
21
21
|
* @returns {Array} An array of line numbers.
|
22
22
|
*/
|
23
23
|
function getEmptyLineNums(lines) {
|
24
|
-
const emptyLines = lines.map(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
};
|
29
|
-
}).filter(function(line) {
|
30
|
-
return !line.code;
|
31
|
-
}).map(function(line) {
|
32
|
-
return line.num;
|
33
|
-
});
|
24
|
+
const emptyLines = lines.map((line, i) => ({
|
25
|
+
code: line.trim(),
|
26
|
+
num: i + 1
|
27
|
+
})).filter(line => !line.code).map(line => line.num);
|
34
28
|
|
35
29
|
return emptyLines;
|
36
30
|
}
|
@@ -43,7 +37,7 @@ function getEmptyLineNums(lines) {
|
|
43
37
|
function getCommentLineNums(comments) {
|
44
38
|
const lines = [];
|
45
39
|
|
46
|
-
comments.forEach(
|
40
|
+
comments.forEach(token => {
|
47
41
|
const start = token.loc.start.line;
|
48
42
|
const end = token.loc.end.line;
|
49
43
|
|
@@ -63,15 +63,32 @@ module.exports = {
|
|
63
63
|
return node.loc.start.line - tokenLineBefore >= 2;
|
64
64
|
}
|
65
65
|
|
66
|
+
/**
|
67
|
+
* Gets the last token of a node that is on the same line as the rest of the node.
|
68
|
+
* This will usually be the last token of the node, but it will be the second-to-last token if the node has a trailing
|
69
|
+
* semicolon on a different line.
|
70
|
+
* @param {ASTNode} node A directive node
|
71
|
+
* @returns {Token} The last token of the node on the line
|
72
|
+
*/
|
73
|
+
function getLastTokenOnLine(node) {
|
74
|
+
const lastToken = sourceCode.getLastToken(node);
|
75
|
+
const secondToLastToken = sourceCode.getTokenBefore(lastToken);
|
76
|
+
|
77
|
+
return lastToken.type === "Punctuator" && lastToken.value === ";" && lastToken.loc.start.line > secondToLastToken.loc.end.line
|
78
|
+
? secondToLastToken
|
79
|
+
: lastToken;
|
80
|
+
}
|
81
|
+
|
66
82
|
/**
|
67
83
|
* Check if node is followed by a blank newline.
|
68
84
|
* @param {ASTNode} node Node to check.
|
69
85
|
* @returns {boolean} Whether or not the passed in node is followed by a blank newline.
|
70
86
|
*/
|
71
87
|
function hasNewlineAfter(node) {
|
72
|
-
const
|
88
|
+
const lastToken = getLastTokenOnLine(node);
|
89
|
+
const tokenAfter = sourceCode.getTokenOrCommentAfter(lastToken);
|
73
90
|
|
74
|
-
return tokenAfter.loc.start.line -
|
91
|
+
return tokenAfter.loc.start.line - lastToken.loc.end.line >= 2;
|
75
92
|
}
|
76
93
|
|
77
94
|
/**
|
@@ -91,10 +108,12 @@ module.exports = {
|
|
91
108
|
location
|
92
109
|
},
|
93
110
|
fix(fixer) {
|
111
|
+
const lastToken = getLastTokenOnLine(node);
|
112
|
+
|
94
113
|
if (expected) {
|
95
|
-
return location === "before" ? fixer.insertTextBefore(node, "\n") : fixer.insertTextAfter(
|
114
|
+
return location === "before" ? fixer.insertTextBefore(node, "\n") : fixer.insertTextAfter(lastToken, "\n");
|
96
115
|
}
|
97
|
-
return fixer.removeRange(location === "before" ? [node.range[0] - 1, node.range[0]] : [
|
116
|
+
return fixer.removeRange(location === "before" ? [node.range[0] - 1, node.range[0]] : [lastToken.range[1], lastToken.range[1] + 1]);
|
98
117
|
}
|
99
118
|
});
|
100
119
|
}
|
package/lib/rules/max-len.js
CHANGED
@@ -103,7 +103,7 @@ module.exports = {
|
|
103
103
|
function computeLineLength(line, tabWidth) {
|
104
104
|
let extraCharacterCount = 0;
|
105
105
|
|
106
|
-
line.replace(/\t/g,
|
106
|
+
line.replace(/\t/g, (match, offset) => {
|
107
107
|
const totalOffset = offset + extraCharacterCount,
|
108
108
|
previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0,
|
109
109
|
spaceCount = tabWidth - previousTabStopOffset;
|
@@ -213,9 +213,7 @@ module.exports = {
|
|
213
213
|
* @returns {ASTNode[]} An array of string nodes.
|
214
214
|
*/
|
215
215
|
function getAllStrings() {
|
216
|
-
return sourceCode.ast.tokens.filter(
|
217
|
-
return token.type === "String";
|
218
|
-
});
|
216
|
+
return sourceCode.ast.tokens.filter(token => token.type === "String");
|
219
217
|
}
|
220
218
|
|
221
219
|
/**
|
@@ -224,9 +222,7 @@ module.exports = {
|
|
224
222
|
* @returns {ASTNode[]} An array of template literal nodes.
|
225
223
|
*/
|
226
224
|
function getAllTemplateLiterals() {
|
227
|
-
return sourceCode.ast.tokens.filter(
|
228
|
-
return token.type === "Template";
|
229
|
-
});
|
225
|
+
return sourceCode.ast.tokens.filter(token => token.type === "Template");
|
230
226
|
}
|
231
227
|
|
232
228
|
|
@@ -236,9 +232,7 @@ module.exports = {
|
|
236
232
|
* @returns {ASTNode[]} An array of RegExp literal nodes.
|
237
233
|
*/
|
238
234
|
function getAllRegExpLiterals() {
|
239
|
-
return sourceCode.ast.tokens.filter(
|
240
|
-
return token.type === "RegularExpression";
|
241
|
-
});
|
235
|
+
return sourceCode.ast.tokens.filter(token => token.type === "RegularExpression");
|
242
236
|
}
|
243
237
|
|
244
238
|
|
@@ -283,7 +277,7 @@ module.exports = {
|
|
283
277
|
const regExpLiterals = getAllRegExpLiterals(sourceCode);
|
284
278
|
const regExpLiteralsByLine = regExpLiterals.reduce(groupByLineNumber, {});
|
285
279
|
|
286
|
-
lines.forEach(
|
280
|
+
lines.forEach((line, i) => {
|
287
281
|
|
288
282
|
// i is zero-indexed, line numbers are one-indexed
|
289
283
|
const lineNumber = i + 1;
|