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
@@ -36,7 +36,8 @@ module.exports = {
36
36
  },
37
37
 
38
38
  create(context) {
39
- const options = context.options[0] || {},
39
+ const sourceCode = context.getSourceCode(),
40
+ options = context.options[0] || {},
40
41
  ignoreDestructuring = options.ignoreDestructuring === true,
41
42
  ignoreImport = options.ignoreImport === true,
42
43
  ignoreExport = options.ignoreExport === true;
@@ -47,10 +48,10 @@ module.exports = {
47
48
 
48
49
  /**
49
50
  * Reports error for unnecessarily renamed assignments
50
- * @param {ASTNode} node - node to report
51
- * @param {ASTNode} initial - node with initial name value
52
- * @param {ASTNode} result - node with new name value
53
- * @param {string} type - the type of the offending node
51
+ * @param {ASTNode} node node to report
52
+ * @param {ASTNode} initial node with initial name value
53
+ * @param {ASTNode} result node with new name value
54
+ * @param {string} type the type of the offending node
54
55
  * @returns {void}
55
56
  */
56
57
  function reportError(node, initial, result, type) {
@@ -64,17 +65,25 @@ module.exports = {
64
65
  type
65
66
  },
66
67
  fix(fixer) {
68
+ if (sourceCode.commentsExistBetween(initial, result)) {
69
+ return null;
70
+ }
71
+
72
+ const replacementText = result.type === "AssignmentPattern"
73
+ ? sourceCode.getText(result)
74
+ : name;
75
+
67
76
  return fixer.replaceTextRange([
68
77
  initial.range[0],
69
78
  result.range[1]
70
- ], name);
79
+ ], replacementText);
71
80
  }
72
81
  });
73
82
  }
74
83
 
75
84
  /**
76
85
  * Checks whether a destructured assignment is unnecessarily renamed
77
- * @param {ASTNode} node - node to check
86
+ * @param {ASTNode} node node to check
78
87
  * @returns {void}
79
88
  */
