eslint 3.15.0 → 3.16.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 (97) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/conf/{eslint.json → eslint-recommended.js} +85 -71
  3. package/lib/ast-utils.js +185 -19
  4. package/lib/code-path-analysis/code-path-state.js +2 -2
  5. package/lib/config/autoconfig.js +3 -3
  6. package/lib/config/config-file.js +14 -7
  7. package/lib/config/config-initializer.js +1 -1
  8. package/lib/config.js +3 -2
  9. package/lib/eslint.js +4 -4
  10. package/lib/rules/arrow-body-style.js +7 -4
  11. package/lib/rules/arrow-spacing.js +7 -6
  12. package/lib/rules/block-spacing.js +2 -2
  13. package/lib/rules/brace-style.js +2 -6
  14. package/lib/rules/capitalized-comments.js +6 -6
  15. package/lib/rules/comma-spacing.js +3 -3
  16. package/lib/rules/consistent-return.js +1 -1
  17. package/lib/rules/constructor-super.js +3 -3
  18. package/lib/rules/curly.js +11 -7
  19. package/lib/rules/default-case.js +3 -3
  20. package/lib/rules/eqeqeq.js +15 -6
  21. package/lib/rules/func-call-spacing.js +10 -13
  22. package/lib/rules/generator-star-spacing.js +18 -19
  23. package/lib/rules/id-blacklist.js +2 -2
  24. package/lib/rules/id-length.js +3 -3
  25. package/lib/rules/id-match.js +2 -2
  26. package/lib/rules/indent.js +7 -6
  27. package/lib/rules/key-spacing.js +12 -16
  28. package/lib/rules/keyword-spacing.js +2 -13
  29. package/lib/rules/line-comment-position.js +1 -1
  30. package/lib/rules/linebreak-style.js +7 -1
  31. package/lib/rules/lines-around-comment.js +4 -4
  32. package/lib/rules/lines-around-directive.js +3 -3
  33. package/lib/rules/max-lines.js +2 -2
  34. package/lib/rules/max-statements-per-line.js +7 -6
  35. package/lib/rules/newline-after-var.js +7 -2
  36. package/lib/rules/newline-per-chained-call.js +3 -1
  37. package/lib/rules/no-cond-assign.js +3 -3
  38. package/lib/rules/no-extend-native.js +3 -3
  39. package/lib/rules/no-extra-bind.js +3 -4
  40. package/lib/rules/no-extra-boolean-cast.js +8 -0
  41. package/lib/rules/no-extra-parens.js +1 -2
  42. package/lib/rules/no-inner-declarations.js +4 -4
  43. package/lib/rules/no-irregular-whitespace.js +7 -1
  44. package/lib/rules/no-lone-blocks.js +10 -10
  45. package/lib/rules/no-mixed-operators.js +1 -7
  46. package/lib/rules/no-multi-spaces.js +4 -1
  47. package/lib/rules/no-multi-str.js +7 -3
  48. package/lib/rules/no-return-assign.js +7 -14
  49. package/lib/rules/no-sequences.js +7 -6
  50. package/lib/rules/no-trailing-spaces.js +8 -2
  51. package/lib/rules/no-undefined.js +45 -6
  52. package/lib/rules/no-unexpected-multiline.js +9 -8
  53. package/lib/rules/no-unneeded-ternary.js +5 -1
  54. package/lib/rules/no-unused-labels.js +17 -2
  55. package/lib/rules/no-unused-vars.js +2 -16
  56. package/lib/rules/no-useless-computed-key.js +8 -3
  57. package/lib/rules/no-useless-concat.js +10 -7
  58. package/lib/rules/no-useless-escape.js +1 -1
  59. package/lib/rules/no-useless-return.js +1 -7
  60. package/lib/rules/no-var.js +1 -3
  61. package/lib/rules/no-whitespace-before-property.js +5 -16
  62. package/lib/rules/object-curly-newline.js +2 -2
  63. package/lib/rules/object-curly-spacing.js +7 -25
  64. package/lib/rules/object-property-newline.js +3 -3
  65. package/lib/rules/object-shorthand.js +2 -2
  66. package/lib/rules/operator-assignment.js +1 -1
  67. package/lib/rules/operator-linebreak.js +8 -10
  68. package/lib/rules/padded-blocks.js +4 -4
  69. package/lib/rules/prefer-spread.js +1 -1
  70. package/lib/rules/prefer-template.js +1 -1
  71. package/lib/rules/quotes.js +10 -6
  72. package/lib/rules/semi-spacing.js +4 -0
  73. package/lib/rules/space-before-function-paren.js +8 -5
  74. package/lib/rules/spaced-comment.js +2 -2
  75. package/lib/rules/strict.js +2 -2
  76. package/lib/rules/unicode-bom.js +1 -1
  77. package/lib/rules/wrap-iife.js +5 -5
  78. package/lib/rules/yoda.js +2 -7
  79. package/lib/testers/rule-tester.js +13 -6
  80. package/lib/token-store/backward-token-comment-cursor.js +57 -0
  81. package/lib/token-store/backward-token-cursor.js +56 -0
  82. package/lib/token-store/cursor.js +76 -0
  83. package/lib/token-store/cursors.js +92 -0
  84. package/lib/token-store/decorative-cursor.js +39 -0
  85. package/lib/token-store/filter-cursor.js +43 -0
  86. package/lib/token-store/forward-token-comment-cursor.js +57 -0
  87. package/lib/token-store/forward-token-cursor.js +61 -0
  88. package/lib/token-store/index.js +604 -0
  89. package/lib/token-store/limit-cursor.js +40 -0
  90. package/lib/token-store/padded-token-cursor.js +38 -0
  91. package/lib/token-store/skip-cursor.js +42 -0
  92. package/lib/token-store/utils.js +100 -0
  93. package/lib/util/source-code-fixer.js +35 -39
  94. package/lib/util/source-code.js +31 -15
  95. package/messages/extend-config-missing.txt +3 -0
  96. package/package.json +2 -2
  97. package/lib/token-store.js +0 -203
