eslint 3.18.0 → 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.
Files changed (38) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +1 -0
  3. package/lib/config/config-rule.js +14 -10
  4. package/lib/config/plugins.js +19 -8
  5. package/lib/eslint.js +6 -5
  6. package/lib/formatters/codeframe.js +4 -9
  7. package/lib/rules/arrow-body-style.js +2 -2
  8. package/lib/rules/arrow-parens.js +9 -3
  9. package/lib/rules/comma-dangle.js +3 -2
  10. package/lib/rules/comma-spacing.js +4 -14
  11. package/lib/rules/comma-style.js +8 -14
  12. package/lib/rules/curly.js +2 -2
  13. package/lib/rules/dot-notation.js +12 -6
  14. package/lib/rules/lines-around-directive.js +1 -1
  15. package/lib/rules/new-parens.js +7 -21
  16. package/lib/rules/no-cond-assign.js +4 -17
  17. package/lib/rules/no-else-return.js +6 -3
  18. package/lib/rules/no-extra-parens.js +47 -103
  19. package/lib/rules/no-extra-semi.js +3 -2
  20. package/lib/rules/no-implicit-coercion.js +21 -8
  21. package/lib/rules/no-native-reassign.js +1 -1
  22. package/lib/rules/no-negated-in-lhs.js +1 -1
  23. package/lib/rules/no-param-reassign.js +8 -1
  24. package/lib/rules/no-restricted-syntax.js +33 -6
  25. package/lib/rules/no-sequences.js +2 -2
  26. package/lib/rules/no-unsafe-negation.js +1 -1
  27. package/lib/rules/no-useless-computed-key.js +12 -1
  28. package/lib/rules/object-curly-spacing.js +2 -2
  29. package/lib/rules/object-shorthand.js +8 -2
  30. package/lib/rules/operator-assignment.js +20 -3
  31. package/lib/rules/prefer-const.js +1 -1
  32. package/lib/rules/quotes.js +1 -0
  33. package/lib/rules/semi-spacing.js +2 -15
  34. package/lib/rules/semi.js +4 -12
  35. package/lib/rules/space-before-function-paren.js +53 -77
  36. package/lib/rules/space-in-parens.js +4 -8
  37. package/lib/util/glob-util.js +1 -1
  38. package/package.json +29 -29
@@ -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";
@@ -116,8 +117,8 @@ module.exports = {
116
117
  nextToken = sourceCode.getTokenAfter(node, 1);
117
118
 
118
119
  return isParenthesised(node) && previousToken && nextToken &&
119
- previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
120
- nextToken.value === ")" && nextToken.range[0] >= node.range[1];
120
+ astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
121
+ astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
121
122
  }
122
123
 
