eslint 6.3.0 → 6.6.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 (189) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +11 -10
  3. package/bin/eslint.js +38 -12
  4. package/lib/cli-engine/cascading-config-array-factory.js +2 -1
  5. package/lib/cli-engine/cli-engine.js +11 -11
  6. package/lib/cli-engine/config-array/config-array.js +0 -4
  7. package/lib/cli-engine/config-array/config-dependency.js +2 -0
  8. package/lib/cli-engine/config-array/override-tester.js +4 -2
  9. package/lib/cli-engine/config-array-factory.js +7 -1
  10. package/lib/cli-engine/file-enumerator.js +5 -3
  11. package/lib/cli-engine/formatters/html.js +1 -0
  12. package/lib/cli-engine/ignored-paths.js +4 -3
  13. package/lib/cli-engine/lint-result-cache.js +0 -1
  14. package/lib/cli.js +13 -12
  15. package/lib/init/autoconfig.js +1 -11
  16. package/lib/init/config-file.js +0 -1
  17. package/lib/init/config-initializer.js +0 -1
  18. package/lib/init/config-rule.js +3 -7
  19. package/lib/init/npm-utils.js +1 -6
  20. package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
  21. package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
  22. package/lib/linter/code-path-analysis/code-path-state.js +40 -81
  23. package/lib/linter/code-path-analysis/code-path.js +10 -11
  24. package/lib/linter/code-path-analysis/debug-helpers.js +9 -13
  25. package/lib/linter/code-path-analysis/fork-context.js +23 -34
  26. package/lib/linter/code-path-analysis/id-generator.js +2 -2
  27. package/lib/linter/linter.js +121 -96
  28. package/lib/linter/node-event-generator.js +3 -2
  29. package/lib/options.js +6 -0
  30. package/lib/rule-tester/rule-tester.js +7 -10
  31. package/lib/rules/accessor-pairs.js +59 -19
  32. package/lib/rules/array-bracket-newline.js +12 -15
  33. package/lib/rules/array-bracket-spacing.js +12 -12
  34. package/lib/rules/array-callback-return.js +6 -11
  35. package/lib/rules/array-element-newline.js +5 -8
  36. package/lib/rules/arrow-parens.js +0 -1
  37. package/lib/rules/block-scoped-var.js +3 -3
  38. package/lib/rules/block-spacing.js +4 -4
  39. package/lib/rules/capitalized-comments.js +2 -9
  40. package/lib/rules/class-methods-use-this.js +3 -3
  41. package/lib/rules/comma-dangle.js +15 -23
  42. package/lib/rules/comma-spacing.js +1 -1
  43. package/lib/rules/computed-property-spacing.js +28 -11
  44. package/lib/rules/consistent-return.js +4 -5
  45. package/lib/rules/consistent-this.js +5 -5
  46. package/lib/rules/constructor-super.js +14 -16
  47. package/lib/rules/curly.js +3 -5
  48. package/lib/rules/default-param-last.js +62 -0
  49. package/lib/rules/dot-location.js +11 -12
  50. package/lib/rules/eqeqeq.js +7 -19
  51. package/lib/rules/func-names.js +6 -6
  52. package/lib/rules/function-call-argument-newline.js +5 -5
  53. package/lib/rules/generator-star-spacing.js +4 -9
  54. package/lib/rules/getter-return.js +4 -7
  55. package/lib/rules/indent-legacy.js +1 -1
  56. package/lib/rules/indent.js +46 -8
  57. package/lib/rules/index.js +3 -0
  58. package/lib/rules/init-declarations.js +2 -2
  59. package/lib/rules/jsx-quotes.js +1 -1
  60. package/lib/rules/keyword-spacing.js +32 -56
  61. package/lib/rules/lines-around-directive.js +1 -1
  62. package/lib/rules/max-len.js +0 -5
  63. package/lib/rules/max-statements-per-line.js +3 -7
  64. package/lib/rules/multiline-ternary.js +3 -3
  65. package/lib/rules/new-parens.js +5 -1
  66. package/lib/rules/newline-after-var.js +6 -7
  67. package/lib/rules/newline-before-return.js +8 -9
  68. package/lib/rules/newline-per-chained-call.js +2 -4
  69. package/lib/rules/no-class-assign.js +2 -2
  70. package/lib/rules/no-compare-neg-zero.js +1 -2
  71. package/lib/rules/no-confusing-arrow.js +2 -2
  72. package/lib/rules/no-console.js +4 -8
  73. package/lib/rules/no-const-assign.js +1 -1
  74. package/lib/rules/no-dupe-args.js +1 -1
  75. package/lib/rules/no-dupe-class-members.js +3 -4
  76. package/lib/rules/no-dupe-keys.js +6 -5
  77. package/lib/rules/no-duplicate-imports.js +14 -18
  78. package/lib/rules/no-else-return.js +0 -8
  79. package/lib/rules/no-empty-function.js +2 -4
  80. package/lib/rules/no-eval.js +10 -18
  81. package/lib/rules/no-ex-assign.js +1 -1
  82. package/lib/rules/no-extra-bind.js +12 -13
  83. package/lib/rules/no-extra-boolean-cast.js +1 -3
  84. package/lib/rules/no-extra-label.js +13 -10
  85. package/lib/rules/no-extra-parens.js +32 -17
  86. package/lib/rules/no-extra-semi.js +5 -6
  87. package/lib/rules/no-fallthrough.js +6 -6
  88. package/lib/rules/no-func-assign.js +3 -3
  89. package/lib/rules/no-global-assign.js +4 -4
  90. package/lib/rules/no-implicit-coercion.js +10 -10
  91. package/lib/rules/no-implied-eval.js +0 -1
  92. package/lib/rules/no-import-assign.js +238 -0
  93. package/lib/rules/no-invalid-this.js +1 -3
  94. package/lib/rules/no-labels.js +3 -6
  95. package/lib/rules/no-lone-blocks.js +7 -2
  96. package/lib/rules/no-loop-func.js +6 -11
  97. package/lib/rules/no-magic-numbers.js +6 -6
  98. package/lib/rules/no-misleading-character-class.js +14 -7
  99. package/lib/rules/no-mixed-operators.js +13 -22
  100. package/lib/rules/no-mixed-requires.js +0 -1
  101. package/lib/rules/no-multi-spaces.js +1 -1
  102. package/lib/rules/no-native-reassign.js +4 -4
  103. package/lib/rules/no-obj-calls.js +29 -9
  104. package/lib/rules/no-octal-escape.js +14 -8
  105. package/lib/rules/no-param-reassign.js +28 -7
  106. package/lib/rules/no-redeclare.js +1 -1
  107. package/lib/rules/no-regex-spaces.js +105 -45
  108. package/lib/rules/no-restricted-imports.js +11 -11
  109. package/lib/rules/no-self-assign.js +18 -18
  110. package/lib/rules/no-sequences.js +5 -5
  111. package/lib/rules/no-shadow.js +1 -4
  112. package/lib/rules/no-tabs.js +8 -2
  113. package/lib/rules/no-this-before-super.js +12 -13
  114. package/lib/rules/no-trailing-spaces.js +19 -7
  115. package/lib/rules/no-undef-init.js +7 -1
  116. package/lib/rules/no-unmodified-loop-condition.js +16 -29
  117. package/lib/rules/no-unneeded-ternary.js +3 -3
  118. package/lib/rules/no-unreachable.js +7 -7
  119. package/lib/rules/no-unsafe-finally.js +4 -7
  120. package/lib/rules/no-unsafe-negation.js +34 -19
  121. package/lib/rules/no-unused-expressions.js +11 -7
  122. package/lib/rules/no-unused-labels.js +3 -6
  123. package/lib/rules/no-unused-vars.js +22 -29
  124. package/lib/rules/no-use-before-define.js +10 -15
  125. package/lib/rules/no-useless-call.js +4 -4
  126. package/lib/rules/no-useless-concat.js +4 -4
  127. package/lib/rules/no-useless-constructor.js +14 -22
  128. package/lib/rules/no-useless-escape.js +3 -5
  129. package/lib/rules/no-useless-rename.js +32 -20
  130. package/lib/rules/no-useless-return.js +11 -17
  131. package/lib/rules/no-var.js +12 -25
  132. package/lib/rules/no-warning-comments.js +0 -1
  133. package/lib/rules/no-whitespace-before-property.js +3 -3
  134. package/lib/rules/object-curly-newline.js +7 -10
  135. package/lib/rules/object-curly-spacing.js +14 -15
  136. package/lib/rules/object-shorthand.js +36 -10
  137. package/lib/rules/one-var-declaration-per-line.js +2 -2
  138. package/lib/rules/operator-assignment.js +22 -1
  139. package/lib/rules/padded-blocks.js +1 -1
  140. package/lib/rules/padding-line-between-statements.js +0 -16
  141. package/lib/rules/prefer-arrow-callback.js +6 -6
  142. package/lib/rules/prefer-const.js +13 -21
  143. package/lib/rules/prefer-destructuring.js +1 -7
  144. package/lib/rules/prefer-named-capture-group.js +3 -16
  145. package/lib/rules/prefer-numeric-literals.js +35 -3
  146. package/lib/rules/prefer-object-spread.js +7 -7
  147. package/lib/rules/prefer-regex-literals.js +125 -0
  148. package/lib/rules/prefer-rest-params.js +3 -6
  149. package/lib/rules/prefer-spread.js +4 -4
  150. package/lib/rules/prefer-template.js +5 -6
  151. package/lib/rules/quote-props.js +1 -1
  152. package/lib/rules/quotes.js +11 -6
  153. package/lib/rules/radix.js +5 -10
  154. package/lib/rules/require-await.js +2 -5
  155. package/lib/rules/require-yield.js +2 -2
  156. package/lib/rules/rest-spread-spacing.js +1 -1
  157. package/lib/rules/sort-imports.js +3 -4
  158. package/lib/rules/sort-keys.js +1 -3
  159. package/lib/rules/space-before-blocks.js +1 -2
  160. package/lib/rules/space-before-function-paren.js +12 -1
  161. package/lib/rules/space-in-parens.js +81 -75
  162. package/lib/rules/space-infix-ops.js +5 -5
  163. package/lib/rules/spaced-comment.js +15 -18
  164. package/lib/rules/strict.js +2 -4
  165. package/lib/rules/symbol-description.js +1 -2
  166. package/lib/rules/template-curly-spacing.js +2 -2
  167. package/lib/rules/use-isnan.js +104 -6
  168. package/lib/rules/utils/ast-utils.js +53 -81
  169. package/lib/rules/utils/fix-tracker.js +0 -6
  170. package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
  171. package/lib/rules/vars-on-top.js +11 -11
  172. package/lib/shared/config-ops.js +2 -2
  173. package/lib/shared/logging.js +2 -0
  174. package/lib/shared/runtime-info.js +163 -0
  175. package/lib/shared/traverser.js +2 -0
  176. package/lib/source-code/source-code.js +11 -12
  177. package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
  178. package/lib/source-code/token-store/backward-token-cursor.js +5 -5
  179. package/lib/source-code/token-store/cursors.js +17 -19
  180. package/lib/source-code/token-store/decorative-cursor.js +1 -1
  181. package/lib/source-code/token-store/filter-cursor.js +2 -2
  182. package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
  183. package/lib/source-code/token-store/forward-token-cursor.js +5 -5
  184. package/lib/source-code/token-store/index.js +86 -92
  185. package/lib/source-code/token-store/limit-cursor.js +2 -2
  186. package/lib/source-code/token-store/padded-token-cursor.js +7 -7
  187. package/lib/source-code/token-store/skip-cursor.js +2 -2
  188. package/lib/source-code/token-store/utils.js +9 -13
  189. package/package.json +8 -5