@@ -4,6 +4,12 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const astUtils = require("../ast-utils");
12
+
7
13
  //------------------------------------------------------------------------------
8
14
  // Rule Definition
9
15
  //------------------------------------------------------------------------------
@@ -51,12 +57,7 @@ module.exports = {
51
57
  * @returns {Object} Tokens of arrow and before/after arrow.
52
58
  */
53
59
  function getTokens(node) {
54
- let arrow = sourceCode.getTokenBefore(node.body);
55
-
56
- // skip '(' tokens.
57
- while (arrow.value !== "=>") {
58
- arrow = sourceCode.getTokenBefore(arrow);
59
- }
60
+ const arrow = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken);
60
61
 
61
62
  return {
62
63
  before: sourceCode.getTokenBefore(arrow),
@@ -74,8 +74,8 @@ module.exports = {
74
74
  // Gets braces and the first/last token of content.
75
75
  const openBrace = getOpenBrace(node);
76
76
  const closeBrace = sourceCode.getLastToken(node);
77
- const firstToken = sourceCode.getTokenOrCommentAfter(openBrace);
78
- const lastToken = sourceCode.getTokenOrCommentBefore(closeBrace);
77
+ const firstToken = sourceCode.getTokenAfter(openBrace, { includeComments: true });
78
+ const lastToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
79
79
 
80
80
  // Skip if the node is invalid or empty.
81
81
  if (openBrace.type !== "Punctuator" ||
@@ -62,7 +62,7 @@ module.exports = {
62
62
  function removeNewlineBetween(firstToken, secondToken) {
63
63
  const textRange = [firstToken.range[1], secondToken.range[0]];
64
64
  const textBetween = sourceCode.text.slice(textRange[0], textRange[1]);
65
- const NEWLINE_REGEX = /\r\n|\r|\n|\u2028|\u2029/g;
65
+ const NEWLINE_REGEX = astUtils.createGlobalLinebreakMatcher();
66
66
 
67
67
  // Don't do a fix if there is a comment between the tokens
68
68
  return fixer => fixer.replaceTextRange(textRange, textBetween.trim() ? null : textBetween.replace(NEWLINE_REGEX, ""));
@@ -144,11 +144,7 @@ module.exports = {
144
144
 
145
145
  return {
146
146
  BlockStatement(node) {
147
- if (
148
- node.parent.type !== "BlockStatement" &&
149
- node.parent.type !== "SwitchCase" &&
150
- node.parent.type !== "Program"
151
- ) {
147
+ if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
152
148
  validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node));
153
149
  }
154
150
  },
@@ -163,8 +163,8 @@ module.exports = {
163
163
  * otherwise.
164
164
  */
165
165
  function isInlineComment(comment) {
166
- const previousToken = sourceCode.getTokenOrCommentBefore(comment),
167
- nextToken = sourceCode.getTokenOrCommentAfter(comment);
166
+ const previousToken = sourceCode.getTokenBefore(comment, { includeComments: true }),
167
+ nextToken = sourceCode.getTokenAfter(comment, { includeComments: true });
168
168
 
169
169
  return Boolean(
170
170
  previousToken &&
@@ -181,7 +181,7 @@ module.exports = {
181
181
  * @returns {boolean} True if the comment follows a valid comment.
182
182
  */
183
183
  function isConsecutiveComment(comment) {
184
- const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(comment);
184
+ const previousTokenOrComment = sourceCode.getTokenBefore(comment, { includeComments: true });
185
185
 
186
186
  return Boolean(
187
187
  previousTokenOrComment &&
@@ -264,9 +264,9 @@ module.exports = {
264
264
  commentValid = isCommentValid(comment, options);
265
265
 
266
266
  if (!commentValid) {
267
- const message = capitalize === "always" ?
268
- ALWAYS_MESSAGE :
269
- NEVER_MESSAGE;
267
+ const message = capitalize === "always"
268
+ ? ALWAYS_MESSAGE
269
+ : NEVER_MESSAGE;
270
270
 
271
271
  context.report({
272
272
  node: null, // Intentionally using loc instead
@@ -96,9 +96,9 @@ module.exports = {
96
96
  return fixer.replaceTextRange([start, end], newText);
97
97
 
98
98
  },
99
- message: options[dir] ?
100
- "A space is required {{dir}} ','." :
101
- "There should be no space {{dir}} ','.",
99
+ message: options[dir]
100
+ ? "A space is required {{dir}} ','."
101
+ : "There should be no space {{dir}} ','.",
102
102
  data: {
103
103
  dir
104
104
  }
@@ -104,7 +104,7 @@ module.exports = {
104
104
  } else if (node.type === "ArrowFunctionExpression") {
105
105
 
106
106
  // `=>` token
107
- loc = context.getSourceCode().getTokenBefore(node.body).loc.start;
107
+ loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start;
108
108
  type = "function";
109
109
  } else if (
110
110
  node.parent.type === "MethodDefinition" ||
@@ -209,9 +209,9 @@ module.exports = {
209
209
 
210
210
  if (!calledInEveryPaths) {
211
211
  context.report({
212
- message: calledInSomePaths ?
213
- "Lacked a call of 'super()' in some code paths." :
214
- "Expected to call 'super()'.",
212
+ message: calledInSomePaths
213
+ ? "Lacked a call of 'super()' in some code paths."
214
+ : "Expected to call 'super()'.",
215
215
  node: node.parent
216
216
  });
217
217
  }
@@ -94,19 +94,23 @@ module.exports = {
94
94
  return first.loc.start.line === last.loc.end.line;
95
95
  }
96
96
 
97
+ /**
98
+ * Checks if the given token is an `else` token or not.
99
+ *
100
+ * @param {Token} token - The token to check.
101
+ * @returns {boolean} `true` if the token is an `else` token.
102
+ */
103
+ function isElseKeywordToken(token) {
104
+ return token.value === "else" && token.type === "Keyword";
105
+ }
106
+
97
107
  /**
98
108
  * Gets the `else` keyword token of a given `IfStatement` node.
99
109
  * @param {ASTNode} node - A `IfStatement` node to get.
100
110
  * @returns {Token} The `else` keyword token.
101
111
  */
102
112
  function getElseKeyword(node) {
103
- let token = sourceCode.getTokenAfter(node.consequent);
104
-
105
- while (token.type !== "Keyword" || token.value !== "else") {
106
- token = sourceCode.getTokenAfter(token);
107
- }
108
-
109
- return token;
113
+ return node.alternate && sourceCode.getFirstTokenBetween(node.consequent, node.alternate, isElseKeywordToken);
110
114
  }
111
115
 
112
116
  /**
@@ -31,9 +31,9 @@ module.exports = {
31
31
 
32
32
  create(context) {
33
33
  const options = context.options[0] || {};
34
- const commentPattern = options.commentPattern ?
35
- new RegExp(options.commentPattern) :
36
- DEFAULT_COMMENT_PATTERN;
34
+ const commentPattern = options.commentPattern
35
+ ? new RegExp(options.commentPattern)
36
+ : DEFAULT_COMMENT_PATTERN;
37
37
 
38
38
  const sourceCode = context.getSourceCode();
39
39
 
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("../ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -57,9 +63,9 @@ module.exports = {
57
63
  const options = context.options[1] || {};
58
64
  const sourceCode = context.getSourceCode();
59
65
 
60
- const nullOption = (config === "always") ?
61
- options.null || "always" :
62
- "ignore";
66
+ const nullOption = (config === "always")
67
+ ? options.null || "always"
68
+ : "ignore";
63
69
  const enforceRuleForNull = (nullOption === "always");
64
70
  const enforceInverseRuleForNull = (nullOption === "never");
65
71
 
@@ -100,8 +106,7 @@ module.exports = {
100
106
  * @private
101
107
  */
102
108
  function isNullCheck(node) {
103
- return (node.right.type === "Literal" && node.right.value === null) ||
104
- (node.left.type === "Literal" && node.left.value === null);
109
+ return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
105
110
  }
106
111
 
107
112
  /**
@@ -134,7 +139,11 @@ module.exports = {
134
139
 
135
140
  // If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix.
136
141
  if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) {
137
- const operatorToken = sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator);
142
+ const operatorToken = sourceCode.getFirstTokenBetween(
143
+ node.left,
144
+ node.right,
145
+ token => token.value === node.operator
146
+ );
138
147
 
139
148
  return fixer.replaceText(operatorToken, expectedOperator);
140
149
  }
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("../ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -67,19 +73,10 @@ module.exports = {
67
73
  * @private
68
74
  */
69
75
  function checkSpacing(node) {
76
+ const lastToken = sourceCode.getLastToken(node);
70
77
  const lastCalleeToken = sourceCode.getLastToken(node.callee);
71
- let prevToken = lastCalleeToken;
72
- let parenToken = sourceCode.getTokenAfter(lastCalleeToken);
73
-
74
- // advances to an open parenthesis.
75
- while (
76
- parenToken &&
77
- parenToken.range[1] < node.range[1] &&
78
- parenToken.value !== "("
79
- ) {
80
- prevToken = parenToken;
81
- parenToken = sourceCode.getTokenAfter(parenToken);
82
- }
78
+ const parenToken = sourceCode.getFirstTokenBetween(lastCalleeToken, lastToken, astUtils.isOpeningParenToken);
79
+ const prevToken = parenToken && sourceCode.getTokenBefore(parenToken);
83
80
 
84
81
  // Parens in NewExpression are optional
85
82
  if (!(parenToken && parenToken.range[1] < node.range[1])) {
@@ -88,7 +85,7 @@ module.exports = {
88
85
 
89
86
  const textBetweenTokens = text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, "");
90
87
  const hasWhitespace = /\s/.test(textBetweenTokens);
91
- const hasNewline = hasWhitespace && /[\n\r\u2028\u2029]/.test(textBetweenTokens);
88
+ const hasNewline = hasWhitespace && astUtils.LINEBREAK_MATCHER.test(textBetweenTokens);
92
89
 
93
90
  /*
94
91
  * never allowNewlines hasWhitespace hasNewline message
@@ -55,21 +55,26 @@ module.exports = {
55
55
  const sourceCode = context.getSourceCode();
56
56
 
57
57
  /**
58
- * Gets `*` token from a given node.
58
+ * Checks if the given token is a star token or not.
59
59
  *
60
- * @param {ASTNode} node - A node to get `*` token. This is one of
61
- * FunctionDeclaration, FunctionExpression, Property, and
62
- * MethodDefinition.
63
- * @returns {Token} `*` token.
60
+ * @param {Token} token - The token to check.
61
+ * @returns {boolean} `true` if the token is a star token.
64
62
  */
65
- function getStarToken(node) {
66
- let token = sourceCode.getFirstToken(node);
67
-
68
- while (token.value !== "*") {
69
- token = sourceCode.getTokenAfter(token);
70
- }
63
+ function isStarToken(token) {
64
+ return token.value === "*" && token.type === "Punctuator";
65
+ }
71
66
 
72
- return token;
67
+ /**
68
+ * Gets the generator star token of the given function node.
69
+ *
70
+ * @param {ASTNode} node - The function node to get.
71
+ * @returns {Token} Found star token.
72
+ */
73
+ function getStarToken(node) {
74
+ return sourceCode.getFirstToken(
75
+ (node.parent.method || node.parent.type === "MethodDefinition") ? node.parent : node,
76
+ isStarToken
77
+ );
73
78
  }
74
79
 
75
80
  /**
@@ -116,17 +121,11 @@ module.exports = {
116
121
  * @returns {void}
117
122
  */
118
123
  function checkFunction(node) {
119
- let starToken;
120
-
121
124
  if (!node.generator) {
122
125
  return;
123
126
  }
124
127
 
125
- if (node.parent.method || node.parent.type === "MethodDefinition") {
126
- starToken = getStarToken(node.parent);
127
- } else {
128
- starToken = getStarToken(node);
129
- }
128
+ const starToken = getStarToken(node);
130
129
 
131
130
  // Only check before when preceded by `function`|`static` keyword
132
131
  const prevToken = sourceCode.getTokenBefore(starToken);
@@ -55,8 +55,8 @@ module.exports = {
55
55
  * @returns {boolean} whether an error should be reported or not
56
56
  */
57
57
  function shouldReport(effectiveParent, name) {
58
- return effectiveParent.type !== "CallExpression"
59
- && effectiveParent.type !== "NewExpression" &&
58
+ return effectiveParent.type !== "CallExpression" &&
59
+ effectiveParent.type !== "NewExpression" &&
60
60
  isInvalid(name);
61
61
  }
62
62
 
@@ -104,9 +104,9 @@ module.exports = {
104
104
  if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) {
105
105
  context.report({
106
106
  node,
107
- message: isShort ?
108
- "Identifier name '{{name}}' is too short (< {{min}})." :
109
- "Identifier name '{{name}}' is too long (> {{max}}).",
107
+ message: isShort
108
+ ? "Identifier name '{{name}}' is too short (< {{min}})."
109
+ : "Identifier name '{{name}}' is too long (> {{max}}).",
110
110
  data: { name, min: minLength, max: maxLength }
111
111
  });
112
112
  }
@@ -63,8 +63,8 @@ module.exports = {
63
63
  * @returns {boolean} whether an error should be reported or not
64
64
  */
65
65
  function shouldReport(effectiveParent, name) {
66
- return effectiveParent.type !== "CallExpression"
67
- && effectiveParent.type !== "NewExpression" &&
66
+ return effectiveParent.type !== "CallExpression" &&
67
+ effectiveParent.type !== "NewExpression" &&
68
68
  isInvalid(name);
69
69
  }
70
70
 
@@ -8,6 +8,12 @@
8
8
 
9
9
  "use strict";
10
10
 
11
+ //------------------------------------------------------------------------------
12
+ // Requirements
13
+ //------------------------------------------------------------------------------
14
+
15
+ const astUtils = require("../ast-utils");
16
+
11
17
  //------------------------------------------------------------------------------
12
18
  // Rule Definition
13
19
  //------------------------------------------------------------------------------
@@ -435,15 +441,10 @@ module.exports = {
435
441
  * @returns {void}
436
442
  */
437
443
  function checkLastReturnStatementLineIndent(node, firstLineIndent) {
438
- const nodeLastToken = sourceCode.getLastToken(node);
439
- let lastToken = nodeLastToken;
440
444
 
441
445
  // in case if return statement ends with ');' we have traverse back to ')'
442
446
  // otherwise we'll measure indent for ';' and replace ')'
443
- while (lastToken.value !== ")") {
444
- lastToken = sourceCode.getTokenBefore(lastToken);
445
- }
446
-
447
+ const lastToken = sourceCode.getLastToken(node, astUtils.isClosingParenToken);
447
448
  const textBeforeClosingParenthesis = sourceCode.getText(lastToken, lastToken.loc.start.column).slice(0, -1);
448
449
 
449
450
  if (textBeforeClosingParenthesis.trim()) {
@@ -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
  //------------------------------------------------------------------------------
@@ -15,7 +21,7 @@
15
21
  * @returns {boolean} True if str contains a line terminator.
16
22
  */
17
23
  function containsLineTerminator(str) {
18
- return /[\n\r\u2028\u2029]/.test(str);
24
+ return astUtils.LINEBREAK_MATCHER.test(str);
19
25
  }
20
26
 
21
27
  /**
@@ -364,14 +370,9 @@ module.exports = {
364
370
  * @returns {ASTNode} The last token before a colon punctuator.
365
371
  */
366
372
  function getLastTokenBeforeColon(node) {
367
- let prevNode;
373
+ const colonToken = sourceCode.getTokenAfter(node, astUtils.isColonToken);
368
374
 
369
- while (node && (node.type !== "Punctuator" || node.value !== ":")) {
370
- prevNode = node;
371
- node = sourceCode.getTokenAfter(node);
372
- }
373
-
374
- return prevNode;
375
+ return sourceCode.getTokenBefore(colonToken);
375
376
  }
376
377
 
377
378
  /**
@@ -381,12 +382,7 @@ module.exports = {
381
382
  * @returns {ASTNode} The colon punctuator.
382
383
  */
383
384
  function getNextColon(node) {
384
-
385
- while (node && (node.type !== "Punctuator" || node.value !== ":")) {
386
- node = sourceCode.getTokenAfter(node);
387
- }
388
-
389
- return node;
385
+ return sourceCode.getTokenAfter(node, astUtils.isColonToken);
390
386
  }
391
387
 
392
388
  /**
@@ -417,8 +413,8 @@ module.exports = {
417
413
  function report(property, side, whitespace, expected, mode) {
418
414
  const diff = whitespace.length - expected,
419
415
  nextColon = getNextColon(property.key),
420
- tokenBeforeColon = sourceCode.getTokenOrCommentBefore(nextColon),
421
- tokenAfterColon = sourceCode.getTokenOrCommentAfter(nextColon),
416
+ tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
417
+ tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
422
418
  isKeySide = side === "key",
423
419
  locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
424
420
  isExtra = diff > 0,
@@ -342,11 +342,7 @@ module.exports = {
342
342
  */
343
343
  function checkSpacingAroundTokenBefore(node) {
344
344
  if (node) {
345
- let token = sourceCode.getTokenBefore(node);
346
-
347
- while (token.type !== "Keyword") {
348
- token = sourceCode.getTokenBefore(token);
349
- }
345
+ const token = sourceCode.getTokenBefore(node, astUtils.isKeywordToken);
350
346
 
351
347
  checkSpacingAround(token);
352
348
  }
@@ -439,14 +435,7 @@ module.exports = {
439
435
  */
440
436
  function checkSpacingForForOfStatement(node) {
441
437
  checkSpacingAroundFirstToken(node);
442
-
443
- // `of` is not a keyword token.
444
- let token = sourceCode.getTokenBefore(node.right);
445
-
446
- while (token.value !== "of") {
447
- token = sourceCode.getTokenBefore(token);
448
- }
449
- checkSpacingAround(token);
438
+ checkSpacingAround(sourceCode.getTokenBefore(node.right, astUtils.isNotOpeningParenToken));
450
439
  }
451
440
 
452
441
  /**
@@ -77,7 +77,7 @@ module.exports = {
77
77
  return;
78
78
  }
79
79
 
80
- const previous = sourceCode.getTokenOrCommentBefore(node);
80
+ const previous = sourceCode.getTokenBefore(node, { includeComments: true });
81
81
  const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line;
82
82
 
83
83
  if (above) {
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("../ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -60,7 +66,7 @@ module.exports = {
60
66
  expectedLF = linebreakStyle === "unix",
61
67
  expectedLFChars = expectedLF ? "\n" : "\r\n",
62
68
  source = sourceCode.getText(),
63
- pattern = /\r\n|\r|\n|\u2028|\u2029/g;
69
+ pattern = astUtils.createGlobalLinebreakMatcher();
64
70
  let match;
65
71
 
66
72
  let i = 0;
@@ -139,7 +139,7 @@ module.exports = {
139
139
 
140
140
  token = node;
141
141
  do {
142
- token = sourceCode.getTokenOrCommentBefore(token);
142
+ token = sourceCode.getTokenBefore(token, { includeComments: true });
143
143
  } while (isCommentNodeType(token));
144
144
 
145
145
  if (token && astUtils.isTokenOnSameLine(token, node)) {
@@ -148,7 +148,7 @@ module.exports = {
148
148
 
149
149
  token = node;
150
150
  do {
151
- token = sourceCode.getTokenOrCommentAfter(token);
151
+ token = sourceCode.getTokenAfter(token, { includeComments: true });
152
152
  } while (isCommentNodeType(token));
153
153
 
154
154
  if (token && astUtils.isTokenOnSameLine(node, token)) {
@@ -300,8 +300,8 @@ module.exports = {
300
300
  return;
301
301
  }
302
302
 
303
- const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node);
304
- const nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node);
303
+ const previousTokenOrComment = sourceCode.getTokenBefore(node, { includeComments: true });
304
+ const nextTokenOrComment = sourceCode.getTokenAfter(node, { includeComments: true });
305
305
 
306
306
  // check for newline before
307
307
  if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) &&
@@ -57,7 +57,7 @@ module.exports = {
57
57
  * @returns {boolean} Whether or not the passed in node is preceded by a blank newline.
58
58
  */
59
59
  function hasNewlineBefore(node) {
60
- const tokenBefore = sourceCode.getTokenOrCommentBefore(node);
60
+ const tokenBefore = sourceCode.getTokenBefore(node, { includeComments: true });
61
61
  const tokenLineBefore = tokenBefore ? tokenBefore.loc.end.line : 0;
62
62
 
63
63
  return node.loc.start.line - tokenLineBefore >= 2;
@@ -86,7 +86,7 @@ module.exports = {
86
86
  */
87
87
  function hasNewlineAfter(node) {
88
88
  const lastToken = getLastTokenOnLine(node);
89
- const tokenAfter = sourceCode.getTokenOrCommentAfter(lastToken);
89
+ const tokenAfter = sourceCode.getTokenAfter(lastToken, { includeComments: true });
90
90
 
91
91
  return tokenAfter.loc.start.line - lastToken.loc.end.line >= 2;
92
92
  }
@@ -131,7 +131,7 @@ module.exports = {
131
131
  }
132
132
 
133
133
  const firstDirective = directives[0];
134
- const hasTokenOrCommentBefore = !!sourceCode.getTokenOrCommentBefore(firstDirective);
134
+ const hasTokenOrCommentBefore = !!sourceCode.getTokenBefore(firstDirective, { includeComments: true });
135
135
 
136
136
  // Only check before the first directive if it is preceded by a comment or if it is at the top of
137
137
  // the file and expectLineBefore is set to "never". This is to not force a newline at the top of
@@ -90,7 +90,7 @@ module.exports = {
90
90
 
91
91
  token = comment;
92
92
  do {
93
- token = sourceCode.getTokenOrCommentBefore(token);
93
+ token = sourceCode.getTokenBefore(token, { includeComments: true });
94
94
  } while (isCommentNodeType(token));
95
95
 
96
96
  if (token && astUtils.isTokenOnSameLine(token, comment)) {
@@ -99,7 +99,7 @@ module.exports = {
99
99
 
100
100
  token = comment;
101
101
  do {
102
- token = sourceCode.getTokenOrCommentAfter(token);
102
+ token = sourceCode.getTokenAfter(token, { includeComments: true });
103
103
  } while (isCommentNodeType(token));
104
104
 
105
105
  if (token && astUtils.isTokenOnSameLine(comment, token)) {
@@ -4,6 +4,12 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const astUtils = require("../ast-utils");
12
+
7
13
  //------------------------------------------------------------------------------
8
14
  // Rule Definition
9
15
  //------------------------------------------------------------------------------
@@ -74,12 +80,7 @@ module.exports = {
74
80
  * @returns {Token} The actual last token.
75
81
  */
76
82
  function getActualLastToken(node) {
77
- let lastToken = sourceCode.getLastToken(node);
78
-
79
- if (lastToken.value === ";") {
80
- lastToken = sourceCode.getTokenBefore(lastToken);
81
- }
82
- return lastToken;
83
+ return sourceCode.getLastToken(node, astUtils.isNotSemicolonToken);
83
84
  }
84
85
 
85
86
  /**
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("../ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -201,8 +207,7 @@ module.exports = {
201
207
  message: NEVER_MESSAGE,
202
208
  data: { identifier: node.name },
203
209
  fix(fixer) {
204
- const NEWLINE_REGEX = /\r\n|\r|\n|\u2028|\u2029/;
205
- const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(NEWLINE_REGEX);
210
+ const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER);
206
211
 
207
212
  return fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], `${linesBetween.slice(0, -1).join("")}\n${linesBetween[linesBetween.length - 1]}`);
208
213
  }