123
124
  /**
@@ -179,7 +180,7 @@ module.exports = {
179
180
  const lastToken = sourceCode.getLastToken(newExpression);
180
181
  const penultimateToken = sourceCode.getTokenBefore(lastToken);
181
182
 
182
- return newExpression.arguments.length > 0 || penultimateToken.value === "(" && lastToken.value === ")";
183
+ return newExpression.arguments.length > 0 || astUtils.isOpeningParenToken(penultimateToken) && astUtils.isClosingParenToken(lastToken);
183
184
  }
184
185
 
185
186
  /**
@@ -238,69 +239,6 @@ module.exports = {
238
239
  return hasDoubleExcessParens(node);
239
240
  }
240
241
 
241
- /**
242
- * Checks whether or not a given node is located at the head of ExpressionStatement.
243
- * @param {ASTNode} node - A node to check.
244
- * @returns {boolean} `true` if the node is located at the head of ExpressionStatement.
245
- */
246
- function isHeadOfExpressionStatement(node) {
247
- let parent = node.parent;
248
-
249
- while (parent) {
250
- switch (parent.type) {
251
- case "SequenceExpression":
252
- if (parent.expressions[0] !== node || isParenthesised(node)) {
253
- return false;
254
- }
255
- break;
256
-
257
- case "UnaryExpression":
258
- case "UpdateExpression":
259
- if (parent.prefix || isParenthesised(node)) {
260
- return false;
261
- }
262
- break;
263
-
264
- case "BinaryExpression":
265
- case "LogicalExpression":
266
- if (parent.left !== node || isParenthesised(node)) {
267
- return false;
268
- }
269
- break;
270
-
271
- case "ConditionalExpression":
272
- if (parent.test !== node || isParenthesised(node)) {
273
- return false;
274
- }
275
- break;
276
-
277
- case "CallExpression":
278
- if (parent.callee !== node || isParenthesised(node)) {
279
- return false;
280
- }
281
- break;
282
-
283
- case "MemberExpression":
284
- if (parent.object !== node || isParenthesised(node)) {
285
- return false;
286
- }
287
- break;
288
-
289
- case "ExpressionStatement":
290
- return true;
291
-
292
- default:
293
- return false;
294
- }
295
-
296
- node = parent;
297
- parent = parent.parent;
298
- }
299
-
300
- /* istanbul ignore next */
301
- throw new Error("unreachable");
302
- }
303
-
304
242
  /**
305
243
  * Determines whether a node should be preceded by an additional space when removing parens
306
244
  * @param {ASTNode} node node to evaluate; must be surrounded by parentheses
@@ -318,7 +256,7 @@ module.exports = {
318
256
  }
319
257
 
320
258
  // If the parens are preceded by a keyword (e.g. `typeof(0)`), a space should be inserted (`typeof 0`)
321
- const precededByKeyword = tokenBeforeLeftParen.type === "Keyword";
259
+ const precededByIdentiferPart = esUtils.code.isIdentifierPartES6(tokenBeforeLeftParen.value.slice(-1).charCodeAt(0));
322
260
 
323
261
  // However, a space should not be inserted unless the first character of the token is an identifier part
324
262
  // e.g. `typeof([])` should be fixed to `typeof[]`
@@ -331,7 +269,7 @@ module.exports = {
331
269
  const startsWithUnaryPlus = firstToken.type === "Punctuator" && firstToken.value === "+";
332
270
  const startsWithUnaryMinus = firstToken.type === "Punctuator" && firstToken.value === "-";
333
271
 
334
- return (precededByKeyword && startsWithIdentifierPart) ||
272
+ return (precededByIdentiferPart && startsWithIdentifierPart) ||
335
273
  (precededByUnaryPlus && startsWithUnaryPlus) ||
336
274
  (precededByUnaryMinus && startsWithUnaryMinus);
337
275
  }
@@ -346,6 +284,10 @@ module.exports = {
346
284
  const leftParenToken = sourceCode.getTokenBefore(node);
347
285
  const rightParenToken = sourceCode.getTokenAfter(node);
348
286
 
287
+ if (tokensToIgnore.has(sourceCode.getFirstToken(node)) && !isParenthesisedTwice(node)) {
288
+ return;
289
+ }
290
+
349
291
  context.report({
350
292
  node,
351
293
  loc: leftParenToken.loc.start,
@@ -466,6 +408,34 @@ module.exports = {
466
408
  }
467
409
  }
468
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
+
469
439
  return {
470
440
  ArrayExpression(node) {
471
441
  [].forEach.call(node.elements, e => {
@@ -481,13 +451,13 @@ module.exports = {
481
451
  }
482
452
 
483
453
  if (node.body.type !== "BlockStatement") {
484
- if (sourceCode.getFirstToken(node.body).value !== "{" && hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
485
- report(node.body);
486
- return;
487
- }
454
+ const firstBodyToken = sourceCode.getFirstToken(node.body, astUtils.isNotOpeningParenToken);
455
+ const tokenBeforeFirst = sourceCode.getTokenBefore(firstBodyToken);
488
456
 
489
- // Object literals *must* be parenthesised
490
- if (node.body.type === "ObjectExpression" && hasDoubleExcessParens(node.body)) {
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) {
491
461
  report(node.body);
492
462
  }
493
463
  }
@@ -530,27 +500,8 @@ module.exports = {
530
500
  }
531
501
  },
532
502
 
533
- ExpressionStatement(node) {
534
- if (hasExcessParens(node.expression)) {
535
- const firstTokens = sourceCode.getFirstTokens(node.expression, 2);
536
- const firstToken = firstTokens[0];
537
- const secondToken = firstTokens[1];
538
-
539
- if (
540
- !firstToken ||
541
- firstToken.value !== "{" &&
542
- firstToken.value !== "function" &&
543
- firstToken.value !== "class" &&
544
- (
545
- firstToken.value !== "let" ||
546
- !secondToken ||
547
- secondToken.value !== "["
548
- )
549
- ) {
550
- report(node.expression);
551
- }
552
- }
553
- },
503
+ ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration),
504
+ ExpressionStatement: node => checkExpressionOrExportStatement(node.expression),
554
505
 
555
506
  ForInStatement(node) {
556
507
  if (hasExcessParens(node.right)) {
@@ -593,18 +544,11 @@ module.exports = {
593
544
  (
594
545
  node.computed ||
595
546
  !(
596
- (node.object.type === "Literal" &&
597
- typeof node.object.value === "number" &&
598
- astUtils.isDecimalInteger(node.object)) ||
547
+ astUtils.isDecimalInteger(node.object) ||
599
548
 
600
549
  // RegExp literal is allowed to have parens (#1589)
601
550
  (node.object.type === "Literal" && node.object.regex)
602
551
  )
603
- ) &&
604
- !(
605
- (node.object.type === "FunctionExpression" || node.object.type === "ClassExpression") &&
606
- isHeadOfExpressionStatement(node) &&
607
- !hasDoubleExcessParens(node.object)
608
552
  )
609
553
  ) {
610
554
  report(node.object);
@@ -10,6 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const FixTracker = require("../util/fix-tracker");
13
+ const astUtils = require("../ast-utils");
13
14
 
14
15
  //------------------------------------------------------------------------------
15
16
  // Rule Definition
@@ -60,10 +61,10 @@ module.exports = {
60
61
  */
