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
@@ -60,6 +60,7 @@ module.exports = {
|
|
60
60
|
create(context) {
|
61
61
|
const sourceCode = context.getSourceCode();
|
62
62
|
|
63
|
+
const tokensToIgnore = new WeakSet();
|
63
64
|
const isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode);
|
64
65
|
const precedence = astUtils.getPrecedence;
|
65
66
|
const ALL_NODES = context.options[0] !== "functions";
|
@@ -67,6 +68,8 @@ module.exports = {
|
|
67
68
|
const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false;
|
68
69
|
const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false;
|
69
70
|
const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX;
|
71
|
+
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
|
72
|
+
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
|
70
73
|
|
71
74
|
/**
|
72
75
|
* Determines if this rule should be enforced for a node given the current configuration.
|
@@ -114,8 +117,8 @@ module.exports = {
|
|
114
117
|
nextToken = sourceCode.getTokenAfter(node, 1);
|
115
118
|
|
116
119
|
return isParenthesised(node) && previousToken && nextToken &&
|
117
|
-
|
118
|
-
nextToken
|
120
|
+
astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
|
121
|
+
astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
|
119
122
|
}
|
120
123
|
|
121
124
|
/**
|
@@ -177,7 +180,7 @@ module.exports = {
|
|
177
180
|
const lastToken = sourceCode.getLastToken(newExpression);
|
178
181
|
const penultimateToken = sourceCode.getTokenBefore(lastToken);
|
179
182
|
|
180
|
-
return newExpression.arguments.length > 0 ||
|
183
|
+
return newExpression.arguments.length > 0 || astUtils.isOpeningParenToken(penultimateToken) && astUtils.isClosingParenToken(lastToken);
|
181
184
|
}
|
182
185
|
|
183
186
|
/**
|
@@ -236,69 +239,6 @@ module.exports = {
|
|
236
239
|
return hasDoubleExcessParens(node);
|
237
240
|
}
|
238
241
|
|
239
|
-
/**
|
240
|
-
* Checks whether or not a given node is located at the head of ExpressionStatement.
|
241
|
-
* @param {ASTNode} node - A node to check.
|
242
|
-
* @returns {boolean} `true` if the node is located at the head of ExpressionStatement.
|
243
|
-
*/
|
244
|
-
function isHeadOfExpressionStatement(node) {
|
245
|
-
let parent = node.parent;
|
246
|
-
|
247
|
-
while (parent) {
|
248
|
-
switch (parent.type) {
|
249
|
-
case "SequenceExpression":
|
250
|
-
if (parent.expressions[0] !== node || isParenthesised(node)) {
|
251
|
-
return false;
|
252
|
-
}
|
253
|
-
break;
|
254
|
-
|
255
|
-
case "UnaryExpression":
|
256
|
-
case "UpdateExpression":
|
257
|
-
if (parent.prefix || isParenthesised(node)) {
|
258
|
-
return false;
|
259
|
-
}
|
260
|
-
break;
|
261
|
-
|
262
|
-
case "BinaryExpression":
|
263
|
-
case "LogicalExpression":
|
264
|
-
if (parent.left !== node || isParenthesised(node)) {
|
265
|
-
return false;
|
266
|
-
}
|
267
|
-
break;
|
268
|
-
|
269
|
-
case "ConditionalExpression":
|
270
|
-
if (parent.test !== node || isParenthesised(node)) {
|
271
|
-
return false;
|
272
|
-
}
|
273
|
-
break;
|
274
|
-
|
275
|
-
case "CallExpression":
|
276
|
-
if (parent.callee !== node || isParenthesised(node)) {
|
277
|
-
return false;
|
278
|
-
}
|
279
|
-
break;
|
280
|
-
|
281
|
-
case "MemberExpression":
|
282
|
-
if (parent.object !== node || isParenthesised(node)) {
|
283
|
-
return false;
|
284
|
-
}
|
285
|
-
break;
|
286
|
-
|
287
|
-
case "ExpressionStatement":
|
288
|
-
return true;
|
289
|
-
|
290
|
-
default:
|
291
|
-
return false;
|
292
|
-
}
|
293
|
-
|
294
|
-
node = parent;
|
295
|
-
parent = parent.parent;
|
296
|
-
}
|
297
|
-
|
298
|
-
/* istanbul ignore next */
|
299
|
-
throw new Error("unreachable");
|
300
|
-
}
|
301
|
-
|
302
242
|
/**
|
303
243
|
* Determines whether a node should be preceded by an additional space when removing parens
|
304
244
|
* @param {ASTNode} node node to evaluate; must be surrounded by parentheses
|
@@ -316,7 +256,7 @@ module.exports = {
|
|
316
256
|
}
|
317
257
|
|
318
258
|
// If the parens are preceded by a keyword (e.g. `typeof(0)`), a space should be inserted (`typeof 0`)
|
319
|
-
const
|
259
|
+
const precededByIdentiferPart = esUtils.code.isIdentifierPartES6(tokenBeforeLeftParen.value.slice(-1).charCodeAt(0));
|
320
260
|
|
321
261
|
// However, a space should not be inserted unless the first character of the token is an identifier part
|
322
262
|
// e.g. `typeof([])` should be fixed to `typeof[]`
|
@@ -329,7 +269,7 @@ module.exports = {
|
|
329
269
|
const startsWithUnaryPlus = firstToken.type === "Punctuator" && firstToken.value === "+";
|
330
270
|
const startsWithUnaryMinus = firstToken.type === "Punctuator" && firstToken.value === "-";
|
331
271
|
|
332
|
-
return (
|
272
|
+
return (precededByIdentiferPart && startsWithIdentifierPart) ||
|
333
273
|
(precededByUnaryPlus && startsWithUnaryPlus) ||
|
334
274
|
(precededByUnaryMinus && startsWithUnaryMinus);
|
335
275
|
}
|
@@ -344,6 +284,10 @@ module.exports = {
|
|
344
284
|
const leftParenToken = sourceCode.getTokenBefore(node);
|
345
285
|
const rightParenToken = sourceCode.getTokenAfter(node);
|
346
286
|
|
287
|
+
if (tokensToIgnore.has(sourceCode.getFirstToken(node)) && !isParenthesisedTwice(node)) {
|
288
|
+
return;
|
289
|
+
}
|
290
|
+
|
347
291
|
context.report({
|
348
292
|
node,
|
349
293
|
loc: leftParenToken.loc.start,
|
@@ -365,7 +309,7 @@ module.exports = {
|
|
365
309
|
* @returns {void}
|
366
310
|
* @private
|
367
311
|
*/
|
368
|
-
function
|
312
|
+
function checkUnaryUpdate(node) {
|
369
313
|
if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") {
|
370
314
|
return;
|
371
315
|
}
|
@@ -381,7 +325,7 @@ module.exports = {
|
|
381
325
|
* @returns {void}
|
382
326
|
* @private
|
383
327
|
*/
|
384
|
-
function
|
328
|
+
function checkCallNew(node) {
|
385
329
|
if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !(
|
386
330
|
node.type === "CallExpression" &&
|
387
331
|
(node.callee.type === "FunctionExpression" ||
|
@@ -393,12 +337,12 @@ module.exports = {
|
|
393
337
|
report(node.callee);
|
394
338
|
}
|
395
339
|
if (node.arguments.length === 1) {
|
396
|
-
if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >=
|
340
|
+
if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
397
341
|
report(node.arguments[0]);
|
398
342
|
}
|
399
343
|
} else {
|
400
344
|
[].forEach.call(node.arguments, arg => {
|
401
|
-
if (hasExcessParens(arg) && precedence(arg) >=
|
345
|
+
if (hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
402
346
|
report(arg);
|
403
347
|
}
|
404
348
|
});
|
@@ -411,7 +355,7 @@ module.exports = {
|
|
411
355
|
* @returns {void}
|
412
356
|
* @private
|
413
357
|
*/
|
414
|
-
function
|
358
|
+
function checkBinaryLogical(node) {
|
415
359
|
const prec = precedence(node);
|
416
360
|
const leftPrecedence = precedence(node.left);
|
417
361
|
const rightPrecedence = precedence(node.right);
|
@@ -428,10 +372,74 @@ module.exports = {
|
|
428
372
|
}
|
429
373
|
}
|
430
374
|
|
375
|
+
/**
|
376
|
+
* Check the parentheses around the super class of the given class definition.
|
377
|
+
* @param {ASTNode} node The node of class declarations to check.
|
378
|
+
* @returns {void}
|
379
|
+
*/
|
380
|
+
function checkClass(node) {
|
381
|
+
if (!node.superClass) {
|
382
|
+
return;
|
383
|
+
}
|
384
|
+
|
385
|
+
// If `node.superClass` is a LeftHandSideExpression, parentheses are extra.
|
386
|
+
// Otherwise, parentheses are needed.
|
387
|
+
const hasExtraParens = precedence(node.superClass) > PRECEDENCE_OF_UPDATE_EXPR
|
388
|
+
? hasExcessParens(node.superClass)
|
389
|
+
: hasDoubleExcessParens(node.superClass);
|
390
|
+
|
391
|
+
if (hasExtraParens) {
|
392
|
+
report(node.superClass);
|
393
|
+
}
|
394
|
+
}
|
395
|
+
|
396
|
+
/**
|
397
|
+
* Check the parentheses around the argument of the given spread operator.
|
398
|
+
* @param {ASTNode} node The node of spread elements/properties to check.
|
399
|
+
* @returns {void}
|
400
|
+
*/
|
401
|
+
function checkSpreadOperator(node) {
|
402
|
+
const hasExtraParens = precedence(node.argument) >= PRECEDENCE_OF_ASSIGNMENT_EXPR
|
403
|
+
? hasExcessParens(node.argument)
|
404
|
+
: hasDoubleExcessParens(node.argument);
|
405
|
+
|
406
|
+
if (hasExtraParens) {
|
407
|
+
report(node.argument);
|
408
|
+
}
|
409
|
+
}
|
410
|
+
|
411
|
+
/**
|
412
|
+
* Checks the parentheses for an ExpressionStatement or ExportDefaultDeclaration
|
413
|
+
* @param {ASTNode} node The ExpressionStatement.expression or ExportDefaultDeclaration.declaration node
|
414
|
+
* @returns {void}
|
415
|
+
*/
|
416
|
+
function checkExpressionOrExportStatement(node) {
|
417
|
+
const firstToken = isParenthesised(node) ? sourceCode.getTokenBefore(node) : sourceCode.getFirstToken(node);
|
418
|
+
const secondToken = sourceCode.getTokenAfter(firstToken, astUtils.isNotOpeningParenToken);
|
419
|
+
|
420
|
+
if (
|
421
|
+
astUtils.isOpeningParenToken(firstToken) &&
|
422
|
+
(
|
423
|
+
astUtils.isOpeningBraceToken(secondToken) ||
|
424
|
+
secondToken.type === "Keyword" && (
|
425
|
+
secondToken.value === "function" ||
|
426
|
+
secondToken.value === "class" ||
|
427
|
+
secondToken.value === "let" && astUtils.isOpeningBracketToken(sourceCode.getTokenAfter(secondToken))
|
428
|
+
)
|
429
|
+
)
|
430
|
+
) {
|
431
|
+
tokensToIgnore.add(secondToken);
|
432
|
+
}
|
433
|
+
|
434
|
+
if (hasExcessParens(node)) {
|
435
|
+
report(node);
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
431
439
|
return {
|
432
440
|
ArrayExpression(node) {
|
433
441
|
[].forEach.call(node.elements, e => {
|
434
|
-
if (e && hasExcessParens(e) && precedence(e) >=
|
442
|
+
if (e && hasExcessParens(e) && precedence(e) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
435
443
|
report(e);
|
436
444
|
}
|
437
445
|
});
|
@@ -443,13 +451,13 @@ module.exports = {
|
|
443
451
|
}
|
444
452
|
|
445
453
|
if (node.body.type !== "BlockStatement") {
|
446
|
-
|
447
|
-
|
448
|
-
return;
|
449
|
-
}
|
454
|
+
const firstBodyToken = sourceCode.getFirstToken(node.body, astUtils.isNotOpeningParenToken);
|
455
|
+
const tokenBeforeFirst = sourceCode.getTokenBefore(firstBodyToken);
|
450
456
|
|
451
|
-
|
452
|
-
|
457
|
+
if (astUtils.isOpeningParenToken(tokenBeforeFirst) && astUtils.isOpeningBraceToken(firstBodyToken)) {
|
458
|
+
tokensToIgnore.add(firstBodyToken);
|
459
|
+
}
|
460
|
+
if (hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
453
461
|
report(node.body);
|
454
462
|
}
|
455
463
|
}
|
@@ -465,8 +473,8 @@ module.exports = {
|
|
465
473
|
}
|
466
474
|
},
|
467
475
|
|
468
|
-
BinaryExpression:
|
469
|
-
CallExpression:
|
476
|
+
BinaryExpression: checkBinaryLogical,
|
477
|
+
CallExpression: checkCallNew,
|
470
478
|
|
471
479
|
ConditionalExpression(node) {
|
472
480
|
if (isReturnAssignException(node)) {
|
@@ -477,11 +485,11 @@ module.exports = {
|
|
477
485
|
report(node.test);
|
478
486
|
}
|
479
487
|
|
480
|
-
if (hasExcessParens(node.consequent) && precedence(node.consequent) >=
|
488
|
+
if (hasExcessParens(node.consequent) && precedence(node.consequent) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
481
489
|
report(node.consequent);
|
482
490
|
}
|
483
491
|
|
484
|
-
if (hasExcessParens(node.alternate) && precedence(node.alternate) >=
|
492
|
+
if (hasExcessParens(node.alternate) && precedence(node.alternate) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
485
493
|
report(node.alternate);
|
486
494
|
}
|
487
495
|
},
|
@@ -492,27 +500,8 @@ module.exports = {
|
|
492
500
|
}
|
493
501
|
},
|
494
502
|
|
495
|
-
|
496
|
-
|
497
|
-
const firstTokens = sourceCode.getFirstTokens(node.expression, 2);
|
498
|
-
const firstToken = firstTokens[0];
|
499
|
-
const secondToken = firstTokens[1];
|
500
|
-
|
501
|
-
if (
|
502
|
-
!firstToken ||
|
503
|
-
firstToken.value !== "{" &&
|
504
|
-
firstToken.value !== "function" &&
|
505
|
-
firstToken.value !== "class" &&
|
506
|
-
(
|
507
|
-
firstToken.value !== "let" ||
|
508
|
-
!secondToken ||
|
509
|
-
secondToken.value !== "["
|
510
|
-
)
|
511
|
-
) {
|
512
|
-
report(node.expression);
|
513
|
-
}
|
514
|
-
}
|
515
|
-
},
|
503
|
+
ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration),
|
504
|
+
ExpressionStatement: node => checkExpressionOrExportStatement(node.expression),
|
516
505
|
|
517
506
|
ForInStatement(node) {
|
518
507
|
if (hasExcessParens(node.right)) {
|
@@ -546,7 +535,7 @@ module.exports = {
|
|
546
535
|
}
|
547
536
|
},
|
548
537
|
|
549
|
-
LogicalExpression:
|
538
|
+
LogicalExpression: checkBinaryLogical,
|
550
539
|
|
551
540
|
MemberExpression(node) {
|
552
541
|
if (
|
@@ -555,18 +544,11 @@ module.exports = {
|
|
555
544
|
(
|
556
545
|
node.computed ||
|
557
546
|
!(
|
558
|
-
(node.object
|
559
|
-
typeof node.object.value === "number" &&
|
560
|
-
astUtils.isDecimalInteger(node.object)) ||
|
547
|
+
astUtils.isDecimalInteger(node.object) ||
|
561
548
|
|
562
549
|
// RegExp literal is allowed to have parens (#1589)
|
563
550
|
(node.object.type === "Literal" && node.object.regex)
|
564
551
|
)
|
565
|
-
) &&
|
566
|
-
!(
|
567
|
-
(node.object.type === "FunctionExpression" || node.object.type === "ClassExpression") &&
|
568
|
-
isHeadOfExpressionStatement(node) &&
|
569
|
-
!hasDoubleExcessParens(node.object)
|
570
552
|
)
|
571
553
|
) {
|
572
554
|
report(node.object);
|
@@ -576,13 +558,13 @@ module.exports = {
|
|
576
558
|
}
|
577
559
|
},
|
578
560
|
|
579
|
-
NewExpression:
|
561
|
+
NewExpression: checkCallNew,
|
580
562
|
|
581
563
|
ObjectExpression(node) {
|
582
564
|
[].forEach.call(node.properties, e => {
|
583
565
|
const v = e.value;
|
584
566
|
|
585
|
-
if (v && hasExcessParens(v) && precedence(v) >=
|
567
|
+
if (v && hasExcessParens(v) && precedence(v) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
586
568
|
report(v);
|
587
569
|
}
|
588
570
|
});
|
@@ -632,13 +614,13 @@ module.exports = {
|
|
632
614
|
}
|
633
615
|
},
|
634
616
|
|
635
|
-
UnaryExpression:
|
636
|
-
UpdateExpression:
|
637
|
-
AwaitExpression:
|
617
|
+
UnaryExpression: checkUnaryUpdate,
|
618
|
+
UpdateExpression: checkUnaryUpdate,
|
619
|
+
AwaitExpression: checkUnaryUpdate,
|
638
620
|
|
639
621
|
VariableDeclarator(node) {
|
640
622
|
if (node.init && hasExcessParens(node.init) &&
|
641
|
-
precedence(node.init) >=
|
623
|
+
precedence(node.init) >= PRECEDENCE_OF_ASSIGNMENT_EXPR &&
|
642
624
|
|
643
625
|
// RegExp literal is allowed to have parens (#1589)
|
644
626
|
!(node.init.type === "Literal" && node.init.regex)) {
|
@@ -668,7 +650,14 @@ module.exports = {
|
|
668
650
|
report(node.argument);
|
669
651
|
}
|
670
652
|
}
|
671
|
-
}
|
653
|
+
},
|
654
|
+
|
655
|
+
ClassDeclaration: checkClass,
|
656
|
+
ClassExpression: checkClass,
|
657
|
+
|
658
|
+
SpreadElement: checkSpreadOperator,
|
659
|
+
SpreadProperty: checkSpreadOperator,
|
660
|
+
ExperimentalSpreadProperty: checkSpreadOperator
|
672
661
|
};
|
673
662
|
|
674
663
|
}
|
@@ -5,6 +5,13 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const FixTracker = require("../util/fix-tracker");
|
13
|
+
const astUtils = require("../ast-utils");
|
14
|
+
|
8
15
|
//------------------------------------------------------------------------------
|
9
16
|
// Rule Definition
|
10
17
|
//------------------------------------------------------------------------------
|
@@ -34,7 +41,13 @@ module.exports = {
|
|
34
41
|
node: nodeOrToken,
|
35
42
|
message: "Unnecessary semicolon.",
|
36
43
|
fix(fixer) {
|
37
|
-
|
44
|
+
|
45
|
+
// Expand the replacement range to include the surrounding
|
46
|
+
// tokens to avoid conflicting with semi.
|
47
|
+
// https://github.com/eslint/eslint/issues/7928
|
48
|
+
return new FixTracker(fixer, context.getSourceCode())
|
49
|
+
.retainSurroundingTokens(nodeOrToken)
|
50
|
+
.remove(nodeOrToken);
|
38
51
|
}
|
39
52
|
});
|
40
53
|
}
|
@@ -48,10 +61,10 @@ module.exports = {
|
|
48
61
|
*/
|
49
62
|
function checkForPartOfClassBody(firstToken) {
|
50
63
|
for (let token = firstToken;
|
51
|
-
token.type === "Punctuator" && token
|
64
|
+
token.type === "Punctuator" && !astUtils.isClosingBraceToken(token);
|
52
65
|
token = sourceCode.getTokenAfter(token)
|
53
66
|
) {
|
54
|
-
if (token
|
67
|
+
if (astUtils.isSemicolonToken(token)) {
|
55
68
|
report(token);
|
56
69
|
}
|
57
70
|
}
|
@@ -6,6 +6,7 @@
|
|
6
6
|
"use strict";
|
7
7
|
|
8
8
|
const astUtils = require("../ast-utils");
|
9
|
+
const esUtils = require("esutils");
|
9
10
|
|
10
11
|
//------------------------------------------------------------------------------
|
11
12
|
// Helpers
|
@@ -197,19 +198,31 @@ module.exports = {
|
|
197
198
|
*/
|
198
199
|
function report(node, recommendation, shouldFix) {
|
199
200
|
shouldFix = typeof shouldFix === "undefined" ? true : shouldFix;
|
200
|
-
|
201
|
+
|
202
|
+
context.report({
|
201
203
|
node,
|
202
204
|
message: "use `{{recommendation}}` instead.",
|
203
205
|
data: {
|
204
206
|
recommendation
|
207
|
+
},
|
208
|
+
fix(fixer) {
|
209
|
+
if (!shouldFix) {
|
210
|
+
return null;
|
211
|
+
}
|
212
|
+
|
213
|
+
const tokenBefore = sourceCode.getTokenBefore(node);
|
214
|
+
|
215
|
+
if (
|
216
|
+
tokenBefore &&
|
217
|
+
tokenBefore.range[1] === node.range[0] &&
|
218
|
+
esUtils.code.isIdentifierPartES6(tokenBefore.value.slice(-1).charCodeAt(0)) &&
|
219
|
+
esUtils.code.isIdentifierPartES6(recommendation.charCodeAt(0))
|
220
|
+
) {
|
221
|
+
return fixer.replaceText(node, ` ${recommendation}`);
|
222
|
+
}
|
223
|
+
return fixer.replaceText(node, recommendation);
|
205
224
|
}
|
206
|
-
};
|
207
|
-
|
208
|
-
if (shouldFix) {
|
209
|
-
reportObj.fix = fixer => fixer.replaceText(node, recommendation);
|
210
|
-
}
|
211
|
-
|
212
|
-
context.report(reportObj);
|
225
|
+
});
|
213
226
|
}
|
214
227
|
|
215
228
|
return {
|
@@ -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.
|
@@ -73,8 +96,15 @@ module.exports = {
|
|
73
96
|
}
|
74
97
|
break;
|
75
98
|
|
76
|
-
|
99
|
+
// EXCLUDES: e.g. ({ [foo]: a }) = bar;
|
100
|
+
case "Property":
|
101
|
+
if (parent.key === node) {
|
102
|
+
return false;
|
103
|
+
}
|
104
|
+
|
77
105
|
break;
|
106
|
+
|
107
|
+
// no default
|
78
108
|
}
|
79
109
|
|
80
110
|
node = parent;
|
@@ -103,7 +133,7 @@ module.exports = {
|
|
103
133
|
) {
|
104
134
|
if (reference.isWrite()) {
|
105
135
|
context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } });
|
106
|
-
} else if (props && isModifyingProp(reference)) {
|
136
|
+
} else if (props && isModifyingProp(reference) && ignoredPropertyAssignmentsFor.indexOf(identifier.name) === -1) {
|
107
137
|
context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } });
|
108
138
|
}
|
109
139
|
}
|