eslint 3.16.0 → 3.18.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 +73 -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/eslint.js +5 -5
- 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/capitalized-comments.js +2 -1
- package/lib/rules/complexity.js +14 -8
- package/lib/rules/consistent-return.js +17 -10
- 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/max-params.js +17 -4
- package/lib/rules/max-statements.js +11 -10
- package/lib/rules/no-compare-neg-zero.js +53 -0
- package/lib/rules/no-else-return.js +13 -1
- package/lib/rules/no-empty-function.js +9 -16
- package/lib/rules/no-extra-parens.js +64 -19
- package/lib/rules/no-extra-semi.js +13 -1
- package/lib/rules/no-global-assign.js +1 -1
- package/lib/rules/no-invalid-regexp.js +2 -1
- package/lib/rules/no-multiple-empty-lines.js +2 -4
- package/lib/rules/no-new-func.js +6 -8
- package/lib/rules/no-new.js +2 -6
- package/lib/rules/no-param-reassign.js +29 -6
- 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 +6 -22
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sync.js +8 -13
- 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-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-shorthand.js +2 -1
- package/lib/rules/operator-assignment.js +1 -1
- package/lib/rules/padded-blocks.js +37 -28
- package/lib/rules/prefer-destructuring.js +1 -1
- package/lib/rules/semi.js +13 -1
- package/lib/rules/sort-vars.js +3 -5
- 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/node-event-generator.js +274 -4
- package/lib/util/source-code-fixer.js +2 -2
- package/lib/util/source-code.js +99 -2
- package/lib/util/traverser.js +16 -25
- package/package.json +8 -8
@@ -67,6 +67,8 @@ module.exports = {
|
|
67
67
|
const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false;
|
68
68
|
const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false;
|
69
69
|
const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX;
|
70
|
+
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
|
71
|
+
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
|
70
72
|
|
71
73
|
/**
|
72
74
|
* Determines if this rule should be enforced for a node given the current configuration.
|
@@ -365,7 +367,7 @@ module.exports = {
|
|
365
367
|
* @returns {void}
|
366
368
|
* @private
|
367
369
|
*/
|
368
|
-
function
|
370
|
+
function checkUnaryUpdate(node) {
|
369
371
|
if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") {
|
370
372
|
return;
|
371
373
|
}
|
@@ -381,7 +383,7 @@ module.exports = {
|
|
381
383
|
* @returns {void}
|
382
384
|
* @private
|
383
385
|
*/
|
384
|
-
function
|
386
|
+
function checkCallNew(node) {
|
385
387
|
if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !(
|
386
388
|
node.type === "CallExpression" &&
|
387
389
|
(node.callee.type === "FunctionExpression" ||
|
@@ -393,12 +395,12 @@ module.exports = {
|
|
393
395
|
report(node.callee);
|
394
396
|
}
|
395
397
|
if (node.arguments.length === 1) {
|
396
|
-
if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >=
|
398
|
+
if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
397
399
|
report(node.arguments[0]);
|
398
400
|
}
|
399
401
|
} else {
|
400
402
|
[].forEach.call(node.arguments, arg => {
|
401
|
-
if (hasExcessParens(arg) && precedence(arg) >=
|
403
|
+
if (hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
402
404
|
report(arg);
|
403
405
|
}
|
404
406
|
});
|
@@ -411,7 +413,7 @@ module.exports = {
|
|
411
413
|
* @returns {void}
|
412
414
|
* @private
|
413
415
|
*/
|
414
|
-
function
|
416
|
+
function checkBinaryLogical(node) {
|
415
417
|
const prec = precedence(node);
|
416
418
|
const leftPrecedence = precedence(node.left);
|
417
419
|
const rightPrecedence = precedence(node.right);
|
@@ -428,10 +430,46 @@ module.exports = {
|
|
428
430
|
}
|
429
431
|
}
|
430
432
|
|
433
|
+
/**
|
434
|
+
* Check the parentheses around the super class of the given class definition.
|
435
|
+
* @param {ASTNode} node The node of class declarations to check.
|
436
|
+
* @returns {void}
|
437
|
+
*/
|
438
|
+
function checkClass(node) {
|
439
|
+
if (!node.superClass) {
|
440
|
+
return;
|
441
|
+
}
|
442
|
+
|
443
|
+
// If `node.superClass` is a LeftHandSideExpression, parentheses are extra.
|
444
|
+
// Otherwise, parentheses are needed.
|
445
|
+
const hasExtraParens = precedence(node.superClass) > PRECEDENCE_OF_UPDATE_EXPR
|
446
|
+
? hasExcessParens(node.superClass)
|
447
|
+
: hasDoubleExcessParens(node.superClass);
|
448
|
+
|
449
|
+
if (hasExtraParens) {
|
450
|
+
report(node.superClass);
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
/**
|
455
|
+
* Check the parentheses around the argument of the given spread operator.
|
456
|
+
* @param {ASTNode} node The node of spread elements/properties to check.
|
457
|
+
* @returns {void}
|
458
|
+
*/
|
459
|
+
function checkSpreadOperator(node) {
|
460
|
+
const hasExtraParens = precedence(node.argument) >= PRECEDENCE_OF_ASSIGNMENT_EXPR
|
461
|
+
? hasExcessParens(node.argument)
|
462
|
+
: hasDoubleExcessParens(node.argument);
|
463
|
+
|
464
|
+
if (hasExtraParens) {
|
465
|
+
report(node.argument);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
|
431
469
|
return {
|
432
470
|
ArrayExpression(node) {
|
433
471
|
[].forEach.call(node.elements, e => {
|
434
|
-
if (e && hasExcessParens(e) && precedence(e) >=
|
472
|
+
if (e && hasExcessParens(e) && precedence(e) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
435
473
|
report(e);
|
436
474
|
}
|
437
475
|
});
|
@@ -443,7 +481,7 @@ module.exports = {
|
|
443
481
|
}
|
444
482
|
|
445
483
|
if (node.body.type !== "BlockStatement") {
|
446
|
-
if (sourceCode.getFirstToken(node.body).value !== "{" && hasExcessParens(node.body) && precedence(node.body) >=
|
484
|
+
if (sourceCode.getFirstToken(node.body).value !== "{" && hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
447
485
|
report(node.body);
|
448
486
|
return;
|
449
487
|
}
|
@@ -465,8 +503,8 @@ module.exports = {
|
|
465
503
|
}
|
466
504
|
},
|
467
505
|
|
468
|
-
BinaryExpression:
|
469
|
-
CallExpression:
|
506
|
+
BinaryExpression: checkBinaryLogical,
|
507
|
+
CallExpression: checkCallNew,
|
470
508
|
|
471
509
|
ConditionalExpression(node) {
|
472
510
|
if (isReturnAssignException(node)) {
|
@@ -477,11 +515,11 @@ module.exports = {
|
|
477
515
|
report(node.test);
|
478
516
|
}
|
479
517
|
|
480
|
-
if (hasExcessParens(node.consequent) && precedence(node.consequent) >=
|
518
|
+
if (hasExcessParens(node.consequent) && precedence(node.consequent) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
481
519
|
report(node.consequent);
|
482
520
|
}
|
483
521
|
|
484
|
-
if (hasExcessParens(node.alternate) && precedence(node.alternate) >=
|
522
|
+
if (hasExcessParens(node.alternate) && precedence(node.alternate) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
485
523
|
report(node.alternate);
|
486
524
|
}
|
487
525
|
},
|
@@ -546,7 +584,7 @@ module.exports = {
|
|
546
584
|
}
|
547
585
|
},
|
548
586
|
|
549
|
-
LogicalExpression:
|
587
|
+
LogicalExpression: checkBinaryLogical,
|
550
588
|
|
551
589
|
MemberExpression(node) {
|
552
590
|
if (
|
@@ -576,13 +614,13 @@ module.exports = {
|
|
576
614
|
}
|
577
615
|
},
|
578
616
|
|
579
|
-
NewExpression:
|
617
|
+
NewExpression: checkCallNew,
|
580
618
|
|
581
619
|
ObjectExpression(node) {
|
582
620
|
[].forEach.call(node.properties, e => {
|
583
621
|
const v = e.value;
|
584
622
|
|
585
|
-
if (v && hasExcessParens(v) && precedence(v) >=
|
623
|
+
if (v && hasExcessParens(v) && precedence(v) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
586
624
|
report(v);
|
587
625
|
}
|
588
626
|
});
|
@@ -632,13 +670,13 @@ module.exports = {
|
|
632
670
|
}
|
633
671
|
},
|
634
672
|
|
635
|
-
UnaryExpression:
|
636
|
-
UpdateExpression:
|
637
|
-
AwaitExpression:
|
673
|
+
UnaryExpression: checkUnaryUpdate,
|
674
|
+
UpdateExpression: checkUnaryUpdate,
|
675
|
+
AwaitExpression: checkUnaryUpdate,
|
638
676
|
|
639
677
|
VariableDeclarator(node) {
|
640
678
|
if (node.init && hasExcessParens(node.init) &&
|
641
|
-
precedence(node.init) >=
|
679
|
+
precedence(node.init) >= PRECEDENCE_OF_ASSIGNMENT_EXPR &&
|
642
680
|
|
643
681
|
// RegExp literal is allowed to have parens (#1589)
|
644
682
|
!(node.init.type === "Literal" && node.init.regex)) {
|
@@ -668,7 +706,14 @@ module.exports = {
|
|
668
706
|
report(node.argument);
|
669
707
|
}
|
670
708
|
}
|
671
|
-
}
|
709
|
+
},
|
710
|
+
|
711
|
+
ClassDeclaration: checkClass,
|
712
|
+
ClassExpression: checkClass,
|
713
|
+
|
714
|
+
SpreadElement: checkSpreadOperator,
|
715
|
+
SpreadProperty: checkSpreadOperator,
|
716
|
+
ExperimentalSpreadProperty: checkSpreadOperator
|
672
717
|
};
|
673
718
|
|
674
719
|
}
|
@@ -5,6 +5,12 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const FixTracker = require("../util/fix-tracker");
|
13
|
+
|
8
14
|
//------------------------------------------------------------------------------
|
9
15
|
// Rule Definition
|
10
16
|
//------------------------------------------------------------------------------
|
@@ -34,7 +40,13 @@ module.exports = {
|
|
34
40
|
node: nodeOrToken,
|
35
41
|
message: "Unnecessary semicolon.",
|
36
42
|
fix(fixer) {
|
37
|
-
|
43
|
+
|
44
|
+
// Expand the replacement range to include the surrounding
|
45
|
+
// tokens to avoid conflicting with semi.
|
46
|
+
// https://github.com/eslint/eslint/issues/7928
|
47
|
+
return new FixTracker(fixer, context.getSourceCode())
|
48
|
+
.retainSurroundingTokens(nodeOrToken)
|
49
|
+
.remove(nodeOrToken);
|
38
50
|
}
|
39
51
|
});
|
40
52
|
}
|
@@ -5,8 +5,6 @@
|
|
5
5
|
*/
|
6
6
|
"use strict";
|
7
7
|
|
8
|
-
const astUtils = require("../ast-utils");
|
9
|
-
|
10
8
|
//------------------------------------------------------------------------------
|
11
9
|
// Rule Definition
|
12
10
|
//------------------------------------------------------------------------------
|
@@ -114,8 +112,8 @@ module.exports = {
|
|
114
112
|
data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" },
|
115
113
|
fix(fixer) {
|
116
114
|
return fixer.removeRange([
|
117
|
-
|
118
|
-
|
115
|
+
sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 }),
|
116
|
+
sourceCode.getIndexFromLoc({ line: lineNumber - maxAllowed, column: 0 })
|
119
117
|
]);
|
120
118
|
}
|
121
119
|
});
|
package/lib/rules/no-new-func.js
CHANGED
@@ -27,20 +27,18 @@ module.exports = {
|
|
27
27
|
//--------------------------------------------------------------------------
|
28
28
|
|
29
29
|
/**
|
30
|
-
*
|
31
|
-
* @param {ASTNode} node The node to
|
30
|
+
* Reports a node.
|
31
|
+
* @param {ASTNode} node The node to report
|
32
32
|
* @returns {void}
|
33
33
|
* @private
|
34
34
|
*/
|
35
|
-
function
|
36
|
-
|
37
|
-
context.report({ node, message: "The Function constructor is eval." });
|
38
|
-
}
|
35
|
+
function report(node) {
|
36
|
+
context.report({ node, message: "The Function constructor is eval." });
|
39
37
|
}
|
40
38
|
|
41
39
|
return {
|
42
|
-
NewExpression:
|
43
|
-
CallExpression:
|
40
|
+
"NewExpression[callee.name = 'Function']": report,
|
41
|
+
"CallExpression[callee.name = 'Function']": report
|
44
42
|
};
|
45
43
|
|
46
44
|
}
|
package/lib/rules/no-new.js
CHANGED
@@ -24,12 +24,8 @@ module.exports = {
|
|
24
24
|
create(context) {
|
25
25
|
|
26
26
|
return {
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
if (node.expression.type === "NewExpression") {
|
31
|
-
context.report({ node, message: "Do not use 'new' for side effects." });
|
32
|
-
}
|
27
|
+
"ExpressionStatement > NewExpression"(node) {
|
28
|
+
context.report({ node: node.parent, message: "Do not use 'new' for side effects." });
|
33
29
|
}
|
34
30
|
};
|
35
31
|
|
@@ -20,17 +20,40 @@ module.exports = {
|
|
20
20
|
|
21
21
|
schema: [
|
22
22
|
{
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
oneOf: [
|
24
|
+
{
|
25
|
+
type: "object",
|
26
|
+
properties: {
|
27
|
+
props: {
|
28
|
+
enum: [false]
|
29
|
+
}
|
30
|
+
},
|
31
|
+
additionalProperties: false
|
32
|
+
},
|
33
|
+
{
|
34
|
+
type: "object",
|
35
|
+
properties: {
|
36
|
+
props: {
|
37
|
+
enum: [true]
|
38
|
+
},
|
39
|
+
ignorePropertyModificationsFor: {
|
40
|
+
type: "array",
|
41
|
+
items: {
|
42
|
+
type: "string"
|
43
|
+
},
|
44
|
+
uniqueItems: true
|
45
|
+
}
|
46
|
+
},
|
47
|
+
additionalProperties: false
|
48
|
+
}
|
49
|
+
]
|
28
50
|
}
|
29
51
|
]
|
30
52
|
},
|
31
53
|
|
32
54
|
create(context) {
|
33
55
|
const props = context.options[0] && Boolean(context.options[0].props);
|
56
|
+
const ignoredPropertyAssignmentsFor = context.options[0] && context.options[0].ignorePropertyModificationsFor || [];
|
34
57
|
|
35
58
|
/**
|
36
59
|
* Checks whether or not the reference modifies properties of its variable.
|
@@ -103,7 +126,7 @@ module.exports = {
|
|
103
126
|
) {
|
104
127
|
if (reference.isWrite()) {
|
105
128
|
context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } });
|
106
|
-
} else if (props && isModifyingProp(reference)) {
|
129
|
+
} else if (props && isModifyingProp(reference) && ignoredPropertyAssignmentsFor.indexOf(identifier.name) === -1) {
|
107
130
|
context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } });
|
108
131
|
}
|
109
132
|
}
|
@@ -26,17 +26,9 @@ module.exports = {
|
|
26
26
|
//--------------------------------------------------------------------------
|
27
27
|
|
28
28
|
return {
|
29
|
-
|
30
|
-
|
31
|
-
const callee = node.callee;
|
32
|
-
|
33
|
-
if (callee.type === "MemberExpression" && callee.object.name === "process" &&
|
34
|
-
callee.property.name === "exit"
|
35
|
-
) {
|
36
|
-
context.report({ node, message: "Don't use process.exit(); throw an error instead." });
|
37
|
-
}
|
29
|
+
"CallExpression > MemberExpression.callee[object.name = 'process'][property.name = 'exit']"(node) {
|
30
|
+
context.report({ node: node.parent, message: "Don't use process.exit(); throw an error instead." });
|
38
31
|
}
|
39
|
-
|
40
32
|
};
|
41
33
|
|
42
34
|
}
|
@@ -109,6 +109,7 @@ module.exports = {
|
|
109
109
|
if (matchedObjectProperty) {
|
110
110
|
const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
|
111
111
|
|
112
|
+
// eslint-disable-next-line eslint-plugin/report-message-format
|
112
113
|
context.report({ node, message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}", data: {
|
113
114
|
objectName,
|
114
115
|
propertyName,
|
@@ -117,6 +118,7 @@ module.exports = {
|
|
117
118
|
} else if (globalMatchedProperty) {
|
118
119
|
const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
|
119
120
|
|
121
|
+
// eslint-disable-next-line eslint-plugin/report-message-format
|
120
122
|
context.report({ node, message: "'{{propertyName}}' is restricted from being used.{{message}}", data: {
|
121
123
|
propertyName,
|
122
124
|
message
|
@@ -8,8 +8,6 @@
|
|
8
8
|
// Rule Definition
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const nodeTypes = require("espree").Syntax;
|
12
|
-
|
13
11
|
module.exports = {
|
14
12
|
meta: {
|
15
13
|
docs: {
|
@@ -20,32 +18,18 @@ module.exports = {
|
|
20
18
|
|
21
19
|
schema: {
|
22
20
|
type: "array",
|
23
|
-
items: [
|
24
|
-
{
|
25
|
-
enum: Object.keys(nodeTypes).map(k => nodeTypes[k])
|
26
|
-
}
|
27
|
-
],
|
21
|
+
items: [{ type: "string" }],
|
28
22
|
uniqueItems: true,
|
29
23
|
minItems: 0
|
30
24
|
}
|
31
25
|
},
|
32
26
|
|
33
27
|
create(context) {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
*/
|
40
|
-
function warn(node) {
|
41
|
-
context.report({ node, message: "Using '{{type}}' is not allowed.", data: node });
|
42
|
-
}
|
43
|
-
|
44
|
-
return context.options.reduce((result, nodeType) => {
|
45
|
-
result[nodeType] = warn;
|
46
|
-
|
47
|
-
return result;
|
48
|
-
}, {});
|
28
|
+
return context.options.reduce((result, selector) => Object.assign(result, {
|
29
|
+
[selector](node) {
|
30
|
+
context.report({ node, message: "Using '{{selector}}' is not allowed.", data: { selector } });
|
31
|
+
}
|
32
|
+
}), {});
|
49
33
|
|
50
34
|
}
|
51
35
|
};
|
package/lib/rules/no-sync.js
CHANGED
@@ -26,19 +26,14 @@ module.exports = {
|
|
26
26
|
|
27
27
|
return {
|
28
28
|
|
29
|
-
MemberExpression(node) {
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
data: {
|
38
|
-
propertyName
|
39
|
-
}
|
40
|
-
});
|
41
|
-
}
|
29
|
+
"MemberExpression[property.name=/.*Sync$/]"(node) {
|
30
|
+
context.report({
|
31
|
+
node,
|
32
|
+
message: "Unexpected sync method: '{{propertyName}}'.",
|
33
|
+
data: {
|
34
|
+
propertyName: node.property.name
|
35
|
+
}
|
36
|
+
});
|
42
37
|
}
|
43
38
|
};
|
44
39
|
|
@@ -25,6 +25,9 @@ module.exports = {
|
|
25
25
|
},
|
26
26
|
allowTernary: {
|
27
27
|
type: "boolean"
|
28
|
+
},
|
29
|
+
allowTaggedTemplates: {
|
30
|
+
type: "boolean"
|
28
31
|
}
|
29
32
|
},
|
30
33
|
additionalProperties: false
|
@@ -35,7 +38,8 @@ module.exports = {
|
|
35
38
|
create(context) {
|
36
39
|
const config = context.options[0] || {},
|
37
40
|
allowShortCircuit = config.allowShortCircuit || false,
|
38
|
-
allowTernary = config.allowTernary || false
|
41
|
+
allowTernary = config.allowTernary || false,
|
42
|
+
allowTaggedTemplates = config.allowTaggedTemplates || false;
|
39
43
|
|
40
44
|
/**
|
41
45
|
* @param {ASTNode} node - any node
|
@@ -95,12 +99,17 @@ module.exports = {
|
|
95
99
|
return isValidExpression(node.consequent) && isValidExpression(node.alternate);
|
96
100
|
}
|
97
101
|
}
|
102
|
+
|
98
103
|
if (allowShortCircuit) {
|
99
104
|
if (node.type === "LogicalExpression") {
|
100
105
|
return isValidExpression(node.right);
|
101
106
|
}
|
102
107
|
}
|
103
108
|
|
109
|
+
if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") {
|
110
|
+
return true;
|
111
|
+
}
|
112
|
+
|
104
113
|
return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) ||
|
105
114
|
(node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
|
106
115
|
}
|
@@ -66,6 +66,7 @@ module.exports = {
|
|
66
66
|
|
67
67
|
const DEFINED_MESSAGE = "'{{name}}' is defined but never used.";
|
68
68
|
const ASSIGNED_MESSAGE = "'{{name}}' is assigned a value but never used.";
|
69
|
+
const REST_PROPERTY_TYPE = /^(?:Experimental)?RestProperty$/;
|
69
70
|
|
70
71
|
const config = {
|
71
72
|
vars: "all",
|
@@ -139,17 +140,16 @@ module.exports = {
|
|
139
140
|
*/
|
140
141
|
function hasRestSpreadSibling(variable) {
|
141
142
|
if (config.ignoreRestSiblings) {
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
));
|
143
|
+
return variable.defs.some(def => {
|
144
|
+
const propertyNode = def.name.parent;
|
145
|
+
const patternNode = propertyNode.parent;
|
146
|
+
|
147
|
+
return (
|
148
|
+
propertyNode.type === "Property" &&
|
149
|
+
patternNode.type === "ObjectPattern" &&
|
150
|
+
REST_PROPERTY_TYPE.test(patternNode.properties[patternNode.properties.length - 1].type)
|
151
|
+
);
|
152
|
+
});
|
153
153
|
}
|
154
154
|
|
155
155
|
return false;
|
@@ -568,7 +568,7 @@ module.exports = {
|
|
568
568
|
function getLocation(variable) {
|
569
569
|
const comment = variable.eslintExplicitGlobalComment;
|
570
570
|
|
571
|
-
return
|
571
|
+
return sourceCode.getLocFromIndex(comment.range[0] + 2 + getColumnInComment(variable, comment));
|
572
572
|
}
|
573
573
|
|
574
574
|
//--------------------------------------------------------------------------
|
@@ -166,7 +166,7 @@ module.exports = {
|
|
166
166
|
const options = parseOptions(context.options[0]);
|
167
167
|
|
168
168
|
/**
|
169
|
-
* Determines whether a given use-before-define case should be
|
169
|
+
* Determines whether a given use-before-define case should be reported according to the options.
|
170
170
|
* @param {escope.Variable} variable The variable that gets used before being defined
|
171
171
|
* @param {escope.Reference} reference The reference to the variable
|
172
172
|
* @returns {boolean} `true` if the usage should be reported
|
@@ -94,7 +94,7 @@ module.exports = {
|
|
94
94
|
function report(node, startOffset, character) {
|
95
95
|
context.report({
|
96
96
|
node,
|
97
|
-
loc:
|
97
|
+
loc: sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(node.loc.start) + startOffset),
|
98
98
|
message: "Unnecessary escape character: \\{{character}}.",
|
99
99
|
data: { character }
|
100
100
|
});
|
@@ -147,7 +147,13 @@ module.exports = {
|
|
147
147
|
function check(node) {
|
148
148
|
const isTemplateElement = node.type === "TemplateElement";
|
149
149
|
|
150
|
-
if (
|
150
|
+
if (
|
151
|
+
isTemplateElement &&
|
152
|
+
node.parent &&
|
153
|
+
node.parent.parent &&
|
154
|
+
node.parent.parent.type === "TaggedTemplateExpression" &&
|
155
|
+
node.parent === node.parent.parent.quasi
|
156
|
+
) {
|
151
157
|
|
152
158
|
// Don't report tagged template literals, because the backslash character is accessible to the tag function.
|
153
159
|
return;
|
@@ -8,7 +8,8 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const astUtils = require("../ast-utils")
|
11
|
+
const astUtils = require("../ast-utils"),
|
12
|
+
FixTracker = require("../util/fix-tracker");
|
12
13
|
|
13
14
|
//------------------------------------------------------------------------------
|
14
15
|
// Helpers
|
@@ -219,7 +220,17 @@ module.exports = {
|
|
219
220
|
loc: node.loc,
|
220
221
|
message: "Unnecessary return statement.",
|
221
222
|
fix(fixer) {
|
222
|
-
|
223
|
+
if (isRemovable(node)) {
|
224
|
+
|
225
|
+
// Extend the replacement range to include the
|
226
|
+
// entire function to avoid conflicting with
|
227
|
+
// no-else-return.
|
228
|
+
// https://github.com/eslint/eslint/issues/8026
|
229
|
+
return new FixTracker(fixer, context.getSourceCode())
|
230
|
+
.retainEnclosingFunction(node)
|
231
|
+
.remove(node);
|
232
|
+
}
|
233
|
+
return null;
|
223
234
|
}
|
224
235
|
});
|
225
236
|
}
|