eslint 6.5.0 → 6.7.1

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 (196) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +10 -9
  3. package/conf/config-schema.js +1 -0
  4. package/conf/default-cli-options.js +1 -1
  5. package/lib/cli-engine/cascading-config-array-factory.js +40 -14
  6. package/lib/cli-engine/cli-engine.js +49 -21
  7. package/lib/cli-engine/config-array/config-array.js +13 -4
  8. package/lib/cli-engine/config-array/config-dependency.js +2 -0
  9. package/lib/cli-engine/config-array/extracted-config.js +27 -0
  10. package/lib/cli-engine/config-array/ignore-pattern.js +231 -0
  11. package/lib/cli-engine/config-array/index.js +2 -0
  12. package/lib/cli-engine/config-array/override-tester.js +2 -0
  13. package/lib/cli-engine/config-array-factory.js +120 -2
  14. package/lib/cli-engine/file-enumerator.js +51 -30
  15. package/lib/cli-engine/formatters/html.js +1 -0
  16. package/lib/init/autoconfig.js +1 -11
  17. package/lib/init/config-file.js +0 -1
  18. package/lib/init/config-initializer.js +4 -4
  19. package/lib/init/config-rule.js +1 -5
  20. package/lib/init/npm-utils.js +0 -5
  21. package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
  22. package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
  23. package/lib/linter/code-path-analysis/code-path-state.js +40 -81
  24. package/lib/linter/code-path-analysis/code-path.js +10 -11
  25. package/lib/linter/code-path-analysis/debug-helpers.js +8 -12
  26. package/lib/linter/code-path-analysis/fork-context.js +23 -34
  27. package/lib/linter/code-path-analysis/id-generator.js +2 -2
  28. package/lib/linter/linter.js +121 -95
  29. package/lib/linter/node-event-generator.js +3 -2
  30. package/lib/linter/report-translator.js +73 -7
  31. package/lib/rule-tester/rule-tester.js +46 -14
  32. package/lib/rules/accessor-pairs.js +8 -8
  33. package/lib/rules/array-bracket-newline.js +12 -15
  34. package/lib/rules/array-bracket-spacing.js +12 -12
  35. package/lib/rules/array-callback-return.js +6 -11
  36. package/lib/rules/array-element-newline.js +5 -8
  37. package/lib/rules/arrow-parens.js +0 -1
  38. package/lib/rules/block-scoped-var.js +3 -3
  39. package/lib/rules/block-spacing.js +4 -4
  40. package/lib/rules/camelcase.js +19 -6
  41. package/lib/rules/capitalized-comments.js +0 -7
  42. package/lib/rules/class-methods-use-this.js +3 -3
  43. package/lib/rules/comma-dangle.js +20 -25
  44. package/lib/rules/comma-spacing.js +1 -1
  45. package/lib/rules/computed-property-spacing.js +14 -14
  46. package/lib/rules/consistent-return.js +4 -5
  47. package/lib/rules/consistent-this.js +5 -5
  48. package/lib/rules/constructor-super.js +14 -16
  49. package/lib/rules/curly.js +12 -9
  50. package/lib/rules/default-param-last.js +1 -0
  51. package/lib/rules/dot-location.js +11 -12
  52. package/lib/rules/func-names.js +6 -6
  53. package/lib/rules/function-call-argument-newline.js +8 -6
  54. package/lib/rules/generator-star-spacing.js +4 -9
  55. package/lib/rules/getter-return.js +4 -7
  56. package/lib/rules/grouped-accessor-pairs.js +224 -0
  57. package/lib/rules/indent.js +13 -2
  58. package/lib/rules/index.js +5 -0
  59. package/lib/rules/init-declarations.js +2 -2
  60. package/lib/rules/jsx-quotes.js +1 -1
  61. package/lib/rules/keyword-spacing.js +32 -56
  62. package/lib/rules/lines-around-directive.js +1 -1
  63. package/lib/rules/max-len.js +0 -5
  64. package/lib/rules/max-statements-per-line.js +3 -7
  65. package/lib/rules/multiline-comment-style.js +237 -106
  66. package/lib/rules/multiline-ternary.js +3 -3
  67. package/lib/rules/newline-after-var.js +6 -7
  68. package/lib/rules/newline-before-return.js +8 -9
  69. package/lib/rules/newline-per-chained-call.js +2 -4
  70. package/lib/rules/no-class-assign.js +2 -2
  71. package/lib/rules/no-compare-neg-zero.js +1 -2
  72. package/lib/rules/no-cond-assign.js +14 -4
  73. package/lib/rules/no-confusing-arrow.js +2 -2
  74. package/lib/rules/no-console.js +4 -8
  75. package/lib/rules/no-const-assign.js +1 -1
  76. package/lib/rules/no-constructor-return.js +62 -0
  77. package/lib/rules/no-dupe-args.js +1 -1
  78. package/lib/rules/no-dupe-class-members.js +3 -4
  79. package/lib/rules/no-dupe-else-if.js +122 -0
  80. package/lib/rules/no-dupe-keys.js +6 -5
  81. package/lib/rules/no-duplicate-imports.js +14 -18
  82. package/lib/rules/no-else-return.js +0 -8
  83. package/lib/rules/no-empty-function.js +2 -4
  84. package/lib/rules/no-eval.js +10 -18
  85. package/lib/rules/no-ex-assign.js +1 -1
  86. package/lib/rules/no-extra-bind.js +5 -12
  87. package/lib/rules/no-extra-boolean-cast.js +0 -2
  88. package/lib/rules/no-extra-label.js +4 -9
  89. package/lib/rules/no-extra-parens.js +17 -15
  90. package/lib/rules/no-extra-semi.js +5 -6
  91. package/lib/rules/no-fallthrough.js +6 -6
  92. package/lib/rules/no-func-assign.js +3 -3
  93. package/lib/rules/no-global-assign.js +4 -4
  94. package/lib/rules/no-implicit-coercion.js +10 -10
  95. package/lib/rules/no-implicit-globals.js +90 -8
  96. package/lib/rules/no-implied-eval.js +0 -1
  97. package/lib/rules/no-inline-comments.js +25 -11
  98. package/lib/rules/no-invalid-this.js +17 -5
  99. package/lib/rules/no-labels.js +3 -6
  100. package/lib/rules/no-lone-blocks.js +1 -1
  101. package/lib/rules/no-loop-func.js +6 -11
  102. package/lib/rules/no-magic-numbers.js +6 -6
  103. package/lib/rules/no-misleading-character-class.js +14 -7
  104. package/lib/rules/no-mixed-operators.js +13 -22
  105. package/lib/rules/no-mixed-requires.js +0 -1
  106. package/lib/rules/no-multi-spaces.js +1 -1
  107. package/lib/rules/no-native-reassign.js +4 -4
  108. package/lib/rules/no-octal-escape.js +1 -1
  109. package/lib/rules/no-param-reassign.js +28 -7
  110. package/lib/rules/no-redeclare.js +1 -1
  111. package/lib/rules/no-regex-spaces.js +0 -1
  112. package/lib/rules/no-restricted-imports.js +11 -11
  113. package/lib/rules/no-self-assign.js +12 -13
  114. package/lib/rules/no-sequences.js +3 -3
  115. package/lib/rules/no-setter-return.js +227 -0
  116. package/lib/rules/no-shadow.js +1 -4
  117. package/lib/rules/no-tabs.js +8 -2
  118. package/lib/rules/no-this-before-super.js +12 -13
  119. package/lib/rules/no-trailing-spaces.js +19 -7
  120. package/lib/rules/no-underscore-dangle.js +23 -4
  121. package/lib/rules/no-unmodified-loop-condition.js +16 -29
  122. package/lib/rules/no-unneeded-ternary.js +3 -3
  123. package/lib/rules/no-unreachable.js +7 -7
  124. package/lib/rules/no-unsafe-finally.js +4 -7
  125. package/lib/rules/no-unsafe-negation.js +32 -9
  126. package/lib/rules/no-unused-expressions.js +11 -7
  127. package/lib/rules/no-unused-labels.js +3 -6
  128. package/lib/rules/no-unused-vars.js +22 -29
  129. package/lib/rules/no-use-before-define.js +10 -15
  130. package/lib/rules/no-useless-call.js +4 -4
  131. package/lib/rules/no-useless-computed-key.js +60 -33
  132. package/lib/rules/no-useless-concat.js +4 -4
  133. package/lib/rules/no-useless-constructor.js +14 -22
  134. package/lib/rules/no-useless-escape.js +29 -8
  135. package/lib/rules/no-useless-rename.js +15 -7
  136. package/lib/rules/no-useless-return.js +8 -15
  137. package/lib/rules/no-var.js +12 -25
  138. package/lib/rules/no-warning-comments.js +0 -1
  139. package/lib/rules/no-whitespace-before-property.js +3 -3
  140. package/lib/rules/object-curly-newline.js +7 -10
  141. package/lib/rules/object-curly-spacing.js +21 -22
  142. package/lib/rules/object-shorthand.js +1 -1
  143. package/lib/rules/one-var-declaration-per-line.js +2 -2
  144. package/lib/rules/operator-assignment.js +33 -3
  145. package/lib/rules/padded-blocks.js +1 -1
  146. package/lib/rules/padding-line-between-statements.js +0 -16
  147. package/lib/rules/prefer-arrow-callback.js +6 -6
  148. package/lib/rules/prefer-const.js +27 -28
  149. package/lib/rules/prefer-destructuring.js +1 -7
  150. package/lib/rules/prefer-exponentiation-operator.js +189 -0
  151. package/lib/rules/prefer-named-capture-group.js +0 -1
  152. package/lib/rules/prefer-numeric-literals.js +32 -4
  153. package/lib/rules/prefer-object-spread.js +7 -7
  154. package/lib/rules/prefer-rest-params.js +3 -6
  155. package/lib/rules/prefer-spread.js +4 -4
  156. package/lib/rules/prefer-template.js +5 -6
  157. package/lib/rules/quote-props.js +1 -1
  158. package/lib/rules/quotes.js +5 -6
  159. package/lib/rules/radix.js +5 -10
  160. package/lib/rules/require-await.js +10 -5
  161. package/lib/rules/require-yield.js +2 -2
  162. package/lib/rules/rest-spread-spacing.js +1 -1
  163. package/lib/rules/semi.js +6 -3
  164. package/lib/rules/sort-imports.js +3 -4
  165. package/lib/rules/sort-keys.js +1 -3
  166. package/lib/rules/space-before-blocks.js +1 -2
  167. package/lib/rules/space-in-parens.js +4 -4
  168. package/lib/rules/space-infix-ops.js +6 -6
  169. package/lib/rules/spaced-comment.js +20 -22
  170. package/lib/rules/strict.js +2 -4
  171. package/lib/rules/symbol-description.js +1 -2
  172. package/lib/rules/template-curly-spacing.js +2 -2
  173. package/lib/rules/use-isnan.js +40 -3
  174. package/lib/rules/utils/ast-utils.js +84 -85
  175. package/lib/rules/utils/fix-tracker.js +0 -6
  176. package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
  177. package/lib/rules/vars-on-top.js +11 -11
  178. package/lib/shared/config-ops.js +2 -2
  179. package/lib/shared/runtime-info.js +8 -8
  180. package/lib/shared/traverser.js +2 -0
  181. package/lib/shared/types.js +9 -0
  182. package/lib/source-code/source-code.js +62 -17
  183. package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
  184. package/lib/source-code/token-store/backward-token-cursor.js +5 -5
  185. package/lib/source-code/token-store/cursors.js +17 -19
  186. package/lib/source-code/token-store/decorative-cursor.js +1 -1
  187. package/lib/source-code/token-store/filter-cursor.js +2 -2
  188. package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
  189. package/lib/source-code/token-store/forward-token-cursor.js +5 -5
  190. package/lib/source-code/token-store/index.js +86 -92
  191. package/lib/source-code/token-store/limit-cursor.js +2 -2
  192. package/lib/source-code/token-store/padded-token-cursor.js +7 -7
  193. package/lib/source-code/token-store/skip-cursor.js +2 -2
  194. package/lib/source-code/token-store/utils.js +9 -13
  195. package/package.json +9 -7
  196. package/lib/cli-engine/ignored-paths.js +0 -362