@@ -17,7 +17,7 @@ const astUtils = require("./utils/ast-utils");
17
17
 
18
18
  /**
19
19
  * Checks whether or not a given node is a concatenation.
20
- * @param {ASTNode} node - A node to check.
20
+ * @param {ASTNode} node A node to check.
21
21
  * @returns {boolean} `true` if the node is a concatenation.
22
22
  */
23
23
  function isConcatenation(node) {
@@ -26,7 +26,7 @@ function isConcatenation(node) {
26
26
 
27
27
  /**
28
28
  * Gets the top binary expression node for concatenation in parents of a given node.
29
- * @param {ASTNode} node - A node to get.
29
+ * @param {ASTNode} node A node to get.
30
30
  * @returns {ASTNode} the top binary expression node in parents of a given node.
31
31
  */
32
32
  function getTopConcatBinaryExpression(node) {
@@ -70,7 +70,7 @@ function hasOctalEscapeSequence(node) {
70
70
 
71
71
  /**
72
72
  * Checks whether or not a given binary expression has string literals.
73
- * @param {ASTNode} node - A node to check.
73
+ * @param {ASTNode} node A node to check.
74
74
  * @returns {boolean} `true` if the node has string literals.
75
75
  */
76
76
  function hasStringLiteral(node) {
@@ -84,7 +84,7 @@ function hasStringLiteral(node) {
84
84
 
85
85
  /**
86
86
  * Checks whether or not a given binary expression has non string literals.
87
- * @param {ASTNode} node - A node to check.
87
+ * @param {ASTNode} node A node to check.
88
88
  * @returns {boolean} `true` if the node has non string literals.
89
89
  */
90
90
  function hasNonStringLiteral(node) {
@@ -242,8 +242,7 @@ module.exports = {
242
242
 
243
243
  /**
244
244
  * Reports if a given node is string concatenation with non string literals.
245
- *
246
- * @param {ASTNode} node - A node to check.
245
+ * @param {ASTNode} node A node to check.
247
246
  * @returns {void}
248
247
  */
249
248
  function checkForStringConcat(node) {
@@ -85,7 +85,7 @@ module.exports = {
85
85
 
86
86
  /**
87
87
  * Checks whether a certain string constitutes an ES3 token
88
- * @param {string} tokenStr - The string to be checked.
88
+ * @param {string} tokenStr The string to be checked.
89
89
  * @returns {boolean} `true` if it is an ES3 token.
90
90
  */
91
91
  function isKeyword(tokenStr) {
@@ -41,7 +41,7 @@ const UNESCAPED_LINEBREAK_PATTERN = new RegExp(String.raw`(^|[^\\])(\\\\)*[${Arr
41
41
  * escaping and unescaping as necessary.
42
42
  * Only escaping of the minimal set of characters is changed.
43
43
  * Note: escaping of newlines when switching from backtick to other quotes is not handled.
44
- * @param {string} str - A string to convert.
44
+ * @param {string} str A string to convert.
45
45
  * @returns {string} The string with changed quotes.
46
46
  * @private
47
47
  */
@@ -143,7 +143,6 @@ module.exports = {
143
143
  *
144
144
  * In both cases, inside of the braces is handled as normal JavaScript.
145
145
  * The braces are `JSXExpressionContainer` nodes.
146
- *
147
146
  * @param {ASTNode} node The Literal node to check.
148
147
  * @returns {boolean} True if the node is a part of JSX, false if not.
149
148
  * @private
@@ -155,7 +154,7 @@ module.exports = {
155
154
  /**
156
155
  * Checks whether or not a given node is a directive.
157
156
  * The directive is a `ExpressionStatement` which has only a string literal.
158
- * @param {ASTNode} node - A node to check.
157
+ * @param {ASTNode} node A node to check.
159
158
  * @returns {boolean} Whether or not the node is a directive.
160
159
  * @private
161
160
  */
@@ -170,7 +169,7 @@ module.exports = {
170
169
  /**
171
170
  * Checks whether or not a given node is a part of directive prologues.
172
171
  * See also: http://www.ecma-international.org/ecma-262/6.0/#sec-directive-prologues-and-the-use-strict-directive
173
- * @param {ASTNode} node - A node to check.
172
+ * @param {ASTNode} node A node to check.
174
173
  * @returns {boolean} Whether or not the node is a part of directive prologues.
175
174
  * @private
176
175
  */
@@ -198,7 +197,7 @@ module.exports = {
198
197
 
199
198
  /**
200
199
  * Checks whether or not a given node is allowed as non backtick.
201
- * @param {ASTNode} node - A node to check.
200
+ * @param {ASTNode} node A node to check.
202
201
  * @returns {boolean} Whether or not the node is allowed as non backtick.
203
202
  * @private
204
203
  */
@@ -230,7 +229,7 @@ module.exports = {
230
229
 
231
230
  /**
232
231
  * Checks whether or not a given TemplateLiteral node is actually using any of the special features provided by template literal strings.
233
- * @param {ASTNode} node - A TemplateLiteral node to check.
232
+ * @param {ASTNode} node A TemplateLiteral node to check.
234
233
  * @returns {boolean} Whether or not the TemplateLiteral node is using any of the special features provided by template literal strings.
235
234
  * @private
236
235
  */
@@ -279,6 +278,12 @@ module.exports = {
279
278
  description: settings.description
280
279
  },
281
280
  fix(fixer) {
281
+ if (quoteOption === "backtick" && astUtils.hasOctalEscapeSequence(rawVal)) {
282
+
283
+ // An octal escape sequence in a template literal would produce syntax error, even in non-strict mode.
284
+ return null;
285
+ }
286
+
282
287
  return fixer.replaceText(node, settings.convert(node.raw));
283
288
  }
284
289
  });
@@ -20,8 +20,7 @@ const MODE_ALWAYS = "always",
20
20
 
21
21
  /**
22
22
  * Checks whether a given variable is shadowed or not.
23
- *
24
- * @param {eslint-scope.Variable} variable - A variable to check.
23
+ * @param {eslint-scope.Variable} variable A variable to check.
25
24
  * @returns {boolean} `true` if the variable is shadowed.
26
25
  */
27
26
  function isShadowed(variable) {
@@ -30,8 +29,7 @@ function isShadowed(variable) {
30
29
 
31
30
  /**
32
31
  * Checks whether a given node is a MemberExpression of `parseInt` method or not.
33
- *
34
- * @param {ASTNode} node - A node to check.
32
+ * @param {ASTNode} node A node to check.
35
33
  * @returns {boolean} `true` if the node is a MemberExpression of `parseInt`
36
34
  * method.
37
35
  */
@@ -51,8 +49,7 @@ function isParseIntMethod(node) {
51
49
  *
52
50
  * - A literal except numbers.
53
51
  * - undefined.
54
- *
55
- * @param {ASTNode} radix - A node of radix to check.
52
+ * @param {ASTNode} radix A node of radix to check.
56
53
  * @returns {boolean} `true` if the node is valid.
57
54
  */
58
55
  function isValidRadix(radix) {
@@ -64,8 +61,7 @@ function isValidRadix(radix) {
64
61
 
65
62
  /**
66
63
  * Checks whether a given node is a default value of radix or not.
67
- *
68
- * @param {ASTNode} radix - A node of radix to check.
64
+ * @param {ASTNode} radix A node of radix to check.
69
65
  * @returns {boolean} `true` if the node is the literal node of `10`.
70
66
  */
71
67
  function isDefaultRadix(radix) {
@@ -100,8 +96,7 @@ module.exports = {
100
96
  /**
101
97
  * Checks the arguments of a given CallExpression node and reports it if it
102
98
  * offends this rule.
103
- *
104
- * @param {ASTNode} node - A CallExpression node to check.
99
+ * @param {ASTNode} node A CallExpression node to check.
105
100
  * @returns {void}
106
101
  */
107
102
  function checkArguments(node) {
@@ -17,8 +17,7 @@ const astUtils = require("./utils/ast-utils");
17
17
 
18
18
  /**
19
19
  * Capitalize the 1st letter of the given text.
20
- *
21
- * @param {string} text - The text to capitalize.
20
+ * @param {string} text The text to capitalize.
22
21
  * @returns {string} The text that the 1st letter was capitalized.
23
22
  */
24
23
  function capitalizeFirstLetter(text) {
@@ -49,7 +48,6 @@ module.exports = {
49
48
 
50
49
  /**
51
50
  * Push the scope info object to the stack.
52
- *
53
51
  * @returns {void}
54
52
  */
55
53
  function enterFunction() {
@@ -62,8 +60,7 @@ module.exports = {
62
60
  /**
63
61
  * Pop the top scope info object from the stack.
64
62
  * Also, it reports the function if needed.
65
- *
66
- * @param {ASTNode} node - The node to report.
63
+ * @param {ASTNode} node The node to report.
67
64
  * @returns {void}
68
65
  */
69
66
  function exitFunction(node) {
@@ -28,7 +28,7 @@ module.exports = {
28
28
 
29
29
  /**
30
30
  * If the node is a generator function, start counting `yield` keywords.
31
- * @param {Node} node - A function node to check.
31
+ * @param {Node} node A function node to check.
32
32
  * @returns {void}
33
33
  */
34
34
  function beginChecking(node) {
@@ -40,7 +40,7 @@ module.exports = {
40
40
  /**
41
41
  * If the node is a generator function, end counting `yield` keywords, then
42
42
  * reports result.
43
- * @param {Node} node - A function node to check.
43
+ * @param {Node} node A function node to check.
44
44
  * @returns {void}
45
45
  */
46
46
  function endChecking(node) {
@@ -39,7 +39,7 @@ module.exports = {
39
39
 
40
40
  /**
41
41
  * Checks whitespace between rest/spread operators and their expressions
42
- * @param {ASTNode} node - The node to check
42
+ * @param {ASTNode} node The node to check
43
43
  * @returns {void}
44
44
  */
45
45
  function checkWhiteSpace(node) {
@@ -70,8 +70,7 @@ module.exports = {
70
70
  * import * as myModule from "my-module.js" --> all
71
71
  * import {myMember} from "my-module.js" --> single
72
72
  * import {foo, bar} from "my-module.js" --> multiple
73
- *
74
- * @param {ASTNode} node - the ImportDeclaration node.
73
+ * @param {ASTNode} node the ImportDeclaration node.
75
74
  * @returns {string} used member parameter style, ["all", "multiple", "single"]
76
75
  */
77
76
  function usedMemberSyntax(node) {
@@ -90,7 +89,7 @@ module.exports = {
90
89
 
91
90
  /**
92
91
  * Gets the group by member parameter index for given declaration.
93
- * @param {ASTNode} node - the ImportDeclaration node.
92
+ * @param {ASTNode} node the ImportDeclaration node.
94
93
  * @returns {number} the declaration group by member index.
95
94
  */
96
95
  function getMemberParameterGroupIndex(node) {
@@ -99,7 +98,7 @@ module.exports = {
99
98
 
100
99
  /**
101
100
  * Gets the local name of the first imported module.
102
- * @param {ASTNode} node - the ImportDeclaration node.
101
+ * @param {ASTNode} node the ImportDeclaration node.
103
102
  * @returns {?string} the local name of the first imported module.
104
103
  */
105
104
  function getFirstLocalMemberName(node) {
@@ -23,8 +23,7 @@ const astUtils = require("./utils/ast-utils"),
23
23
  * whether it's a computed property or not.
24
24
  * - If the property has a static name, this returns the static name.
25
25
  * - Otherwise, this returns null.
26
- *
27
- * @param {ASTNode} node - The `Property` node to get.
26
+ * @param {ASTNode} node The `Property` node to get.
28
27
  * @returns {string|null} The property name or null.
29
28
  * @private
30
29
  */
@@ -43,7 +42,6 @@ function getPropertyName(node) {
43
42
  *
44
43
  * Postfix `I` is meant insensitive.
45
44
  * Postfix `N` is meant natual.
46
- *
47
45
  * @private
48
46
  */
49
47
  const isValidOrders = {
@@ -79,8 +79,7 @@ module.exports = {
79
79
  /**
80
80
  * Checks whether or not a given token is an arrow operator (=>) or a keyword
81
81
  * in order to avoid to conflict with `arrow-spacing` and `keyword-spacing`.
82
- *
83
- * @param {Token} token - A token to check.
82
+ * @param {Token} token A token to check.
84
83
  * @returns {boolean} `true` if the token is an arrow operator.
85
84
  */
86
85
  function isConflicted(token) {
@@ -124,7 +124,18 @@ module.exports = {
124
124
  node,
125
125
  loc: leftToken.loc.end,
126
126
  message: "Unexpected space before function parentheses.",
127
- fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]])
127
+ fix(fixer) {
128
+ const comments = sourceCode.getCommentsBefore(rightToken);
129
+
130
+ // Don't fix anything if there's a single line comment between the left and the right token
131
+ if (comments.some(comment => comment.type === "Line")) {
132
+ return null;
133
+ }
134
+ return fixer.replaceTextRange(
135
+ [leftToken.range[1], rightToken.range[0]],
136
+ comments.reduce((text, comment) => text + sourceCode.getText(comment), "")
137
+ );
138
+ }
128
139
  });
129
140
  } else if (!hasSpacing && functionConfig === "always") {
130
141
  context.report({
@@ -40,23 +40,28 @@ module.exports = {
40
40
  },
41
41
  additionalProperties: false
42
42
  }
43
- ]
43
+ ],
44
+
45
+ messages: {
46
+ missingOpeningSpace: "There must be a space after this paren.",
47
+ missingClosingSpace: "There must be a space before this paren.",
48
+ rejectedOpeningSpace: "There should be no space after this paren.",
49
+ rejectedClosingSpace: "There should be no space before this paren."
50
+ }
44
51
  },
45
52
 
46
53
  create(context) {
47
-
48
- const MISSING_SPACE_MESSAGE = "There must be a space inside this paren.",
49
- REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.",
50
- ALWAYS = context.options[0] === "always",
54
+ const ALWAYS = context.options[0] === "always",
51
55
  exceptionsArrayOptions = (context.options[1] && context.options[1].exceptions) || [],
52
56
  options = {};
57
+
53
58
  let exceptions;
54
59
 
55
60
  if (exceptionsArrayOptions.length) {
56
- options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1;
57
- options.bracketException = exceptionsArrayOptions.indexOf("[]") !== -1;
58
- options.parenException = exceptionsArrayOptions.indexOf("()") !== -1;
59
- options.empty = exceptionsArrayOptions.indexOf("empty") !== -1;
61
+ options.braceException = exceptionsArrayOptions.includes("{}");
62
+ options.bracketException = exceptionsArrayOptions.includes("[]");
63
+ options.parenException = exceptionsArrayOptions.includes("()");
64
+ options.empty = exceptionsArrayOptions.includes("empty");
60
65
  }
61
66
 
62
67
  /**
@@ -105,7 +110,7 @@ module.exports = {
105
110
  * @returns {boolean} True if the token is one of the exceptions for the opener paren
106
111
  */
107
112
  function isOpenerException(token) {
108
- return token.type === "Punctuator" && exceptions.openers.indexOf(token.value) >= 0;
113
+ return exceptions.openers.includes(token.value);
109
114
  }
110
115
 
111
116
  /**
@@ -114,102 +119,95 @@ module.exports = {
114
119
  * @returns {boolean} True if the token is one of the exceptions for the closer paren
115
120
  */
116
121
  function isCloserException(token) {
117
- return token.type === "Punctuator" && exceptions.closers.indexOf(token.value) >= 0;
122
+ return exceptions.closers.includes(token.value);
118
123
  }
119
124
 
120
125
  /**
121
- * Determines if an opener paren should have a missing space after it
122
- * @param {Object} left The paren token
123
- * @param {Object} right The token after it
124
- * @returns {boolean} True if the paren should have a space
126
+ * Determines if an opening paren is immediately followed by a required space
127
+ * @param {Object} openingParenToken The paren token
128
+ * @param {Object} tokenAfterOpeningParen The token after it
129
+ * @returns {boolean} True if the opening paren is missing a required space
125
130
  */
126
- function shouldOpenerHaveSpace(left, right) {
127
- if (sourceCode.isSpaceBetweenTokens(left, right)) {
131
+ function openerMissingSpace(openingParenToken, tokenAfterOpeningParen) {
132
+ if (sourceCode.isSpaceBetweenTokens(openingParenToken, tokenAfterOpeningParen)) {
128
133
  return false;
129
134
  }
130
135
 
131
- if (ALWAYS) {
132
- if (astUtils.isClosingParenToken(right)) {
133
- return false;
134
- }
135
- return !isOpenerException(right);
136
+ if (!options.empty && astUtils.isClosingParenToken(tokenAfterOpeningParen)) {
137
+ return false;
136
138
  }
137
- return isOpenerException(right);
138
139
 
140
+ if (ALWAYS) {
141
+ return !isOpenerException(tokenAfterOpeningParen);
142
+ }
143
+ return isOpenerException(tokenAfterOpeningParen);
139
144
  }
140
145
 
141
146
  /**
142
- * Determines if an closer paren should have a missing space after it
143
- * @param {Object} left The token before the paren
144
- * @param {Object} right The paren token
145
- * @returns {boolean} True if the paren should have a space
147
+ * Determines if an opening paren is immediately followed by a disallowed space
148
+ * @param {Object} openingParenToken The paren token
149
+ * @param {Object} tokenAfterOpeningParen The token after it
150
+ * @returns {boolean} True if the opening paren has a disallowed space
146
151
  */
147
- function shouldCloserHaveSpace(left, right) {
148
- if (astUtils.isOpeningParenToken(left)) {
152
+ function openerRejectsSpace(openingParenToken, tokenAfterOpeningParen) {
153
+ if (!astUtils.isTokenOnSameLine(openingParenToken, tokenAfterOpeningParen)) {
149
154
  return false;
150
155
  }
151
156
 
152
- if (sourceCode.isSpaceBetweenTokens(left, right)) {
157
+ if (tokenAfterOpeningParen.type === "Line") {
153
158
  return false;
154
159
  }
155
160
 
156
- if (ALWAYS) {
157
- return !isCloserException(left);
161
+ if (!sourceCode.isSpaceBetweenTokens(openingParenToken, tokenAfterOpeningParen)) {
162
+ return false;
158
163
  }
159
- return isCloserException(left);
160
164
 
165
+ if (ALWAYS) {
166
+ return isOpenerException(tokenAfterOpeningParen);
167
+ }
168
+ return !isOpenerException(tokenAfterOpeningParen);
161
169
  }
162
170
 
163
171
  /**
164
- * Determines if an opener paren should not have an existing space after it
165
- * @param {Object} left The paren token
166
- * @param {Object} right The token after it
167
- * @returns {boolean} True if the paren should reject the space
172
+ * Determines if a closing paren is immediately preceeded by a required space
173
+ * @param {Object} tokenBeforeClosingParen The token before the paren
174
+ * @param {Object} closingParenToken The paren token
175
+ * @returns {boolean} True if the closing paren is missing a required space
168
176
  */
169
- function shouldOpenerRejectSpace(left, right) {
170
- if (right.type === "Line") {
171
- return false;
172
- }
173
-
174
- if (!astUtils.isTokenOnSameLine(left, right)) {
177
+ function closerMissingSpace(tokenBeforeClosingParen, closingParenToken) {
178
+ if (sourceCode.isSpaceBetweenTokens(tokenBeforeClosingParen, closingParenToken)) {
175
179
  return false;
176
180
  }
177
181
 
178
- if (!sourceCode.isSpaceBetweenTokens(left, right)) {
182
+ if (!options.empty && astUtils.isOpeningParenToken(tokenBeforeClosingParen)) {
179
183
  return false;
180
184
  }
181
185
 
182
186
  if (ALWAYS) {
183
- return isOpenerException(right);
187
+ return !isCloserException(tokenBeforeClosingParen);
184
188
  }
185
- return !isOpenerException(right);
186
-
189
+ return isCloserException(tokenBeforeClosingParen);
187
190
  }
188
191
 
189
192
  /**
190
- * Determines if an closer paren should not have an existing space after it
191
- * @param {Object} left The token before the paren
192
- * @param {Object} right The paren token
193
- * @returns {boolean} True if the paren should reject the space
193
+ * Determines if a closer paren is immediately preceeded by a disallowed space
194
+ * @param {Object} tokenBeforeClosingParen The token before the paren
195
+ * @param {Object} closingParenToken The paren token
196
+ * @returns {boolean} True if the closing paren has a disallowed space
194
197
  */
195
- function shouldCloserRejectSpace(left, right) {
196
- if (astUtils.isOpeningParenToken(left)) {
198
+ function closerRejectsSpace(tokenBeforeClosingParen, closingParenToken) {
199
+ if (!astUtils.isTokenOnSameLine(tokenBeforeClosingParen, closingParenToken)) {
197
200
  return false;
198
201
  }
199
202
 
200
- if (!astUtils.isTokenOnSameLine(left, right)) {
201
- return false;
202
- }
203
-
204
- if (!sourceCode.isSpaceBetweenTokens(left, right)) {
203
+ if (!sourceCode.isSpaceBetweenTokens(tokenBeforeClosingParen, closingParenToken)) {
205
204
  return false;
206
205
  }
207
206
 
208
207
  if (ALWAYS) {
209
- return isCloserException(left);
208
+ return isCloserException(tokenBeforeClosingParen);
210
209
  }
211
- return !isCloserException(left);
212
-
210
+ return !isCloserException(tokenBeforeClosingParen);
213
211
  }
214
212
 
215
213
  //--------------------------------------------------------------------------
@@ -225,44 +223,53 @@ module.exports = {
225
223
  const prevToken = tokens[i - 1];
226
224
  const nextToken = tokens[i + 1];
227
225
 
226
+ // if token is not an opening or closing paren token, do nothing
228
227
  if (!astUtils.isOpeningParenToken(token) && !astUtils.isClosingParenToken(token)) {
229
228
  return;
230
229
  }
231
230
 
232
- if (token.value === "(" && shouldOpenerHaveSpace(token, nextToken)) {
231
+ // if token is an opening paren and is not followed by a required space
232
+ if (token.value === "(" && openerMissingSpace(token, nextToken)) {
233
233
  context.report({
234
234
  node,
235
- loc: token.loc.start,
236
- message: MISSING_SPACE_MESSAGE,
235
+ loc: token.loc,
236
+ messageId: "missingOpeningSpace",
237
237
  fix(fixer) {
238
238
  return fixer.insertTextAfter(token, " ");
239
239
  }
240
240
  });
241
- } else if (token.value === "(" && shouldOpenerRejectSpace(token, nextToken)) {
241
+ }
242
+
243
+ // if token is an opening paren and is followed by a disallowed space
244
+ if (token.value === "(" && openerRejectsSpace(token, nextToken)) {
242
245
  context.report({
243
246
  node,
244
- loc: token.loc.start,
245
- message: REJECTED_SPACE_MESSAGE,
247
+ loc: { start: token.loc.end, end: nextToken.loc.start },
248
+ messageId: "rejectedOpeningSpace",
246
249
  fix(fixer) {
247
250
  return fixer.removeRange([token.range[1], nextToken.range[0]]);
248
251
  }
249
252
  });
250
- } else if (token.value === ")" && shouldCloserHaveSpace(prevToken, token)) {
253
+ }
251
254
 
252
- // context.report(node, token.loc.start, MISSING_SPACE_MESSAGE);
255
+ // if token is a closing paren and is not preceded by a required space
256
+ if (token.value === ")" && closerMissingSpace(prevToken, token)) {
253
257
  context.report({
254
258
  node,
255
- loc: token.loc.start,
256
- message: MISSING_SPACE_MESSAGE,
259
+ loc: token.loc,
260
+ messageId: "missingClosingSpace",
257
261
  fix(fixer) {
258
262
  return fixer.insertTextBefore(token, " ");
259
263
  }
260
264
  });
261
- } else if (token.value === ")" && shouldCloserRejectSpace(prevToken, token)) {
265
+ }
266
+
267
+ // if token is a closing paren and is preceded by a disallowed space
268
+ if (token.value === ")" && closerRejectsSpace(prevToken, token)) {
262
269
  context.report({
263
270
  node,
264
- loc: token.loc.start,
265
- message: REJECTED_SPACE_MESSAGE,
271
+ loc: { start: prevToken.loc.end, end: token.loc.start },
272
+ messageId: "rejectedClosingSpace",
266
273
  fix(fixer) {
267
274
  return fixer.removeRange([prevToken.range[1], token.range[0]]);
268
275
  }
@@ -271,6 +278,5 @@ module.exports = {
271
278
  });
272
279
  }
273
280
  };
274
-
275
281
  }
276
282
  };
@@ -41,9 +41,9 @@ module.exports = {
41
41
 
42
42
  /**
43
43
  * Returns the first token which violates the rule
44
- * @param {ASTNode} left - The left node of the main node
45
- * @param {ASTNode} right - The right node of the main node
46
- * @param {string} op - The operator of the main node
44
+ * @param {ASTNode} left The left node of the main node
45
+ * @param {ASTNode} right The right node of the main node
46
+ * @param {string} op The operator of the main node
47
47
  * @returns {Object} The violator token or null
48
48
  * @private
49
49
  */
@@ -61,8 +61,8 @@ module.exports = {
61
61
 
62
62
  /**
63
63
  * Reports an AST node as a rule violation
64
- * @param {ASTNode} mainNode - The node to report
65
- * @param {Object} culpritToken - The token which has a problem
64
+ * @param {ASTNode} mainNode The node to report
65
+ * @param {Object} culpritToken The token which has a problem
66
66
  * @returns {void}
67
67
  * @private
68
68
  */