61
62
  function checkForPartOfClassBody(firstToken) {
62
63
  for (let token = firstToken;
63
- token.type === "Punctuator" && token.value !== "}";
64
+ token.type === "Punctuator" && !astUtils.isClosingBraceToken(token);
64
65
  token = sourceCode.getTokenAfter(token)
65
66
  ) {
66
- if (token.value === ";") {
67
+ if (astUtils.isSemicolonToken(token)) {
67
68
  report(token);
68
69
  }
69
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
- const reportObj = {
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 {
@@ -15,7 +15,7 @@ module.exports = {
15
15
  docs: {
16
16
  description: "disallow assignments to native objects or read-only global variables",
17
17
  category: "Best Practices",
18
- recommended: true,
18
+ recommended: false,
19
19
  replacedBy: ["no-global-assign"]
20
20
  },
21
21
 
@@ -15,7 +15,7 @@ module.exports = {
15
15
  docs: {
16
16
  description: "disallow negating the left operand in `in` expressions",
17
17
  category: "Possible Errors",
18
- recommended: true,
18
+ recommended: false,
19
19
  replacedBy: ["no-unsafe-negation"]
20
20
  },
21
21
  deprecated: true,
@@ -96,8 +96,15 @@ module.exports = {
96
96
  }
97
97
  break;
98
98
 
99
- default:
99
+ // EXCLUDES: e.g. ({ [foo]: a }) = bar;
100
+ case "Property":
101
+ if (parent.key === node) {
102
+ return false;
103
+ }
104
+
100
105
  break;
106
+
107
+ // no default
101
108
  }
102
109
 
103
110
  node = parent;
@@ -18,18 +18,45 @@ module.exports = {
18
18
 
19
19
  schema: {
20
20
  type: "array",
21
- items: [{ type: "string" }],
21
+ items: [{
22
+ oneOf: [
23
+ {
24
+ type: "string"
25
+ },
26
+ {
27
+ type: "object",
28
+ properties: {
29
+ selector: { type: "string" },
30
+ message: { type: "string" }
31
+ },
32
+ required: ["selector"],
33
+ additionalProperties: false
34
+ }
35
+ ]
36
+ }],
22
37
  uniqueItems: true,
23
38
  minItems: 0
24
39
  }
25
40
  },
26
41
 
27
42
  create(context) {
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
- }), {});
43
+ return context.options.reduce((result, selectorOrObject) => {
44
+ const isStringFormat = (typeof selectorOrObject === "string");
45
+ const hasCustomMessage = !isStringFormat && Boolean(selectorOrObject.message);
46
+
47
+ const selector = isStringFormat ? selectorOrObject : selectorOrObject.selector;
48
+ const message = hasCustomMessage ? selectorOrObject.message : "Using '{{selector}}' is not allowed.";
49
+
50
+ return Object.assign(result, {
51
+ [selector](node) {
52
+ context.report({
53
+ node,
54
+ message,
55
+ data: hasCustomMessage ? {} : { selector }
56
+ });
57
+ }
58
+ });
59
+ }, {});
33
60
 
34
61
  }
35
62
  };
@@ -76,8 +76,8 @@ module.exports = {
76
76
  nextToken = sourceCode.getTokenAfter(node, 1);
77
77
 
78
78
  return isParenthesised(node) && previousToken && nextToken &&
79
- previousToken.value === "(" && previousToken.range[1] <= node.range[0] &&
80
- nextToken.value === ")" && nextToken.range[0] >= node.range[1];
79
+ astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
80
+ astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
81
81
  }
82
82
 
83
83
  return {
@@ -44,7 +44,7 @@ module.exports = {
44
44
  docs: {
45
45
  description: "disallow negating the left operand of relational operators",
46
46
  category: "Possible Errors",
47
- recommended: false
47
+ recommended: true
48
48
  },
49
49
  schema: [],
50
50
  fixable: "code"
@@ -9,6 +9,7 @@
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  const astUtils = require("../ast-utils");
12
+ const esUtils = require("esutils");
12
13
 
13
14
  //------------------------------------------------------------------------------
14
15
  // Rule Definition
@@ -55,7 +56,17 @@ module.exports = {
55
56
  // If there are comments between the brackets and the property name, don't do a fix.
56
57
  return null;
57
58
  }
58
- return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], key.raw);
59
+
60
+ const tokenBeforeLeftBracket = sourceCode.getTokenBefore(leftSquareBracket);
61
+
62
+ // Insert a space before the key to avoid changing identifiers, e.g. ({ get[2]() {} }) to ({ get2() {} })
63
+ const needsSpaceBeforeKey = tokenBeforeLeftBracket.range[1] === leftSquareBracket.range[0] &&
64
+ esUtils.code.isIdentifierPartES6(tokenBeforeLeftBracket.value.slice(-1).charCodeAt(0)) &&
65
+ esUtils.code.isIdentifierPartES6(key.raw.charCodeAt(0));
66
+
67
+ const replacementKey = (needsSpaceBeforeKey ? " " : "") + key.raw;
68
+
69
+ return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], replacementKey);
59
70
  }