80
89
  function checkDestructured(node) {
@@ -82,33 +91,36 @@ module.exports = {
82
91
  return;
83
92
  }
84
93
 
85
- const properties = node.properties;
94
+ for (const property of node.properties) {
86
95
 
87
- for (let i = 0; i < properties.length; i++) {
88
- if (properties[i].shorthand) {
96
+ /*
97
+ * TODO: Remove after babel-eslint removes ExperimentalRestProperty
98
+ * https://github.com/eslint/eslint/issues/12335
99
+ */
100
+ if (property.type === "ExperimentalRestProperty") {
89
101
  continue;
90
102
  }
91
103
 
92
104
  /**
93
- * If an ObjectPattern property is computed, we have no idea
94
- * if a rename is useless or not. If an ObjectPattern property
95
- * lacks a key, it is likely an ExperimentalRestProperty and
96
- * so there is no "renaming" occurring here.
105
+ * Properties using shorthand syntax and rest elements can not be renamed.
106
+ * If the property is computed, we have no idea if a rename is useless or not.
97
107
  */
98
- if (properties[i].computed || !properties[i].key) {
108
+ if (property.shorthand || property.type === "RestElement" || property.computed) {
99
109
  continue;
100
110
  }
101
111
 
102
- if (properties[i].key.type === "Identifier" && properties[i].key.name === properties[i].value.name ||
103
- properties[i].key.type === "Literal" && properties[i].key.value === properties[i].value.name) {
104
- reportError(properties[i], properties[i].key, properties[i].value, "Destructuring assignment");
112
+ const key = (property.key.type === "Identifier" && property.key.name) || (property.key.type === "Literal" && property.key.value);
113
+ const renamedKey = property.value.type === "AssignmentPattern" ? property.value.left.name : property.value.name;
114
+
115
+ if (key === renamedKey) {
116
+ reportError(property, property.key, property.value, "Destructuring assignment");
105
117
  }
106
118
  }
107
119
  }
108
120
 
109
121
  /**
110
122
  * Checks whether an import is unnecessarily renamed
111
- * @param {ASTNode} node - node to check
123
+ * @param {ASTNode} node node to check
112
124
  * @returns {void}
113
125
  */
114
126
  function checkImport(node) {
@@ -124,7 +136,7 @@ module.exports = {
124
136
 
125
137
  /**
126
138
  * Checks whether an export is unnecessarily renamed
127
- * @param {ASTNode} node - node to check
139
+ * @param {ASTNode} node node to check
128
140
  * @returns {void}
129
141
  */
130
142
  function checkExport(node) {
@@ -17,9 +17,8 @@ const astUtils = require("./utils/ast-utils"),
17
17
 
18
18
  /**
19
19
  * Removes the given element from the array.
20
- *
21
- * @param {Array} array - The source array to remove.
22
- * @param {any} element - The target item to remove.
20
+ * @param {Array} array The source array to remove.
21
+ * @param {any} element The target item to remove.
23
22
  * @returns {void}
24
23
  */
25
24
  function remove(array, element) {
@@ -32,8 +31,7 @@ function remove(array, element) {
32
31
 
33
32
  /**
34
33
  * Checks whether it can remove the given return statement or not.
35
- *
36
- * @param {ASTNode} node - The return statement node to check.
34
+ * @param {ASTNode} node The return statement node to check.
37
35
  * @returns {boolean} `true` if the node is removeable.
38
36
  */
39
37
  function isRemovable(node) {
@@ -42,8 +40,7 @@ function isRemovable(node) {
42
40
 
43
41
  /**
44
42
  * Checks whether the given return statement is in a `finally` block or not.
45
- *
46
- * @param {ASTNode} node - The return statement node to check.
43
+ * @param {ASTNode} node The return statement node to check.
47
44
  * @returns {boolean} `true` if the node is in a `finally` block.
48
45
  */
49
46
  function isInFinally(node) {
@@ -82,12 +79,12 @@ module.exports = {
82
79
  create(context) {
83
80
  const segmentInfoMap = new WeakMap();
84
81
  const usedUnreachableSegments = new WeakSet();
82
+ const sourceCode = context.getSourceCode();
85
83
  let scopeInfo = null;
86
84
 
87
85
  /**
88
86
  * Checks whether the given segment is terminated by a return statement or not.
89
- *
90
- * @param {CodePathSegment} segment - The segment to check.
87
+ * @param {CodePathSegment} segment The segment to check.
91
88
  * @returns {boolean} `true` if the segment is terminated by a return statement, or if it's still a part of unreachable.
92
89
  */
93
90
  function isReturned(segment) {
@@ -109,9 +106,8 @@ module.exports = {
109
106
  *
110
107
  * This behavior would simulate code paths for the case that the return
111
108
  * statement does not exist.
112
- *
113
- * @param {ASTNode[]} uselessReturns - The collected return statements.
114
- * @param {CodePathSegment[]} prevSegments - The previous segments to traverse.
109
+ * @param {ASTNode[]} uselessReturns The collected return statements.
110
+ * @param {CodePathSegment[]} prevSegments The previous segments to traverse.
115
111
  * @param {WeakSet<CodePathSegment>} [providedTraversedSegments] A set of segments that have already been traversed in this call
116
112
  * @returns {ASTNode[]} `uselessReturns`.
117
113
  */
@@ -151,8 +147,7 @@ module.exports = {
151
147
  *
152
148
  * This behavior would simulate code paths for the case that the return
153
149
  * statement does not exist.
154
- *
155
- * @param {CodePathSegment} segment - The segment to get return statements.
150
+ * @param {CodePathSegment} segment The segment to get return statements.
156
151
  * @returns {void}
157
152
  */
158
153
  function markReturnStatementsOnSegmentAsUsed(segment) {
@@ -183,7 +178,6 @@ module.exports = {
183
178
  * - FunctionDeclarations are always executed whether it's returned or not.
184
179
  * - BlockStatements do nothing.
185
180
  * - BreakStatements go the next merely.
186
- *
187
181
  * @returns {void}
188
182
  */
189
183
  function markReturnStatementsOnCurrentSegmentsAsUsed() {
@@ -216,7 +210,7 @@ module.exports = {
216
210
  loc: node.loc,
217
211
  message: "Unnecessary return statement.",
218
212
  fix(fixer) {
219
- if (isRemovable(node)) {
213
+ if (isRemovable(node) && !sourceCode.getCommentsInside(node).length) {
220
214
 
221
215
  /*
222
216
  * Extend the replacement range to include the
@@ -224,7 +218,7 @@ module.exports = {
224
218
  * no-else-return.
225
219
  * https://github.com/eslint/eslint/issues/8026
226
220
  */
227
- return new FixTracker(fixer, context.getSourceCode())
221
+ return new FixTracker(fixer, sourceCode)
228
222
  .retainEnclosingFunction(node)
229
223
  .remove(node);
230
224
  }
@@ -27,8 +27,7 @@ function isGlobal(variable) {
27
27
  /**
28
28
  * Finds the nearest function scope or global scope walking up the scope
29
29
  * hierarchy.
30
- *
31
- * @param {eslint-scope.Scope} scope - The scope to traverse.
30
+ * @param {eslint-scope.Scope} scope The scope to traverse.
32
31
  * @returns {eslint-scope.Scope} a function scope or global scope containing the given
33
32
  * scope.
34
33
  */
@@ -44,8 +43,7 @@ function getEnclosingFunctionScope(scope) {
44
43
  /**
45
44
  * Checks whether the given variable has any references from a more specific
46
45
  * function expression (i.e. a closure).
47
- *
48
- * @param {eslint-scope.Variable} variable - A variable to check.
46
+ * @param {eslint-scope.Variable} variable A variable to check.
49
47
  * @returns {boolean} `true` if the variable is used from a closure.
50
48
  */
51
49
  function isReferencedInClosure(variable) {
@@ -57,8 +55,7 @@ function isReferencedInClosure(variable) {
57
55
 
58
56
  /**
59
57
  * Checks whether the given node is the assignee of a loop.
60
- *
61
- * @param {ASTNode} node - A VariableDeclaration node to check.
58
+ * @param {ASTNode} node A VariableDeclaration node to check.
62
59
  * @returns {boolean} `true` if the declaration is assigned as part of loop
63
60
  * iteration.
64
61
  */
@@ -69,8 +66,7 @@ function isLoopAssignee(node) {
69
66
 
70
67
  /**
71
68
  * Checks whether the given variable declaration is immediately initialized.
72
- *
73
- * @param {ASTNode} node - A VariableDeclaration node to check.
69
+ * @param {ASTNode} node A VariableDeclaration node to check.
74
70
  * @returns {boolean} `true` if the declaration has an initializer.
75
71
  */
76
72
  function isDeclarationInitialized(node) {
@@ -81,8 +77,7 @@ const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement
81
77
 
82
78
  /**
83
79
  * Gets the scope node which directly contains a given node.
84
- *
85
- * @param {ASTNode} node - A node to get. This is a `VariableDeclaration` or
80
+ * @param {ASTNode} node A node to get. This is a `VariableDeclaration` or
86
81
  * an `Identifier`.
87
82
  * @returns {ASTNode} A scope node. This is one of `Program`, `BlockStatement`,
88
83
  * `SwitchStatement`, `ForStatement`, `ForInStatement`, and
@@ -101,8 +96,7 @@ function getScopeNode(node) {
101
96
 
102
97
  /**
103
98
  * Checks whether a given variable is redeclared or not.
104
- *
105
- * @param {eslint-scope.Variable} variable - A variable to check.
99
+ * @param {eslint-scope.Variable} variable A variable to check.
106
100
  * @returns {boolean} `true` if the variable is redeclared.
107
101
  */
108
102
  function isRedeclared(variable) {
@@ -111,8 +105,7 @@ function isRedeclared(variable) {
111
105
 
112
106
  /**
113
107
  * Checks whether a given variable is used from outside of the specified scope.
114
- *
115
- * @param {ASTNode} scopeNode - A scope node to check.
108
+ * @param {ASTNode} scopeNode A scope node to check.
116
109
  * @returns {Function} The predicate function which checks whether a given
117
110
  * variable is used from outside of the specified scope.
118
111
  */
@@ -120,8 +113,7 @@ function isUsedFromOutsideOf(scopeNode) {
120
113
 
121
114
  /**
122
115
  * Checks whether a given reference is inside of the specified scope or not.
123
- *
124
- * @param {eslint-scope.Reference} reference - A reference to check.
116
+ * @param {eslint-scope.Reference} reference A reference to check.
125
117
  * @returns {boolean} `true` if the reference is inside of the specified
126
118
  * scope.
127
119
  */
@@ -145,8 +137,7 @@ function isUsedFromOutsideOf(scopeNode) {
145
137
  * - if a reference is before the declarator. E.g. (var a = b, b = 1;)(var {a = b, b} = {};)
146
138
  * - if a reference is in the expression of their default value. E.g. (var {a = a} = {};)
147
139
  * - if a reference is in the expression of their initializer. E.g. (var a = a;)
148
- *
149
- * @param {ASTNode} node - The initializer node of VariableDeclarator.
140
+ * @param {ASTNode} node The initializer node of VariableDeclarator.
150
141
  * @returns {Function} The predicate function.
151
142
  * @private
152
143
  */
@@ -177,7 +168,6 @@ function hasReferenceInTDZ(node) {
177
168
  /**
178
169
  * Checks whether a given variable has name that is allowed for 'var' declarations,
179
170
  * but disallowed for `let` declarations.
180
- *
181
171
  * @param {eslint-scope.Variable} variable The variable to check.
182
172
  * @returns {boolean} `true` if the variable has a disallowed name.
183
173
  */
@@ -209,8 +199,7 @@ module.exports = {
209
199
 
210
200
  /**
211
201
  * Checks whether the variables which are defined by the given declarator node have their references in TDZ.
212
- *
213
- * @param {ASTNode} declarator - The VariableDeclarator node to check.
202
+ * @param {ASTNode} declarator The VariableDeclarator node to check.
214
203
  * @returns {boolean} `true` if one of the variables which are defined by the given declarator node have their references in TDZ.
215
204
  */
216
205
  function hasSelfReferenceInTDZ(declarator) {
@@ -271,8 +260,7 @@ module.exports = {
271
260
  * the implementation simple, we only convert `var` to `let` within
272
261
  * loops when the variable is a loop assignee or the declaration has an
273
262
  * initializer.
274
- *
275
- * @param {ASTNode} node - A variable declaration node to check.
263
+ * @param {ASTNode} node A variable declaration node to check.
276
264
  * @returns {boolean} `true` if it can fix the node.
277
265
  */
278
266
  function canFix(node) {
@@ -313,8 +301,7 @@ module.exports = {
313
301
 
314
302
  /**
315
303
  * Reports a given variable declaration node.
316
- *
317
- * @param {ASTNode} node - A variable declaration node to report.
304
+ * @param {ASTNode} node A variable declaration node to report.
318
305
  * @returns {void}
319
306
  */
320
307
  function report(node) {
@@ -54,7 +54,6 @@ module.exports = {
54
54
  * Convert a warning term into a RegExp which will match a comment containing that whole word in the specified
55
55
  * location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not
56
56
  * require word boundaries on that side.
57
- *
58
57
  * @param {string} term A term to convert to a RegExp
59
58
  * @returns {RegExp} The term converted to a RegExp
60
59
  */
@@ -38,9 +38,9 @@ module.exports = {
38
38
 
39
39
  /**
40
40
  * Reports whitespace before property token
41
- * @param {ASTNode} node - the node to report in the event of an error
42
- * @param {Token} leftToken - the left token
43
- * @param {Token} rightToken - the right token
41
+ * @param {ASTNode} node the node to report in the event of an error
42
+ * @param {Token} leftToken the left token
43
+ * @param {Token} rightToken the right token
44
44
  * @returns {void}
45
45
  * @private
46
46
  */
@@ -44,8 +44,7 @@ const OPTION_VALUE = {
44
44
 
45
45
  /**
46
46
  * Normalizes a given option value.
47
- *
48
- * @param {string|Object|undefined} value - An option value to parse.
47
+ * @param {string|Object|undefined} value An option value to parse.
49
48
  * @returns {{multiline: boolean, minProperties: number, consistent: boolean}} Normalized option object.
50
49
  */
51
50
  function normalizeOptionValue(value) {
@@ -72,8 +71,7 @@ function normalizeOptionValue(value) {
72
71
 
73
72
  /**
74
73
  * Normalizes a given option value.
75
- *
76
- * @param {string|Object|undefined} options - An option value to parse.
74
+ * @param {string|Object|undefined} options An option value to parse.
77
75
  * @returns {{
78
76
  * ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
79
77
  * ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
@@ -101,11 +99,10 @@ function normalizeOptions(options) {
101
99
  /**
102
100
  * Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
103
101
  * node needs to be checked for missing line breaks
104
- *
105
- * @param {ASTNode} node - Node under inspection
106
- * @param {Object} options - option specific to node type
107
- * @param {Token} first - First object property
108
- * @param {Token} last - Last object property
102
+ * @param {ASTNode} node Node under inspection
103
+ * @param {Object} options option specific to node type
104
+ * @param {Token} first First object property
105
+ * @param {Token} last Last object property
109
106
  * @returns {boolean} `true` if node needs to be checked for missing line breaks
110
107
  */
111
108
  function areLineBreaksRequired(node, options, first, last) {
@@ -171,7 +168,7 @@ module.exports = {
171
168
 
172
169
  /**
173
170
  * Reports a given node if it violated this rule.
174
- * @param {ASTNode} node - A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
171
+ * @param {ASTNode} node A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
175
172
  * @returns {void}
176
173
  */
177
174
  function check(node) {
@@ -50,7 +50,7 @@ module.exports = {
50
50
  * Determines whether an option is set, relative to the spacing option.
51
51
  * If spaced is "always", then check whether option is set to false.
52
52
  * If spaced is "never", then check whether option is set to true.
53
- * @param {Object} option - The option to exclude.
53
+ * @param {Object} option The option to exclude.
54
54
  * @returns {boolean} Whether or not the property is excluded.
55
55
  */
56
56
  function isOptionSet(option) {
@@ -69,8 +69,8 @@ module.exports = {
69
69
 
70
70
  /**
71
71
  * Reports that there shouldn't be a space after the first token
72
- * @param {ASTNode} node - The node to report in the event of an error.
73
- * @param {Token} token - The token to use for the report.
72
+ * @param {ASTNode} node The node to report in the event of an error.
73
+ * @param {Token} token The token to use for the report.
74
74
  * @returns {void}
75
75
  */
76
76
  function reportNoBeginningSpace(node, token) {
@@ -91,8 +91,8 @@ module.exports = {
91
91
 
92
92
  /**
93
93
  * Reports that there shouldn't be a space before the last token
94
- * @param {ASTNode} node - The node to report in the event of an error.
95
- * @param {Token} token - The token to use for the report.
94
+ * @param {ASTNode} node The node to report in the event of an error.
95
+ * @param {Token} token The token to use for the report.
96
96
  * @returns {void}
97
97
  */
98
98
  function reportNoEndingSpace(node, token) {
@@ -113,8 +113,8 @@ module.exports = {
113
113
 
114
114
  /**
115
115
  * Reports that there should be a space after the first token
116
- * @param {ASTNode} node - The node to report in the event of an error.
117
- * @param {Token} token - The token to use for the report.
116
+ * @param {ASTNode} node The node to report in the event of an error.
117
+ * @param {Token} token The token to use for the report.
118
118
  * @returns {void}
119
119
  */
120
120
  function reportRequiredBeginningSpace(node, token) {
@@ -133,8 +133,8 @@ module.exports = {
133
133
 
134
134
  /**
135
135
  * Reports that there should be a space before the last token
136
- * @param {ASTNode} node - The node to report in the event of an error.
137
- * @param {Token} token - The token to use for the report.
136
+ * @param {ASTNode} node The node to report in the event of an error.
137
+ * @param {Token} token The token to use for the report.
138
138
  * @returns {void}
139
139
  */
140
140
  function reportRequiredEndingSpace(node, token) {
@@ -167,7 +167,7 @@ module.exports = {
167
167
  if (options.spaced && !firstSpaced) {
168
168
  reportRequiredBeginningSpace(node, first);
169
169
  }
170
- if (!options.spaced && firstSpaced) {
170
+ if (!options.spaced && firstSpaced && second.type !== "Line") {
171
171
  reportNoBeginningSpace(node, first);
172
172
  }
173
173
  }
@@ -201,8 +201,7 @@ module.exports = {
201
201
  * Because the last token of object patterns might be a type annotation,
202
202
  * this traverses tokens preceded by the last property, then returns the
203
203
  * first '}' token.
204
- *
205
- * @param {ASTNode} node - The node to get. This node is an
204
+ * @param {ASTNode} node The node to get. This node is an
206
205
  * ObjectExpression or an ObjectPattern. And this node has one or
207
206
  * more properties.
208
207
  * @returns {Token} '}' token.
@@ -215,7 +214,7 @@ module.exports = {
215
214
 
216
215
  /**
217
216
  * Reports a given object node if spacing in curly braces is invalid.
218
- * @param {ASTNode} node - An ObjectExpression or ObjectPattern node to check.
217
+ * @param {ASTNode} node An ObjectExpression or ObjectPattern node to check.
219
218
  * @returns {void}
220
219
  */
221
220
  function checkForObject(node) {
@@ -233,7 +232,7 @@ module.exports = {
233
232
 
234
233
  /**
235
234
  * Reports a given import node if spacing in curly braces is invalid.
236
- * @param {ASTNode} node - An ImportDeclaration node to check.
235
+ * @param {ASTNode} node An ImportDeclaration node to check.
237
236
  * @returns {void}
238
237
  */
239
238
  function checkForImport(node) {
@@ -261,7 +260,7 @@ module.exports = {
261
260
 
262
261
  /**
263
262
  * Reports a given export node if spacing in curly braces is invalid.
264
- * @param {ASTNode} node - An ExportNamedDeclaration node to check.
263
+ * @param {ASTNode} node An ExportNamedDeclaration node to check.
265
264
  * @returns {void}
266
265
  */
267
266
  function checkForExport(node) {
@@ -147,7 +147,7 @@ module.exports = {
147
147
 
148
148
  /**
149
149
  * Checks whether a node is a string literal.
150
- * @param {ASTNode} node - Any AST node.
150
+ * @param {ASTNode} node Any AST node.
151
151
  * @returns {boolean} `true` if it is a string literal.
152
152
  */
153
153
  function isStringLiteral(node) {
@@ -244,6 +244,7 @@ module.exports = {
244
244
  const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
245
245
  let keyPrefix = "";
246
246
 
247
+ // key: /* */ () => {}
247
248
  if (sourceCode.commentsExistBetween(lastKeyToken, node.value)) {
248
249
  return null;
249
250
  }
@@ -255,24 +256,49 @@ module.exports = {
255
256
  keyPrefix += "*";
256
257
  }
257
258
 
259
+ const fixRange = [firstKeyToken.range[0], node.range[1]];
260
+ const methodPrefix = keyPrefix + keyText;
261
+
258
262
  if (node.value.type === "FunctionExpression") {
259
263
  const functionToken = sourceCode.getTokens(node.value).find(token => token.type === "Keyword" && token.value === "function");
260
264
  const tokenBeforeParams = node.value.generator ? sourceCode.getTokenAfter(functionToken) : functionToken;
261
265
 
262
266
  return fixer.replaceTextRange(
263
- [firstKeyToken.range[0], node.range[1]],
264
- keyPrefix + keyText + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1])
267
+ fixRange,
268
+ methodPrefix + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1])
265
269
  );
266
270
  }
267
- const arrowToken = sourceCode.getTokenBefore(node.value.body, { filter: token => token.value === "=>" });
268
- const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken);
269
- const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")";
270
- const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]);
271
- const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`;
271
+
272
+ const arrowToken = sourceCode.getTokenBefore(node.value.body, astUtils.isArrowToken);
273
+ const fnBody = sourceCode.text.slice(arrowToken.range[1], node.value.range[1]);
274
+
275
+ let shouldAddParensAroundParameters = false;
276
+ let tokenBeforeParams;
277
+
278
+ if (node.value.params.length === 0) {
279
+ tokenBeforeParams = sourceCode.getFirstToken(node.value, astUtils.isOpeningParenToken);
280
+ } else {
281
+ tokenBeforeParams = sourceCode.getTokenBefore(node.value.params[0]);
282
+ }
283
+
284
+ if (node.value.params.length === 1) {
285
+ const hasParen = astUtils.isOpeningParenToken(tokenBeforeParams);
286
+ const isTokenOutsideNode = tokenBeforeParams.range[0] < node.range[0];
287
+
288
+ shouldAddParensAroundParameters = !hasParen || isTokenOutsideNode;
289
+ }
290
+
291
+ const sliceStart = shouldAddParensAroundParameters
292
+ ? node.value.params[0].range[0]
293
+ : tokenBeforeParams.range[0];
294
+ const sliceEnd = sourceCode.getTokenBefore(arrowToken).range[1];
295
+
296
+ const oldParamText = sourceCode.text.slice(sliceStart, sliceEnd);
297
+ const newParamText = shouldAddParensAroundParameters ? `(${oldParamText})` : oldParamText;
272
298
 
273
299
  return fixer.replaceTextRange(
274
- [firstKeyToken.range[0], node.range[1]],
275
- keyPrefix + keyText + newParamText + sourceCode.text.slice(arrowToken.range[1], node.value.range[1])
300
+ fixRange,
301
+ methodPrefix + newParamText + fnBody
276
302
  );
277
303
 
278
304
  }
@@ -41,7 +41,7 @@ module.exports = {
41
41
  /**
42
42
  * Determine if provided keyword is a variant of for specifiers
43
43
  * @private
44
- * @param {string} keyword - keyword to test
44
+ * @param {string} keyword keyword to test
45
45
  * @returns {boolean} True if `keyword` is a variant of for specifier
46
46
  */
47
47
  function isForTypeSpecifier(keyword) {
@@ -51,7 +51,7 @@ module.exports = {
51
51
  /**
52
52
  * Checks newlines around variable declarations.
53
53
  * @private
54
- * @param {ASTNode} node - `VariableDeclaration` node to test
54
+ * @param {ASTNode} node `VariableDeclaration` node to test
55
55
  * @returns {void}
56
56
  */
57
57
  function checkForNewLine(node) {
@@ -150,6 +150,11 @@ module.exports = {
150
150
  const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]);
151
151
  const rightText = sourceCode.getText().slice(operatorToken.range[1], node.right.range[1]);
152
152
 
153
+ // Check for comments that would be removed.
154
+ if (sourceCode.commentsExistBetween(equalsToken, operatorToken)) {
155
+ return null;
156
+ }
157
+
153
158
  return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`);
154
159
  }
155
160
  return null;
@@ -182,11 +187,17 @@ module.exports = {
182
187
  messageId: "unexpected",
183
188
  fix(fixer) {
184
189
  if (canBeFixed(node.left)) {
190
+ const firstToken = sourceCode.getFirstToken(node);
185
191
  const operatorToken = getOperatorToken(node);
186
192
  const leftText = sourceCode.getText().slice(node.range[0], operatorToken.range[0]);
187
193
  const newOperator = node.operator.slice(0, -1);
188
194
  let rightText;
189
195
 
196
+ // Check for comments that would be duplicated.
197
+ if (sourceCode.commentsExistBetween(firstToken, operatorToken)) {
198
+ return null;
199
+ }
200
+
190
201
  // If this change would modify precedence (e.g. `foo *= bar + 1` => `foo = foo * (bar + 1)`), parenthesize the right side.
191
202
  if (
192
203
  astUtils.getPrecedence(node.right) <= astUtils.getPrecedence({ type: "BinaryExpression", operator: newOperator }) &&
@@ -194,7 +205,17 @@ module.exports = {
194
205
  ) {
195
206
  rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`;
196
207
  } else {
197
- rightText = sourceCode.text.slice(operatorToken.range[1], node.range[1]);
208
+ const firstRightToken = sourceCode.getFirstToken(node.right);
209
+ let rightTextPrefix = "";
210
+
211
+ if (
212
+ operatorToken.range[1] === firstRightToken.range[0] &&
213
+ !astUtils.canTokensBeAdjacent(newOperator, firstRightToken)
214
+ ) {
215
+ rightTextPrefix = " "; // foo+=+bar -> foo= foo+ +bar
216
+ }
217
+
218
+ rightText = `${rightTextPrefix}${sourceCode.text.slice(operatorToken.range[1], node.range[1])}`;
198
219
  }
199
220
 
200
221
  return fixer.replaceText(node, `${leftText}= ${leftText}${newOperator}${rightText}`);
@@ -97,7 +97,7 @@ module.exports = {
97
97
 
98
98
  /**
99
99
  * Gets the open brace token from a given node.
100
- * @param {ASTNode} node - A BlockStatement or SwitchStatement node from which to get the open brace.
100
+ * @param {ASTNode} node A BlockStatement or SwitchStatement node from which to get the open brace.
101
101
  * @returns {Token} The token of the open brace.
102
102
  */
103
103
  function getOpenBrace(node) {