@@ -0,0 +1,227 @@
1
+ /**
2
+ * @fileoverview Rule to disallow returning values from setters
3
+ * @author Milos Djermanovic
4
+ */
5
+
6
+ "use strict";
7
+
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+ const { findVariable } = require("eslint-utils");
14
+
15
+ //------------------------------------------------------------------------------
16
+ // Helpers
17
+ //------------------------------------------------------------------------------
18
+
19
+ /**
20
+ * Determines whether the given identifier node is a reference to a global variable.
21
+ * @param {ASTNode} node `Identifier` node to check.
22
+ * @param {Scope} scope Scope to which the node belongs.
23
+ * @returns {boolean} True if the identifier is a reference to a global variable.
24
+ */
25
+ function isGlobalReference(node, scope) {
26
+ const variable = findVariable(scope, node);
27
+
28
+ return variable !== null && variable.scope.type === "global" && variable.defs.length === 0;
29
+ }
30
+
31
+ /**
32
+ * Determines whether the given node is an argument of the specified global method call, at the given `index` position.
33
+ * E.g., for given `index === 1`, this function checks for `objectName.methodName(foo, node)`, where objectName is a global variable.
34
+ * @param {ASTNode} node The node to check.
35
+ * @param {Scope} scope Scope to which the node belongs.
36
+ * @param {string} objectName Name of the global object.
37
+ * @param {string} methodName Name of the method.
38
+ * @param {number} index The given position.
39
+ * @returns {boolean} `true` if the node is argument at the given position.
40
+ */
41
+ function isArgumentOfGlobalMethodCall(node, scope, objectName, methodName, index) {
42
+ const parent = node.parent;
43
+
44
+ return parent.type === "CallExpression" &&
45
+ parent.arguments[index] === node &&
46
+ parent.callee.type === "MemberExpression" &&
47
+ astUtils.getStaticPropertyName(parent.callee) === methodName &&
48
+ parent.callee.object.type === "Identifier" &&
49
+ parent.callee.object.name === objectName &&
50
+ isGlobalReference(parent.callee.object, scope);
51
+ }
52
+
53
+ /**
54
+ * Determines whether the given node is used as a property descriptor.
55
+ * @param {ASTNode} node The node to check.
56
+ * @param {Scope} scope Scope to which the node belongs.
57
+ * @returns {boolean} `true` if the node is a property descriptor.
58
+ */
59
+ function isPropertyDescriptor(node, scope) {
60
+ if (
61
+ isArgumentOfGlobalMethodCall(node, scope, "Object", "defineProperty", 2) ||
62
+ isArgumentOfGlobalMethodCall(node, scope, "Reflect", "defineProperty", 2)
63
+ ) {
64
+ return true;
65
+ }
66
+
67
+ const parent = node.parent;
68
+
69
+ if (
70
+ parent.type === "Property" &&
71
+ parent.value === node
72
+ ) {
73
+ const grandparent = parent.parent;
74
+
75
+ if (
76
+ grandparent.type === "ObjectExpression" &&
77
+ (
78
+ isArgumentOfGlobalMethodCall(grandparent, scope, "Object", "create", 1) ||
79
+ isArgumentOfGlobalMethodCall(grandparent, scope, "Object", "defineProperties", 1)
80
+ )
81
+ ) {
82
+ return true;
83
+ }
84
+ }
85
+
86
+ return false;
87
+ }
88
+
89
+ /**
90
+ * Determines whether the given function node is used as a setter function.
91
+ * @param {ASTNode} node The node to check.
92
+ * @param {Scope} scope Scope to which the node belongs.
93
+ * @returns {boolean} `true` if the node is a setter.
94
+ */
95
+ function isSetter(node, scope) {
96
+ const parent = node.parent;
97
+
98
+ if (
99
+ parent.kind === "set" &&
100
+ parent.value === node
101
+ ) {
102
+
103
+ // Setter in an object literal or in a class
104
+ return true;
105
+ }
106
+
107
+ if (
108
+ parent.type === "Property" &&
109
+ parent.value === node &&
110
+ astUtils.getStaticPropertyName(parent) === "set" &&
111
+ parent.parent.type === "ObjectExpression" &&
112
+ isPropertyDescriptor(parent.parent, scope)
113
+ ) {
114
+
115
+ // Setter in a property descriptor
116
+ return true;
117
+ }
118
+
119
+ return false;
120
+ }
121
+
122
+ /**
123
+ * Finds function's outer scope.
124
+ * @param {Scope} scope Function's own scope.
125
+ * @returns {Scope} Function's outer scope.
126
+ */
127
+ function getOuterScope(scope) {
128
+ const upper = scope.upper;
129
+
130
+ if (upper.type === "function-expression-name") {
131
+ return upper.upper;
132
+ }
133
+
134
+ return upper;
135
+ }
136
+
137
+ //------------------------------------------------------------------------------
138
+ // Rule Definition
139
+ //------------------------------------------------------------------------------
140
+
141
+ module.exports = {
142
+ meta: {
143
+ type: "problem",
144
+
145
+ docs: {
146
+ description: "disallow returning values from setters",
147
+ category: "Possible Errors",
148
+ recommended: false,
149
+ url: "https://eslint.org/docs/rules/no-setter-return"
150
+ },
151
+
152
+ schema: [],
153
+
154
+ messages: {
155
+ returnsValue: "Setter cannot return a value."
156
+ }
157
+ },
158
+
159
+ create(context) {
160
+ let funcInfo = null;
161
+
162
+ /**
163
+ * Creates and pushes to the stack a function info object for the given function node.
164
+ * @param {ASTNode} node The function node.
165
+ * @returns {void}
166
+ */
167
+ function enterFunction(node) {
168
+ const outerScope = getOuterScope(context.getScope());
169
+
170
+ funcInfo = {
171
+ upper: funcInfo,
172
+ isSetter: isSetter(node, outerScope)
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Pops the current function info object from the stack.
178
+ * @returns {void}
179
+ */
180
+ function exitFunction() {
181
+ funcInfo = funcInfo.upper;
182
+ }
183
+
184
+ /**
185
+ * Reports the given node.
186
+ * @param {ASTNode} node Node to report.
187
+ * @returns {void}
188
+ */
189
+ function report(node) {
190
+ context.report({ node, messageId: "returnsValue" });
191
+ }
192
+
193
+ return {
194
+
195
+ /*
196
+ * Function declarations cannot be setters, but we still have to track them in the `funcInfo` stack to avoid
197
+ * false positives, because a ReturnStatement node can belong to a function declaration inside a setter.
198
+ *
199
+ * Note: A previously declared function can be referenced and actually used as a setter in a property descriptor,
200
+ * but that's out of scope for this rule.
201
+ */
202
+ FunctionDeclaration: enterFunction,
203
+ FunctionExpression: enterFunction,
204
+ ArrowFunctionExpression(node) {
205
+ enterFunction(node);
206
+
207
+ if (funcInfo.isSetter && node.expression) {
208
+
209
+ // { set: foo => bar } property descriptor. Report implicit return 'bar' as the equivalent for a return statement.
210
+ report(node.body);
211
+ }
212
+ },
213
+
214
+ "FunctionDeclaration:exit": exitFunction,
215
+ "FunctionExpression:exit": exitFunction,
216
+ "ArrowFunctionExpression:exit": exitFunction,
217
+
218
+ ReturnStatement(node) {
219
+
220
+ // Global returns (e.g., at the top level of a Node module) don't have `funcInfo`.
221
+ if (funcInfo && funcInfo.isSetter && node.argument) {
222
+ report(node);
223
+ }
224
+ }
225
+ };
226
+ }
227
+ };
@@ -54,7 +54,6 @@ module.exports = {
54
54
 
55
55
  /**
56
56
  * Check if variable name is allowed.
57
- *
58
57
  * @param {ASTNode} variable The variable to check.
59
58
  * @returns {boolean} Whether or not the variable name is allowed.
60
59
  */
@@ -67,7 +66,6 @@ module.exports = {
67
66
  *
68
67
  * ClassDeclaration creates two variables of its name into its outer scope and its class scope.
69
68
  * So we should ignore the variable in the class scope.
70
- *
71
69
  * @param {Object} variable The variable to check.
72
70
  * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration.
73
71
  */
@@ -82,7 +80,6 @@ module.exports = {
82
80
  *
83
81
  * To avoid reporting at declarations such as `var a = function a() {};`.
84
82
  * But it should report `var a = function(a) {};` or `var a = function() { function a() {} };`.
85
- *
86
83
  * @param {Object} variable The variable to check.
87
84
  * @param {Object} scopeVar The scope variable to look for.
88
85
  * @returns {boolean} Whether or not the variable is inside initializer of scopeVar.
@@ -139,7 +136,7 @@ module.exports = {
139
136
 
140
137
  /**
141
138
  * Checks the current context for shadowed variables.
142
- * @param {Scope} scope - Fixme
139
+ * @param {Scope} scope Fixme
143
140
  * @returns {void}
144
141
  */
145
142
  function checkForShadows(scope) {
@@ -55,8 +55,14 @@ module.exports = {
55
55
  context.report({
56
56
  node,
57
57
  loc: {
58
- line: index + 1,
59
- column: match.index
58
+ start: {
59
+ line: index + 1,
60
+ column: match.index
61
+ },
62
+ end: {
63
+ line: index + 1,
64
+ column: match.index + match[0].length
65
+ }
60
66
  },
61
67
  message: "Unexpected tab character."
62
68
  });
@@ -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 constructor.
20
- * @param {ASTNode} node - A node to check. This node type is one of
20
+ * @param {ASTNode} node A node to check. This node type is one of
21
21
  * `Program`, `FunctionDeclaration`, `FunctionExpression`, and
22
22
  * `ArrowFunctionExpression`.
23
23
  * @returns {boolean} `true` if the node is a constructor.
@@ -71,7 +71,7 @@ module.exports = {
71
71
 
72
72
  /**
73
73
  * Gets whether or not `super()` is called in a given code path segment.
74
- * @param {CodePathSegment} segment - A code path segment to get.
74
+ * @param {CodePathSegment} segment A code path segment to get.
75
75
  * @returns {boolean} `true` if `super()` is called.
76
76
  */
77
77
  function isCalled(segment) {
@@ -99,7 +99,7 @@ module.exports = {
99
99
 
100
100
  /**
101
101
  * Sets a given node as invalid.
102
- * @param {ASTNode} node - A node to set as invalid. This is one of
102
+ * @param {ASTNode} node A node to set as invalid. This is one of
103
103
  * a ThisExpression and a Super.
104
104
  * @returns {void}
105
105
  */
@@ -135,8 +135,8 @@ module.exports = {
135
135
 
136
136
  /**
137
137
  * Adds information of a constructor into the stack.
138
- * @param {CodePath} codePath - A code path which was started.
139
- * @param {ASTNode} node - The current node.
138
+ * @param {CodePath} codePath A code path which was started.
139
+ * @param {ASTNode} node The current node.
140
140
  * @returns {void}
141
141
  */
142
142
  onCodePathStart(codePath, node) {
@@ -169,8 +169,7 @@ module.exports = {
169
169
  *
170
170
  * And this treverses all segments of this code path then reports every
171
171
  * invalid node.
172
- *
173
- * @param {CodePath} codePath - A code path which was ended.
172
+ * @param {CodePath} codePath A code path which was ended.
174
173
  * @returns {void}
175
174
  */
176
175
  onCodePathEnd(codePath) {
@@ -204,7 +203,7 @@ module.exports = {
204
203
 
205
204
  /**
206
205
  * Initialize information of a given code path segment.
207
- * @param {CodePathSegment} segment - A code path segment to initialize.
206
+ * @param {CodePathSegment} segment A code path segment to initialize.
208
207
  * @returns {void}
209
208
  */
210
209
  onCodePathSegmentStart(segment) {
@@ -225,9 +224,9 @@ module.exports = {
225
224
  /**
226
225
  * Update information of the code path segment when a code path was
227
226
  * looped.
228
- * @param {CodePathSegment} fromSegment - The code path segment of the
227
+ * @param {CodePathSegment} fromSegment The code path segment of the
229
228
  * end of a loop.
230
- * @param {CodePathSegment} toSegment - A code path segment of the head
229
+ * @param {CodePathSegment} toSegment A code path segment of the head
231
230
  * of a loop.
232
231
  * @returns {void}
233
232
  */
@@ -258,7 +257,7 @@ module.exports = {
258
257
 
259
258
  /**
260
259
  * Reports if this is before `super()`.
261
- * @param {ASTNode} node - A target node.
260
+ * @param {ASTNode} node A target node.
262
261
  * @returns {void}
263
262
  */
264
263
  ThisExpression(node) {
@@ -269,7 +268,7 @@ module.exports = {
269
268
 
270
269
  /**
271
270
  * Reports if this is before `super()`.
272
- * @param {ASTNode} node - A target node.
271
+ * @param {ASTNode} node A target node.
273
272
  * @returns {void}
274
273
  */
275
274
  Super(node) {
@@ -280,7 +279,7 @@ module.exports = {
280
279
 
281
280
  /**
282
281
  * Marks `super()` called.
283
- * @param {ASTNode} node - A target node.
282
+ * @param {ASTNode} node A target node.
284
283
  * @returns {void}
285
284
  */
286
285
  "CallExpression:exit"(node) {
@@ -90,7 +90,11 @@ module.exports = {
90
90
  const lines = new Set();
91
91
 
92
92
  comments.forEach(comment => {
93
- for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) {
93
+ const endLine = comment.type === "Block"
94
+ ? comment.loc.end.line - 1
95
+ : comment.loc.end.line;
96
+
97
+ for (let i = comment.loc.start.line; i <= endLine; i++) {
94
98
  lines.add(i);
95
99
  }
96
100
  });
@@ -122,7 +126,7 @@ module.exports = {
122
126
  fixRange = [];
123
127
 
124
128
  for (let i = 0, ii = lines.length; i < ii; i++) {
125
- const matches = re.exec(lines[i]);
129
+ const lineNumber = i + 1;
126
130
 
127
131
  /*
128
132
  * Always add linebreak length to line length to accommodate for line break (\n or \r\n)
@@ -132,14 +136,22 @@ module.exports = {
132
136
  const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
133
137
  const lineLength = lines[i].length + linebreakLength;
134
138
 
139
+ const matches = re.exec(lines[i]);
140
+
135
141
  if (matches) {
136
142
  const location = {
137
- line: i + 1,
138
- column: matches.index
143
+ start: {
144
+ line: lineNumber,
145
+ column: matches.index
146
+ },
147
+ end: {
148
+ line: lineNumber,
149
+ column: lineLength - linebreakLength
150
+ }
139
151
  };
140
152
 
141
- const rangeStart = totalLength + location.column;
142
- const rangeEnd = totalLength + lineLength - linebreakLength;
153
+ const rangeStart = totalLength + location.start.column;
154
+ const rangeEnd = totalLength + location.end.column;
143
155
  const containingNode = sourceCode.getNodeByRangeIndex(rangeStart);
144
156
 
145
157
  if (containingNode && containingNode.type === "TemplateElement" &&
@@ -160,7 +172,7 @@ module.exports = {
160
172
 
161
173
  fixRange = [rangeStart, rangeEnd];
162
174
 
163
- if (!ignoreComments || !commentLineNumbers.has(location.line)) {
175
+ if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
164
176
  report(node, location, fixRange);
165
177
  }
166
178
  }
@@ -38,6 +38,10 @@ module.exports = {
38
38
  type: "boolean",
39
39
  default: false
40
40
  },
41
+ allowAfterThisConstructor: {
42
+ type: "boolean",
43
+ default: false
44
+ },
41
45
  enforceInMethodNames: {
42
46
  type: "boolean",
43
47
  default: false
@@ -54,6 +58,7 @@ module.exports = {
54
58
  const ALLOWED_VARIABLES = options.allow ? options.allow : [];
55
59
  const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
56
60
  const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
61
+ const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
57
62
  const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
58
63
 
59
64
  //-------------------------------------------------------------------------
@@ -72,7 +77,7 @@ module.exports = {
72
77
 
73
78
  /**
74
79
  * Check if identifier has a underscore at the end
75
- * @param {ASTNode} identifier node to evaluate
80
+ * @param {string} identifier name of the node
76
81
  * @returns {boolean} true if its is present
77
82
  * @private
78
83
  */
@@ -84,7 +89,7 @@ module.exports = {
84
89
 
85
90
  /**
86
91
  * Check if identifier is a special case member expression
87
- * @param {ASTNode} identifier node to evaluate
92
+ * @param {string} identifier name of the node
88
93
  * @returns {boolean} true if its is a special case
89
94
  * @private
90
95
  */
@@ -94,7 +99,7 @@ module.exports = {
94
99
 
95
100
  /**
96
101
  * Check if identifier is a special case variable expression
97
- * @param {ASTNode} identifier node to evaluate
102
+ * @param {string} identifier name of the node
98
103
  * @returns {boolean} true if its is a special case
99
104
  * @private
100
105
  */
@@ -104,6 +109,18 @@ module.exports = {
104
109
  return identifier === "_";
105
110
  }
106
111
 
112
+ /**
113
+ * Check if a node is a member reference of this.constructor
114
+ * @param {ASTNode} node node to evaluate
115
+ * @returns {boolean} true if it is a reference on this.constructor
116
+ * @private
117
+ */
118
+ function isThisConstructorReference(node) {
119
+ return node.object.type === "MemberExpression" &&
120
+ node.object.property.name === "constructor" &&
121
+ node.object.object.type === "ThisExpression";
122
+ }
123
+
107
124
  /**
108
125
  * Check if function has a underscore at the end
109
126
  * @param {ASTNode} node node to evaluate
@@ -156,11 +173,13 @@ module.exports = {
156
173
  function checkForTrailingUnderscoreInMemberExpression(node) {
157
174
  const identifier = node.property.name,
158
175
  isMemberOfThis = node.object.type === "ThisExpression",
159
- isMemberOfSuper = node.object.type === "Super";
176
+ isMemberOfSuper = node.object.type === "Super",
177
+ isMemberOfThisConstructor = isThisConstructorReference(node);
160
178
 
161
179
  if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
162
180
  !(isMemberOfThis && allowAfterThis) &&
163
181
  !(isMemberOfSuper && allowAfterSuper) &&
182
+ !(isMemberOfThisConstructor && allowAfterThisConstructor) &&
164
183
  !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
165
184
  context.report({
166
185
  node,
@@ -35,8 +35,7 @@ const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/u;
35
35
 
36
36
  /**
37
37
  * Checks whether or not a given reference is a write reference.
38
- *
39
- * @param {eslint-scope.Reference} reference - A reference to check.
38
+ * @param {eslint-scope.Reference} reference A reference to check.
40
39
  * @returns {boolean} `true` if the reference is a write reference.
41
40
  */
42
41
  function isWriteReference(reference) {
@@ -53,8 +52,7 @@ function isWriteReference(reference) {
53
52
  /**
54
53
  * Checks whether or not a given loop condition info does not have the modified
55
54
  * flag.
56
- *
57
- * @param {LoopConditionInfo} condition - A loop condition info to check.
55
+ * @param {LoopConditionInfo} condition A loop condition info to check.
58
56
  * @returns {boolean} `true` if the loop condition info is "unmodified".
59
57
  */
60
58
  function isUnmodified(condition) {
@@ -64,8 +62,7 @@ function isUnmodified(condition) {
64
62
  /**
65
63
  * Checks whether or not a given loop condition info does not have the modified
66
64
  * flag and does not have the group this condition belongs to.
67
- *
68
- * @param {LoopConditionInfo} condition - A loop condition info to check.
65
+ * @param {LoopConditionInfo} condition A loop condition info to check.
69
66
  * @returns {boolean} `true` if the loop condition info is "unmodified".
70
67
  */
71
68
  function isUnmodifiedAndNotBelongToGroup(condition) {
@@ -74,9 +71,8 @@ function isUnmodifiedAndNotBelongToGroup(condition) {
74
71
 
75
72
  /**
76
73
  * Checks whether or not a given reference is inside of a given node.
77
- *
78
- * @param {ASTNode} node - A node to check.
79
- * @param {eslint-scope.Reference} reference - A reference to check.
74
+ * @param {ASTNode} node A node to check.
75
+ * @param {eslint-scope.Reference} reference A reference to check.
80
76
  * @returns {boolean} `true` if the reference is inside of the node.
81
77
  */
82
78
  function isInRange(node, reference) {
@@ -88,9 +84,8 @@ function isInRange(node, reference) {
88
84
 
89
85
  /**
90
86
  * Checks whether or not a given reference is inside of a loop node's condition.
91
- *
92
- * @param {ASTNode} node - A node to check.
93
- * @param {eslint-scope.Reference} reference - A reference to check.
87
+ * @param {ASTNode} node A node to check.
88
+ * @param {eslint-scope.Reference} reference A reference to check.
94
89
  * @returns {boolean} `true` if the reference is inside of the loop node's
95
90
  * condition.
96
91
  */
@@ -108,8 +103,7 @@ const isInLoop = {
108
103
  /**
109
104
  * Gets the function which encloses a given reference.
110
105
  * This supports only FunctionDeclaration.
111
- *
112
- * @param {eslint-scope.Reference} reference - A reference to get.
106
+ * @param {eslint-scope.Reference} reference A reference to get.
113
107
  * @returns {ASTNode|null} The function node or null.
114
108
  */
115
109
  function getEncloseFunctionDeclaration(reference) {
@@ -128,9 +122,8 @@ function getEncloseFunctionDeclaration(reference) {
128
122
 
129
123
  /**
130
124
  * Updates the "modified" flags of given loop conditions with given modifiers.
131
- *
132
- * @param {LoopConditionInfo[]} conditions - The loop conditions to be updated.
133
- * @param {eslint-scope.Reference[]} modifiers - The references to update.
125
+ * @param {LoopConditionInfo[]} conditions The loop conditions to be updated.
126
+ * @param {eslint-scope.Reference[]} modifiers The references to update.
134
127
  * @returns {void}
135
128
  */
136
129
  function updateModifiedFlag(conditions, modifiers) {
@@ -183,8 +176,7 @@ module.exports = {
183
176
 
184
177
  /**
185
178
  * Reports a given condition info.
186
- *
187
- * @param {LoopConditionInfo} condition - A loop condition info to report.
179
+ * @param {LoopConditionInfo} condition A loop condition info to report.
188
180
  * @returns {void}
189
181
  */
190
182
  function report(condition) {
@@ -199,8 +191,7 @@ module.exports = {
199
191
 
200
192
  /**
201
193
  * Registers given conditions to the group the condition belongs to.
202
- *
203
- * @param {LoopConditionInfo[]} conditions - A loop condition info to
194
+ * @param {LoopConditionInfo[]} conditions A loop condition info to
204
195
  * register.
205
196
  * @returns {void}
206
197
  */
@@ -222,8 +213,7 @@ module.exports = {
222
213
 
223
214
  /**
224
215
  * Reports references which are inside of unmodified groups.
225
- *
226
- * @param {LoopConditionInfo[]} conditions - A loop condition info to report.
216
+ * @param {LoopConditionInfo[]} conditions A loop condition info to report.
227
217
  * @returns {void}
228
218
  */
229
219
  function checkConditionsInGroup(conditions) {
@@ -234,8 +224,7 @@ module.exports = {
234
224
 
235
225
  /**
236
226
  * Checks whether or not a given group node has any dynamic elements.
237
- *
238
- * @param {ASTNode} root - A node to check.
227
+ * @param {ASTNode} root A node to check.
239
228
  * This node is one of BinaryExpression or ConditionalExpression.
240
229
  * @returns {boolean} `true` if the node is dynamic.
241
230
  */
@@ -259,8 +248,7 @@ module.exports = {
259
248
 
260
249
  /**
261
250
  * Creates the loop condition information from a given reference.
262
- *
263
- * @param {eslint-scope.Reference} reference - A reference to create.
251
+ * @param {eslint-scope.Reference} reference A reference to create.
264
252
  * @returns {LoopConditionInfo|null} Created loop condition info, or null.
265
253
  */
266
254
  function toLoopCondition(reference) {
@@ -313,8 +301,7 @@ module.exports = {
313
301
  /**
314
302
  * Finds unmodified references which are inside of a loop condition.
315
303
  * Then reports the references which are outside of groups.
316
- *
317
- * @param {eslint-scope.Variable} variable - A variable to report.
304
+ * @param {eslint-scope.Variable} variable A variable to report.
318
305
  * @returns {void}
319
306
  */
320
307
  function checkReferences(variable) {
@@ -57,7 +57,7 @@ module.exports = {
57
57
 
58
58
  /**
59
59
  * Test if the node is a boolean literal
60
- * @param {ASTNode} node - The node to report.
60
+ * @param {ASTNode} node The node to report.
61
61
  * @returns {boolean} True if the its a boolean literal
62
62
  * @private
63
63
  */
@@ -91,7 +91,7 @@ module.exports = {
91
91
 
92
92
  /**
93
93
  * Tests if a given node always evaluates to a boolean value
94
- * @param {ASTNode} node - An expression node
94
+ * @param {ASTNode} node An expression node
95
95
  * @returns {boolean} True if it is determined that the node will always evaluate to a boolean value
96
96
  */
97
97
  function isBooleanExpression(node) {
@@ -101,7 +101,7 @@ module.exports = {
101
101
 
102
102
  /**
103
103
  * Test if the node matches the pattern id ? id : expression
104
- * @param {ASTNode} node - The ConditionalExpression to check.
104
+ * @param {ASTNode} node The ConditionalExpression to check.
105
105
  * @returns {boolean} True if the pattern is matched, and false otherwise
106
106
  * @private
107
107
  */