60
71
  });
61
72
  }
@@ -171,8 +171,8 @@ module.exports = {
171
171
 
172
172
  if (astUtils.isTokenOnSameLine(penultimate, last)) {
173
173
  const shouldCheckPenultimate = (
174
- options.arraysInObjectsException && penultimate.value === "]" ||
175
- options.objectsInObjectsException && penultimate.value === "}"
174
+ options.arraysInObjectsException && astUtils.isClosingBracketToken(penultimate) ||
175
+ options.objectsInObjectsException && astUtils.isClosingBraceToken(penultimate)
176
176
  );
177
177
  const penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type;
178
178
 
@@ -230,7 +230,10 @@ module.exports = {
230
230
  const functionToken = sourceCode.getTokens(node.value).find(token => token.type === "Keyword" && token.value === "function");
231
231
  const tokenBeforeParams = node.value.generator ? sourceCode.getTokenAfter(functionToken) : functionToken;
232
232
 
233
- return fixer.replaceTextRange([firstKeyToken.range[0], tokenBeforeParams.range[1]], keyPrefix + keyText);
233
+ return fixer.replaceTextRange(
234
+ [firstKeyToken.range[0], node.range[1]],
235
+ keyPrefix + keyText + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1])
236
+ );
234
237
  }
235
238
  const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>");
236
239
  const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken);
@@ -238,7 +241,10 @@ module.exports = {
238
241
  const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]);
239
242
  const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`;
240
243
 
241
- return fixer.replaceTextRange([firstKeyToken.range[0], arrowToken.range[1]], keyPrefix + keyText + newParamText);
244
+ return fixer.replaceTextRange(
245
+ [firstKeyToken.range[0], node.range[1]],
246
+ keyPrefix + keyText + newParamText + sourceCode.text.slice(arrowToken.range[1], node.value.range[1])
247
+ );
242
248
 
243
249
  }
244
250
 
@@ -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
  // Helpers
9
15
  //------------------------------------------------------------------------------
@@ -135,7 +141,7 @@ module.exports = {
135
141
  const equalsToken = getOperatorToken(node);
136
142
  const operatorToken = getOperatorToken(expr);
137
143
  const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]);
138
- const rightText = sourceCode.getText().slice(operatorToken.range[1], expr.right.range[1]);
144
+ const rightText = sourceCode.getText().slice(operatorToken.range[1], node.right.range[1]);
139
145
 
140
146
  return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`);
141
147
  }
@@ -171,9 +177,20 @@ module.exports = {
171
177
  if (canBeFixed(node.left)) {
172
178
  const operatorToken = getOperatorToken(node);
173
179
  const leftText = sourceCode.getText().slice(node.range[0], operatorToken.range[0]);
174
- const rightText = sourceCode.getText().slice(operatorToken.range[1], node.range[1]);
180
+ const newOperator = node.operator.slice(0, -1);
181
+ let rightText;
182
+
183
+ // If this change would modify precedence (e.g. `foo *= bar + 1` => `foo = foo * (bar + 1)`), parenthesize the right side.
184
+ if (
185
+ astUtils.getPrecedence(node.right) <= astUtils.getPrecedence({ type: "BinaryExpression", operator: newOperator }) &&
186
+ !astUtils.isParenthesised(sourceCode, node.right)
187
+ ) {
188
+ rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`;
189
+ } else {
190
+ rightText = sourceCode.text.slice(operatorToken.range[1], node.range[1]);
191
+ }
175
192
 
176
- return fixer.replaceText(node, `${leftText}= ${leftText}${node.operator.slice(0, -1)}${rightText}`);
193
+ return fixer.replaceText(node, `${leftText}= ${leftText}${newOperator}${rightText}`);
177
194
  }
178
195
  return null;
179
196
  }
@@ -9,7 +9,7 @@
9
9
  // Helpers
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/;
12
+ const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestProperty|Property)$/;
13
13
  const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/;
14
14
  const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/;
15
15
 
@@ -209,6 +209,7 @@ module.exports = {
209
209
 
210
210
  // LiteralPropertyName.
211
211
  case "Property":
212
+ case "MethodDefinition":
212
213
  return parent.key === node && !parent.computed;
213
214
 
214
215
  // ModuleSpecifier.
@@ -105,20 +105,7 @@ module.exports = {
105
105
  function isBeforeClosingParen(token) {
106
106
  const nextToken = sourceCode.getTokenAfter(token);
107
107
 
108
- return (
109
- nextToken &&
110
- nextToken.type === "Punctuator" &&
111
- (nextToken.value === "}" || nextToken.value === ")")
112
- );
113
- }
114
-
115
- /**
116
- * Checks if the given token is a semicolon.
117
- * @param {Token} token The token to check.
118
- * @returns {boolean} Whether or not the given token is a semicolon.
119
- */
120
- function isSemicolon(token) {
121
- return token.type === "Punctuator" && token.value === ";";
108
+ return (nextToken && astUtils.isClosingBraceToken(nextToken) || astUtils.isClosingParenToken(nextToken));
122
109
  }
123
110
 
124
111
  /**
@@ -128,7 +115,7 @@ module.exports = {
128
115
  * @returns {void}
129
116
  */
130
117
  function checkSemicolonSpacing(token, node) {
131
- if (isSemicolon(token)) {
118
+ if (astUtils.isSemicolonToken(token)) {
132
119
  const location = token.loc.start;
133
120
 
134
121
  if (hasLeadingSpace(token)) {
package/lib/rules/semi.js CHANGED
@@ -9,6 +9,7 @@
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  const FixTracker = require("../util/fix-tracker");
12
+ const astUtils = require("../ast-utils");
12
13
 
13
14
  //------------------------------------------------------------------------------
14
15
  // Rule Definition
@@ -110,15 +111,6 @@ module.exports = {
110
111
 
111
112
  }
112
113
 
113
- /**
114
- * Checks whether a token is a semicolon punctuator.
115
- * @param {Token} token The token.
116
- * @returns {boolean} True if token is a semicolon punctuator.
117
- */
118
- function isSemicolon(token) {
119
- return (token.type === "Punctuator" && token.value === ";");
120
- }
121
-
122
114
  /**
123
115
  * Check if a semicolon is unnecessary, only true if:
124
116
  * - next token is on a new line and is not one of the opt-out tokens
@@ -127,7 +119,7 @@ module.exports = {
127
119
  * @returns {boolean} whether the semicolon is unnecessary.
128
120
  */
129
121
  function isUnnecessarySemicolon(lastToken) {
130
- if (!isSemicolon(lastToken)) {
122
+ if (!astUtils.isSemicolonToken(lastToken)) {
131
123
  return false;
132
124
  }
133
125
 
@@ -140,7 +132,7 @@ module.exports = {
140
132
  const lastTokenLine = lastToken.loc.end.line;
141
133
  const nextTokenLine = nextToken.loc.start.line;
142
134
  const isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value) && nextToken.value !== "++" && nextToken.value !== "--";
143
- const isDivider = (nextToken.value === "}" || nextToken.value === ";");
135
+ const isDivider = (astUtils.isClosingBraceToken(nextToken) || astUtils.isSemicolonToken(nextToken));
144
136
 
145
137
  return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider;
146
138
  }
@@ -176,7 +168,7 @@ module.exports = {
176
168
  report(node, true);
177
169
  }
178
170
  } else {
179
- if (!isSemicolon(lastToken)) {
171
+ if (!astUtils.isSemicolonToken(lastToken)) {
180
172
  if (!exceptOneLine || !isOneLinerBlock(node)) {
181
173
  report(node);
182
174
  }