eslint 8.0.1 → 8.4.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 (305) hide show
  1. package/README.md +8 -12
  2. package/conf/globals.js +144 -0
  3. package/lib/cli-engine/cli-engine.js +10 -21
  4. package/lib/cli.js +1 -1
  5. package/lib/config/default-config.js +11 -2
  6. package/lib/config/flat-config-array.js +2 -2
  7. package/lib/config/flat-config-helpers.js +67 -0
  8. package/lib/config/flat-config-schema.js +13 -8
  9. package/lib/config/rule-validator.js +28 -27
  10. package/lib/eslint/eslint.js +13 -18
  11. package/lib/linter/code-path-analysis/code-path-analyzer.js +6 -1
  12. package/lib/linter/code-path-analysis/code-path.js +1 -1
  13. package/lib/linter/linter.js +457 -45
  14. package/lib/linter/node-event-generator.js +7 -0
  15. package/lib/options.js +6 -6
  16. package/lib/rule-tester/rule-tester.js +5 -2
  17. package/lib/rules/accessor-pairs.js +1 -0
  18. package/lib/rules/array-bracket-newline.js +1 -0
  19. package/lib/rules/array-bracket-spacing.js +1 -0
  20. package/lib/rules/array-callback-return.js +1 -0
  21. package/lib/rules/array-element-newline.js +1 -0
  22. package/lib/rules/arrow-body-style.js +1 -0
  23. package/lib/rules/arrow-parens.js +1 -0
  24. package/lib/rules/arrow-spacing.js +1 -0
  25. package/lib/rules/block-scoped-var.js +3 -0
  26. package/lib/rules/block-spacing.js +11 -3
  27. package/lib/rules/brace-style.js +7 -0
  28. package/lib/rules/callback-return.js +1 -0
  29. package/lib/rules/camelcase.js +1 -0
  30. package/lib/rules/capitalized-comments.js +1 -0
  31. package/lib/rules/class-methods-use-this.js +11 -1
  32. package/lib/rules/comma-dangle.js +1 -0
  33. package/lib/rules/comma-spacing.js +1 -0
  34. package/lib/rules/comma-style.js +1 -0
  35. package/lib/rules/complexity.js +15 -6
  36. package/lib/rules/computed-property-spacing.js +1 -0
  37. package/lib/rules/consistent-return.js +1 -0
  38. package/lib/rules/consistent-this.js +1 -0
  39. package/lib/rules/constructor-super.js +1 -0
  40. package/lib/rules/curly.js +1 -0
  41. package/lib/rules/default-case-last.js +1 -0
  42. package/lib/rules/default-case.js +1 -0
  43. package/lib/rules/default-param-last.js +1 -0
  44. package/lib/rules/dot-location.js +1 -0
  45. package/lib/rules/dot-notation.js +1 -0
  46. package/lib/rules/eol-last.js +1 -0
  47. package/lib/rules/eqeqeq.js +1 -0
  48. package/lib/rules/for-direction.js +1 -0
  49. package/lib/rules/func-call-spacing.js +1 -0
  50. package/lib/rules/func-name-matching.js +1 -0
  51. package/lib/rules/func-names.js +1 -0
  52. package/lib/rules/func-style.js +1 -0
  53. package/lib/rules/function-call-argument-newline.js +1 -0
  54. package/lib/rules/function-paren-newline.js +1 -0
  55. package/lib/rules/generator-star-spacing.js +1 -0
  56. package/lib/rules/getter-return.js +1 -0
  57. package/lib/rules/global-require.js +1 -0
  58. package/lib/rules/grouped-accessor-pairs.js +1 -0
  59. package/lib/rules/guard-for-in.js +1 -0
  60. package/lib/rules/handle-callback-err.js +1 -0
  61. package/lib/rules/id-blacklist.js +1 -0
  62. package/lib/rules/id-denylist.js +1 -0
  63. package/lib/rules/id-length.js +1 -0
  64. package/lib/rules/id-match.js +1 -0
  65. package/lib/rules/implicit-arrow-linebreak.js +1 -0
  66. package/lib/rules/indent-legacy.js +1 -0
  67. package/lib/rules/indent.js +22 -0
  68. package/lib/rules/index.js +1 -0
  69. package/lib/rules/init-declarations.js +1 -0
  70. package/lib/rules/jsx-quotes.js +1 -0
  71. package/lib/rules/key-spacing.js +15 -13
  72. package/lib/rules/keyword-spacing.js +16 -1
  73. package/lib/rules/line-comment-position.js +1 -0
  74. package/lib/rules/linebreak-style.js +1 -0
  75. package/lib/rules/lines-around-comment.js +55 -7
  76. package/lib/rules/lines-around-directive.js +1 -0
  77. package/lib/rules/lines-between-class-members.js +1 -0
  78. package/lib/rules/max-classes-per-file.js +1 -0
  79. package/lib/rules/max-depth.js +3 -0
  80. package/lib/rules/max-len.js +1 -0
  81. package/lib/rules/max-lines-per-function.js +21 -2
  82. package/lib/rules/max-lines.js +1 -0
  83. package/lib/rules/max-nested-callbacks.js +1 -0
  84. package/lib/rules/max-params.js +1 -0
  85. package/lib/rules/max-statements-per-line.js +1 -0
  86. package/lib/rules/max-statements.js +11 -0
  87. package/lib/rules/multiline-comment-style.js +1 -0
  88. package/lib/rules/multiline-ternary.js +1 -0
  89. package/lib/rules/new-cap.js +1 -0
  90. package/lib/rules/new-parens.js +1 -0
  91. package/lib/rules/newline-after-var.js +1 -0
  92. package/lib/rules/newline-before-return.js +1 -0
  93. package/lib/rules/newline-per-chained-call.js +1 -0
  94. package/lib/rules/no-alert.js +1 -0
  95. package/lib/rules/no-array-constructor.js +1 -0
  96. package/lib/rules/no-async-promise-executor.js +1 -0
  97. package/lib/rules/no-await-in-loop.js +1 -0
  98. package/lib/rules/no-bitwise.js +1 -0
  99. package/lib/rules/no-buffer-constructor.js +1 -0
  100. package/lib/rules/no-caller.js +1 -0
  101. package/lib/rules/no-case-declarations.js +1 -0
  102. package/lib/rules/no-catch-shadow.js +1 -0
  103. package/lib/rules/no-class-assign.js +1 -0
  104. package/lib/rules/no-compare-neg-zero.js +1 -0
  105. package/lib/rules/no-cond-assign.js +1 -0
  106. package/lib/rules/no-confusing-arrow.js +1 -0
  107. package/lib/rules/no-console.js +1 -0
  108. package/lib/rules/no-const-assign.js +1 -0
  109. package/lib/rules/no-constant-condition.js +4 -1
  110. package/lib/rules/no-constructor-return.js +1 -0
  111. package/lib/rules/no-continue.js +1 -0
  112. package/lib/rules/no-control-regex.js +1 -0
  113. package/lib/rules/no-debugger.js +1 -0
  114. package/lib/rules/no-delete-var.js +1 -0
  115. package/lib/rules/no-div-regex.js +1 -0
  116. package/lib/rules/no-dupe-args.js +1 -0
  117. package/lib/rules/no-dupe-class-members.js +1 -0
  118. package/lib/rules/no-dupe-else-if.js +1 -0
  119. package/lib/rules/no-dupe-keys.js +1 -0
  120. package/lib/rules/no-duplicate-case.js +1 -0
  121. package/lib/rules/no-duplicate-imports.js +1 -0
  122. package/lib/rules/no-else-return.js +1 -0
  123. package/lib/rules/no-empty-character-class.js +1 -0
  124. package/lib/rules/no-empty-function.js +1 -0
  125. package/lib/rules/no-empty-pattern.js +1 -0
  126. package/lib/rules/no-empty.js +1 -0
  127. package/lib/rules/no-eq-null.js +1 -0
  128. package/lib/rules/no-eval.js +3 -0
  129. package/lib/rules/no-ex-assign.js +1 -0
  130. package/lib/rules/no-extend-native.js +1 -0
  131. package/lib/rules/no-extra-bind.js +1 -0
  132. package/lib/rules/no-extra-boolean-cast.js +1 -0
  133. package/lib/rules/no-extra-label.js +1 -0
  134. package/lib/rules/no-extra-parens.js +1 -0
  135. package/lib/rules/no-extra-semi.js +2 -1
  136. package/lib/rules/no-fallthrough.js +1 -0
  137. package/lib/rules/no-floating-decimal.js +1 -0
  138. package/lib/rules/no-func-assign.js +1 -0
  139. package/lib/rules/no-global-assign.js +1 -0
  140. package/lib/rules/no-implicit-coercion.js +1 -0
  141. package/lib/rules/no-implicit-globals.js +1 -0
  142. package/lib/rules/no-implied-eval.js +1 -0
  143. package/lib/rules/no-import-assign.js +1 -0
  144. package/lib/rules/no-inline-comments.js +1 -0
  145. package/lib/rules/no-inner-declarations.js +27 -4
  146. package/lib/rules/no-invalid-regexp.js +1 -0
  147. package/lib/rules/no-invalid-this.js +5 -0
  148. package/lib/rules/no-irregular-whitespace.js +1 -0
  149. package/lib/rules/no-iterator.js +1 -0
  150. package/lib/rules/no-label-var.js +1 -0
  151. package/lib/rules/no-labels.js +1 -0
  152. package/lib/rules/no-lone-blocks.js +9 -2
  153. package/lib/rules/no-lonely-if.js +1 -0
  154. package/lib/rules/no-loop-func.js +1 -0
  155. package/lib/rules/no-loss-of-precision.js +1 -0
  156. package/lib/rules/no-magic-numbers.js +1 -0
  157. package/lib/rules/no-misleading-character-class.js +1 -0
  158. package/lib/rules/no-mixed-operators.js +1 -0
  159. package/lib/rules/no-mixed-requires.js +1 -0
  160. package/lib/rules/no-mixed-spaces-and-tabs.js +1 -0
  161. package/lib/rules/no-multi-assign.js +1 -0
  162. package/lib/rules/no-multi-spaces.js +1 -0
  163. package/lib/rules/no-multi-str.js +1 -0
  164. package/lib/rules/no-multiple-empty-lines.js +1 -0
  165. package/lib/rules/no-native-reassign.js +1 -0
  166. package/lib/rules/no-negated-condition.js +1 -0
  167. package/lib/rules/no-negated-in-lhs.js +1 -0
  168. package/lib/rules/no-nested-ternary.js +1 -0
  169. package/lib/rules/no-new-func.js +1 -0
  170. package/lib/rules/no-new-object.js +1 -0
  171. package/lib/rules/no-new-require.js +1 -0
  172. package/lib/rules/no-new-symbol.js +1 -0
  173. package/lib/rules/no-new-wrappers.js +1 -0
  174. package/lib/rules/no-new.js +1 -0
  175. package/lib/rules/no-nonoctal-decimal-escape.js +1 -0
  176. package/lib/rules/no-obj-calls.js +1 -0
  177. package/lib/rules/no-octal-escape.js +1 -0
  178. package/lib/rules/no-octal.js +1 -0
  179. package/lib/rules/no-param-reassign.js +1 -0
  180. package/lib/rules/no-path-concat.js +1 -0
  181. package/lib/rules/no-plusplus.js +1 -0
  182. package/lib/rules/no-process-env.js +1 -0
  183. package/lib/rules/no-process-exit.js +1 -0
  184. package/lib/rules/no-promise-executor-return.js +1 -0
  185. package/lib/rules/no-proto.js +1 -0
  186. package/lib/rules/no-prototype-builtins.js +1 -0
  187. package/lib/rules/no-redeclare.js +3 -0
  188. package/lib/rules/no-regex-spaces.js +1 -0
  189. package/lib/rules/no-restricted-exports.js +1 -0
  190. package/lib/rules/no-restricted-globals.js +1 -0
  191. package/lib/rules/no-restricted-imports.js +1 -0
  192. package/lib/rules/no-restricted-modules.js +1 -0
  193. package/lib/rules/no-restricted-properties.js +1 -0
  194. package/lib/rules/no-restricted-syntax.js +1 -0
  195. package/lib/rules/no-return-assign.js +1 -0
  196. package/lib/rules/no-return-await.js +1 -0
  197. package/lib/rules/no-script-url.js +1 -0
  198. package/lib/rules/no-self-assign.js +1 -0
  199. package/lib/rules/no-self-compare.js +1 -0
  200. package/lib/rules/no-sequences.js +1 -0
  201. package/lib/rules/no-setter-return.js +1 -0
  202. package/lib/rules/no-shadow-restricted-names.js +1 -0
  203. package/lib/rules/no-shadow.js +1 -0
  204. package/lib/rules/no-spaced-func.js +1 -0
  205. package/lib/rules/no-sparse-arrays.js +1 -0
  206. package/lib/rules/no-sync.js +1 -0
  207. package/lib/rules/no-tabs.js +1 -0
  208. package/lib/rules/no-template-curly-in-string.js +1 -0
  209. package/lib/rules/no-ternary.js +1 -0
  210. package/lib/rules/no-this-before-super.js +1 -0
  211. package/lib/rules/no-throw-literal.js +1 -0
  212. package/lib/rules/no-trailing-spaces.js +1 -0
  213. package/lib/rules/no-undef-init.js +1 -0
  214. package/lib/rules/no-undef.js +1 -0
  215. package/lib/rules/no-undefined.js +1 -0
  216. package/lib/rules/no-underscore-dangle.js +1 -0
  217. package/lib/rules/no-unexpected-multiline.js +1 -0
  218. package/lib/rules/no-unmodified-loop-condition.js +1 -0
  219. package/lib/rules/no-unneeded-ternary.js +1 -0
  220. package/lib/rules/no-unreachable-loop.js +1 -0
  221. package/lib/rules/no-unreachable.js +1 -0
  222. package/lib/rules/no-unsafe-finally.js +1 -0
  223. package/lib/rules/no-unsafe-negation.js +1 -0
  224. package/lib/rules/no-unsafe-optional-chaining.js +1 -0
  225. package/lib/rules/no-unused-expressions.js +7 -0
  226. package/lib/rules/no-unused-labels.js +1 -0
  227. package/lib/rules/no-unused-private-class-members.js +195 -0
  228. package/lib/rules/no-unused-vars.js +1 -0
  229. package/lib/rules/no-use-before-define.js +176 -74
  230. package/lib/rules/no-useless-backreference.js +1 -0
  231. package/lib/rules/no-useless-call.js +1 -0
  232. package/lib/rules/no-useless-catch.js +1 -0
  233. package/lib/rules/no-useless-computed-key.js +1 -0
  234. package/lib/rules/no-useless-concat.js +1 -0
  235. package/lib/rules/no-useless-constructor.js +1 -0
  236. package/lib/rules/no-useless-escape.js +1 -0
  237. package/lib/rules/no-useless-rename.js +1 -0
  238. package/lib/rules/no-useless-return.js +1 -0
  239. package/lib/rules/no-var.js +1 -0
  240. package/lib/rules/no-void.js +1 -0
  241. package/lib/rules/no-warning-comments.js +1 -0
  242. package/lib/rules/no-whitespace-before-property.js +1 -0
  243. package/lib/rules/no-with.js +1 -0
  244. package/lib/rules/nonblock-statement-body-position.js +1 -0
  245. package/lib/rules/object-curly-newline.js +1 -0
  246. package/lib/rules/object-curly-spacing.js +1 -0
  247. package/lib/rules/object-property-newline.js +1 -0
  248. package/lib/rules/object-shorthand.js +1 -0
  249. package/lib/rules/one-var-declaration-per-line.js +1 -0
  250. package/lib/rules/one-var.js +6 -1
  251. package/lib/rules/operator-assignment.js +1 -0
  252. package/lib/rules/operator-linebreak.js +1 -0
  253. package/lib/rules/padded-blocks.js +9 -0
  254. package/lib/rules/padding-line-between-statements.js +3 -0
  255. package/lib/rules/prefer-arrow-callback.js +1 -0
  256. package/lib/rules/prefer-const.js +2 -1
  257. package/lib/rules/prefer-destructuring.js +1 -0
  258. package/lib/rules/prefer-exponentiation-operator.js +1 -0
  259. package/lib/rules/prefer-named-capture-group.js +1 -0
  260. package/lib/rules/prefer-numeric-literals.js +1 -0
  261. package/lib/rules/prefer-object-spread.js +1 -0
  262. package/lib/rules/prefer-promise-reject-errors.js +1 -0
  263. package/lib/rules/prefer-reflect.js +1 -0
  264. package/lib/rules/prefer-regex-literals.js +1 -0
  265. package/lib/rules/prefer-rest-params.js +1 -0
  266. package/lib/rules/prefer-spread.js +1 -0
  267. package/lib/rules/prefer-template.js +1 -0
  268. package/lib/rules/quote-props.js +1 -0
  269. package/lib/rules/quotes.js +1 -0
  270. package/lib/rules/radix.js +1 -0
  271. package/lib/rules/require-atomic-updates.js +15 -2
  272. package/lib/rules/require-await.js +1 -0
  273. package/lib/rules/require-jsdoc.js +1 -0
  274. package/lib/rules/require-unicode-regexp.js +1 -0
  275. package/lib/rules/require-yield.js +1 -0
  276. package/lib/rules/rest-spread-spacing.js +1 -0
  277. package/lib/rules/semi-spacing.js +1 -0
  278. package/lib/rules/semi-style.js +9 -2
  279. package/lib/rules/semi.js +19 -9
  280. package/lib/rules/sort-imports.js +1 -0
  281. package/lib/rules/sort-keys.js +1 -0
  282. package/lib/rules/sort-vars.js +1 -0
  283. package/lib/rules/space-before-blocks.js +1 -0
  284. package/lib/rules/space-before-function-paren.js +1 -0
  285. package/lib/rules/space-in-parens.js +1 -0
  286. package/lib/rules/space-infix-ops.js +1 -0
  287. package/lib/rules/space-unary-ops.js +1 -0
  288. package/lib/rules/spaced-comment.js +1 -0
  289. package/lib/rules/strict.js +1 -0
  290. package/lib/rules/switch-colon-spacing.js +1 -0
  291. package/lib/rules/symbol-description.js +1 -0
  292. package/lib/rules/template-curly-spacing.js +1 -0
  293. package/lib/rules/template-tag-spacing.js +1 -0
  294. package/lib/rules/unicode-bom.js +1 -0
  295. package/lib/rules/use-isnan.js +1 -0
  296. package/lib/rules/utils/ast-utils.js +15 -3
  297. package/lib/rules/valid-jsdoc.js +1 -0
  298. package/lib/rules/valid-typeof.js +1 -0
  299. package/lib/rules/vars-on-top.js +26 -12
  300. package/lib/rules/wrap-iife.js +1 -0
  301. package/lib/rules/wrap-regex.js +1 -0
  302. package/lib/rules/yield-star-spacing.js +1 -0
  303. package/lib/rules/yoda.js +1 -0
  304. package/lib/shared/types.js +10 -0
  305. package/package.json +12 -12
@@ -24,6 +24,7 @@ function alwaysFalse() {
24
24
  return false;
25
25
  }
26
26
 
27
+ /** @type {import('../shared/types').Rule} */
27
28
  module.exports = {
28
29
  meta: {
29
30
  type: "suggestion",
@@ -115,6 +116,12 @@ module.exports = {
115
116
  const parent = ancestors[ancestors.length - 1],
116
117
  grandparent = ancestors[ancestors.length - 2];
117
118
 
119
+ /**
120
+ * https://tc39.es/ecma262/#directive-prologue
121
+ *
122
+ * Only `FunctionBody`, `ScriptBody` and `ModuleBody` can have directive prologue.
123
+ * Class static blocks do not have directive prologue.
124
+ */
118
125
  return (parent.type === "Program" || parent.type === "BlockStatement" &&
119
126
  (/Function/u.test(grandparent.type))) &&
120
127
  directives(parent).indexOf(node) >= 0;
@@ -9,6 +9,7 @@
9
9
  // Rule Definition
10
10
  //------------------------------------------------------------------------------
11
11
 
12
+ /** @type {import('../shared/types').Rule} */
12
13
  module.exports = {
13
14
  meta: {
14
15
  type: "suggestion",
@@ -0,0 +1,195 @@
1
+ /**
2
+ * @fileoverview Rule to flag declared but unused private class members
3
+ * @author Tim van der Lippe
4
+ */
5
+
6
+ "use strict";
7
+
8
+ //------------------------------------------------------------------------------
9
+ // Rule Definition
10
+ //------------------------------------------------------------------------------
11
+
12
+ /** @type {import('../shared/types').Rule} */
13
+ module.exports = {
14
+ meta: {
15
+ type: "problem",
16
+
17
+ docs: {
18
+ description: "disallow unused private class members",
19
+ recommended: false,
20
+ url: "https://eslint.org/docs/rules/no-unused-private-class-members"
21
+ },
22
+
23
+ schema: [],
24
+
25
+ messages: {
26
+ unusedPrivateClassMember: "'{{classMemberName}}' is defined but never used."
27
+ }
28
+ },
29
+
30
+ create(context) {
31
+ const trackedClasses = [];
32
+
33
+ /**
34
+ * Check whether the current node is in a write only assignment.
35
+ * @param {ASTNode} privateIdentifierNode Node referring to a private identifier
36
+ * @returns {boolean} Whether the node is in a write only assignment
37
+ * @private
38
+ */
39
+ function isWriteOnlyAssignment(privateIdentifierNode) {
40
+ const parentStatement = privateIdentifierNode.parent.parent;
41
+ const isAssignmentExpression = parentStatement.type === "AssignmentExpression";
42
+
43
+ if (!isAssignmentExpression &&
44
+ parentStatement.type !== "ForInStatement" &&
45
+ parentStatement.type !== "ForOfStatement" &&
46
+ parentStatement.type !== "AssignmentPattern") {
47
+ return false;
48
+ }
49
+
50
+ // It is a write-only usage, since we still allow usages on the right for reads
51
+ if (parentStatement.left !== privateIdentifierNode.parent) {
52
+ return false;
53
+ }
54
+
55
+ // For any other operator (such as '+=') we still consider it a read operation
56
+ if (isAssignmentExpression && parentStatement.operator !== "=") {
57
+
58
+ /*
59
+ * However, if the read operation is "discarded" in an empty statement, then
60
+ * we consider it write only.
61
+ */
62
+ return parentStatement.parent.type === "ExpressionStatement";
63
+ }
64
+
65
+ return true;
66
+ }
67
+
68
+ //--------------------------------------------------------------------------
69
+ // Public
70
+ //--------------------------------------------------------------------------
71
+
72
+ return {
73
+
74
+ // Collect all declared members up front and assume they are all unused
75
+ ClassBody(classBodyNode) {
76
+ const privateMembers = new Map();
77
+
78
+ trackedClasses.unshift(privateMembers);
79
+ for (const bodyMember of classBodyNode.body) {
80
+ if (bodyMember.type === "PropertyDefinition" || bodyMember.type === "MethodDefinition") {
81
+ if (bodyMember.key.type === "PrivateIdentifier") {
82
+ privateMembers.set(bodyMember.key.name, {
83
+ declaredNode: bodyMember,
84
+ isAccessor: bodyMember.type === "MethodDefinition" &&
85
+ (bodyMember.kind === "set" || bodyMember.kind === "get")
86
+ });
87
+ }
88
+ }
89
+ }
90
+ },
91
+
92
+ /*
93
+ * Process all usages of the private identifier and remove a member from
94
+ * `declaredAndUnusedPrivateMembers` if we deem it used.
95
+ */
96
+ PrivateIdentifier(privateIdentifierNode) {
97
+ const classBody = trackedClasses.find(classProperties => classProperties.has(privateIdentifierNode.name));
98
+
99
+ // Can't happen, as it is a parser to have a missing class body, but let's code defensively here.
100
+ if (!classBody) {
101
+ return;
102
+ }
103
+
104
+ // In case any other usage was already detected, we can short circuit the logic here.
105
+ const memberDefinition = classBody.get(privateIdentifierNode.name);
106
+
107
+ if (memberDefinition.isUsed) {
108
+ return;
109
+ }
110
+
111
+ // The definition of the class member itself
112
+ if (privateIdentifierNode.parent.type === "PropertyDefinition" ||
113
+ privateIdentifierNode.parent.type === "MethodDefinition") {
114
+ return;
115
+ }
116
+
117
+ /*
118
+ * Any usage of an accessor is considered a read, as the getter/setter can have
119
+ * side-effects in its definition.
120
+ */
121
+ if (memberDefinition.isAccessor) {
122
+ memberDefinition.isUsed = true;
123
+ return;
124
+ }
125
+
126
+ // Any assignments to this member, except for assignments that also read
127
+ if (isWriteOnlyAssignment(privateIdentifierNode)) {
128
+ return;
129
+ }
130
+
131
+ const wrappingExpressionType = privateIdentifierNode.parent.parent.type;
132
+ const parentOfWrappingExpressionType = privateIdentifierNode.parent.parent.parent.type;
133
+
134
+ // A statement which only increments (`this.#x++;`)
135
+ if (wrappingExpressionType === "UpdateExpression" &&
136
+ parentOfWrappingExpressionType === "ExpressionStatement") {
137
+ return;
138
+ }
139
+
140
+ /*
141
+ * ({ x: this.#usedInDestructuring } = bar);
142
+ *
143
+ * But should treat the following as a read:
144
+ * ({ [this.#x]: a } = foo);
145
+ */
146
+ if (wrappingExpressionType === "Property" &&
147
+ parentOfWrappingExpressionType === "ObjectPattern" &&
148
+ privateIdentifierNode.parent.parent.value === privateIdentifierNode.parent) {
149
+ return;
150
+ }
151
+
152
+ // [...this.#unusedInRestPattern] = bar;
153
+ if (wrappingExpressionType === "RestElement") {
154
+ return;
155
+ }
156
+
157
+ // [this.#unusedInAssignmentPattern] = bar;
158
+ if (wrappingExpressionType === "ArrayPattern") {
159
+ return;
160
+ }
161
+
162
+ /*
163
+ * We can't delete the memberDefinition, as we need to keep track of which member we are marking as used.
164
+ * In the case of nested classes, we only mark the first member we encounter as used. If you were to delete
165
+ * the member, then any subsequent usage could incorrectly mark the member of an encapsulating parent class
166
+ * as used, which is incorrect.
167
+ */
168
+ memberDefinition.isUsed = true;
169
+ },
170
+
171
+ /*
172
+ * Post-process the class members and report any remaining members.
173
+ * Since private members can only be accessed in the current class context,
174
+ * we can safely assume that all usages are within the current class body.
175
+ */
176
+ "ClassBody:exit"() {
177
+ const unusedPrivateMembers = trackedClasses.shift();
178
+
179
+ for (const [classMemberName, { declaredNode, isUsed }] of unusedPrivateMembers.entries()) {
180
+ if (isUsed) {
181
+ continue;
182
+ }
183
+ context.report({
184
+ node: declaredNode,
185
+ loc: declaredNode.key.loc,
186
+ messageId: "unusedPrivateClassMember",
187
+ data: {
188
+ classMemberName: `#${classMemberName}`
189
+ }
190
+ });
191
+ }
192
+ }
193
+ };
194
+ }
195
+ };
@@ -27,6 +27,7 @@ const astUtils = require("./utils/ast-utils");
27
27
  // Rule Definition
28
28
  //------------------------------------------------------------------------------
29
29
 
30
+ /** @type {import('../shared/types').Rule} */
30
31
  module.exports = {
31
32
  meta: {
32
33
  type: "problem",
@@ -34,52 +34,113 @@ function parseOptions(options) {
34
34
  }
35
35
 
36
36
  /**
37
- * Checks whether or not a given variable is a function declaration.
38
- * @param {eslint-scope.Variable} variable A variable to check.
39
- * @returns {boolean} `true` if the variable is a function declaration.
37
+ * Checks whether or not a given location is inside of the range of a given node.
38
+ * @param {ASTNode} node An node to check.
39
+ * @param {number} location A location to check.
40
+ * @returns {boolean} `true` if the location is inside of the range of the node.
40
41
  */
41
- function isFunction(variable) {
42
- return variable.defs[0].type === "FunctionName";
42
+ function isInRange(node, location) {
43
+ return node && node.range[0] <= location && location <= node.range[1];
43
44
  }
44
45
 
45
46
  /**
46
- * Checks whether or not a given variable is a class declaration in an upper function scope.
47
- * @param {eslint-scope.Variable} variable A variable to check.
48
- * @param {eslint-scope.Reference} reference A reference to check.
49
- * @returns {boolean} `true` if the variable is a class declaration.
47
+ * Checks whether or not a given location is inside of the range of a class static initializer.
48
+ * Static initializers are static blocks and initializers of static fields.
49
+ * @param {ASTNode} node `ClassBody` node to check static initializers.
50
+ * @param {number} location A location to check.
51
+ * @returns {boolean} `true` if the location is inside of a class static initializer.
50
52
  */
51
- function isOuterClass(variable, reference) {
52
- return (
53
- variable.defs[0].type === "ClassName" &&
54
- variable.scope.variableScope !== reference.from.variableScope
55
- );
53
+ function isInClassStaticInitializerRange(node, location) {
54
+ return node.body.some(classMember => (
55
+ (
56
+ classMember.type === "StaticBlock" &&
57
+ isInRange(classMember, location)
58
+ ) ||
59
+ (
60
+ classMember.type === "PropertyDefinition" &&
61
+ classMember.static &&
62
+ classMember.value &&
63
+ isInRange(classMember.value, location)
64
+ )
65
+ ));
56
66
  }
57
67
 
58
68
  /**
59
- * Checks whether or not a given variable is a variable declaration in an upper function scope.
60
- * @param {eslint-scope.Variable} variable A variable to check.
61
- * @param {eslint-scope.Reference} reference A reference to check.
62
- * @returns {boolean} `true` if the variable is a variable declaration.
69
+ * Checks whether a given scope is the scope of a a class static initializer.
70
+ * Static initializers are static blocks and initializers of static fields.
71
+ * @param {eslint-scope.Scope} scope A scope to check.
72
+ * @returns {boolean} `true` if the scope is a class static initializer scope.
63
73
  */
64
- function isOuterVariable(variable, reference) {
65
- return (
66
- variable.defs[0].type === "Variable" &&
67
- variable.scope.variableScope !== reference.from.variableScope
68
- );
74
+ function isClassStaticInitializerScope(scope) {
75
+ if (scope.type === "class-static-block") {
76
+ return true;
77
+ }
78
+
79
+ if (scope.type === "class-field-initializer") {
80
+
81
+ // `scope.block` is PropertyDefinition#value node
82
+ const propertyDefinition = scope.block.parent;
83
+
84
+ return propertyDefinition.static;
85
+ }
86
+
87
+ return false;
69
88
  }
70
89
 
71
90
  /**
72
- * Checks whether or not a given location is inside of the range of a given node.
73
- * @param {ASTNode} node An node to check.
74
- * @param {number} location A location to check.
75
- * @returns {boolean} `true` if the location is inside of the range of the node.
91
+ * Checks whether a given reference is evaluated in an execution context
92
+ * that isn't the one where the variable it refers to is defined.
93
+ * Execution contexts are:
94
+ * - top-level
95
+ * - functions
96
+ * - class field initializers (implicit functions)
97
+ * - class static blocks (implicit functions)
98
+ * Static class field initializers and class static blocks are automatically run during the class definition evaluation,
99
+ * and therefore we'll consider them as a part of the parent execution context.
100
+ * Example:
101
+ *
102
+ * const x = 1;
103
+ *
104
+ * x; // returns `false`
105
+ * () => x; // returns `true`
106
+ *
107
+ * class C {
108
+ * field = x; // returns `true`
109
+ * static field = x; // returns `false`
110
+ *
111
+ * method() {
112
+ * x; // returns `true`
113
+ * }
114
+ *
115
+ * static method() {
116
+ * x; // returns `true`
117
+ * }
118
+ *
119
+ * static {
120
+ * x; // returns `false`
121
+ * }
122
+ * }
123
+ * @param {eslint-scope.Reference} reference A reference to check.
124
+ * @returns {boolean} `true` if the reference is from a separate execution context.
76
125
  */
77
- function isInRange(node, location) {
78
- return node && node.range[0] <= location && location <= node.range[1];
126
+ function isFromSeparateExecutionContext(reference) {
127
+ const variable = reference.resolved;
128
+ let scope = reference.from;
129
+
130
+ // Scope#variableScope represents execution context
131
+ while (variable.scope.variableScope !== scope.variableScope) {
132
+ if (isClassStaticInitializerScope(scope.variableScope)) {
133
+ scope = scope.variableScope.upper;
134
+ } else {
135
+ return true;
136
+ }
137
+ }
138
+
139
+ return false;
79
140
  }
80
141
 
81
142
  /**
82
- * Checks whether or not a given reference is inside of the initializers of a given variable.
143
+ * Checks whether or not a given reference is evaluated during the initialization of its variable.
83
144
  *
84
145
  * This returns `true` in the following cases:
85
146
  *
@@ -88,17 +149,45 @@ function isInRange(node, location) {
88
149
  * var {a = a} = obj
89
150
  * for (var a in a) {}
90
151
  * for (var a of a) {}
91
- * @param {Variable} variable A variable to check.
152
+ * var C = class { [C]; };
153
+ * var C = class { static foo = C; };
154
+ * var C = class { static { foo = C; } };
155
+ * class C extends C {}
156
+ * class C extends (class { static foo = C; }) {}
157
+ * class C { [C]; }
92
158
  * @param {Reference} reference A reference to check.
93
- * @returns {boolean} `true` if the reference is inside of the initializers.
159
+ * @returns {boolean} `true` if the reference is evaluated during the initialization.
94
160
  */
95
- function isInInitializer(variable, reference) {
96
- if (variable.scope !== reference.from) {
161
+ function isEvaluatedDuringInitialization(reference) {
162
+ if (isFromSeparateExecutionContext(reference)) {
163
+
164
+ /*
165
+ * Even if the reference appears in the initializer, it isn't evaluated during the initialization.
166
+ * For example, `const x = () => x;` is valid.
167
+ */
97
168
  return false;
98
169
  }
99
170
 
100
- let node = variable.identifiers[0].parent;
101
171
  const location = reference.identifier.range[1];
172
+ const definition = reference.resolved.defs[0];
173
+
174
+ if (definition.type === "ClassName") {
175
+
176
+ // `ClassDeclaration` or `ClassExpression`
177
+ const classDefinition = definition.node;
178
+
179
+ return (
180
+ isInRange(classDefinition, location) &&
181
+
182
+ /*
183
+ * Class binding is initialized before running static initializers.
184
+ * For example, `class C { static foo = C; static { bar = C; } }` is valid.
185
+ */
186
+ !isInClassStaticInitializerRange(classDefinition.body, location)
187
+ );
188
+ }
189
+
190
+ let node = definition.name.parent;
102
191
 
103
192
  while (node) {
104
193
  if (node.type === "VariableDeclarator") {
@@ -129,6 +218,7 @@ function isInInitializer(variable, reference) {
129
218
  // Rule Definition
130
219
  //------------------------------------------------------------------------------
131
220
 
221
+ /** @type {import('../shared/types').Rule} */
132
222
  module.exports = {
133
223
  meta: {
134
224
  type: "problem",
@@ -167,65 +257,77 @@ module.exports = {
167
257
  const options = parseOptions(context.options[0]);
168
258
 
169
259
  /**
170
- * Determines whether a given use-before-define case should be reported according to the options.
171
- * @param {eslint-scope.Variable} variable The variable that gets used before being defined
172
- * @param {eslint-scope.Reference} reference The reference to the variable
173
- * @returns {boolean} `true` if the usage should be reported
260
+ * Determines whether a given reference should be checked.
261
+ *
262
+ * Returns `false` if the reference is:
263
+ * - initialization's (e.g., `let a = 1`).
264
+ * - referring to an undefined variable (i.e., if it's an unresolved reference).
265
+ * - referring to a variable that is defined, but not in the given source code
266
+ * (e.g., global environment variable or `arguments` in functions).
267
+ * - allowed by options.
268
+ * @param {eslint-scope.Reference} reference The reference
269
+ * @returns {boolean} `true` if the reference should be checked
174
270
  */
175
- function isForbidden(variable, reference) {
176
- if (isFunction(variable)) {
177
- return options.functions;
271
+ function shouldCheck(reference) {
272
+ if (reference.init) {
273
+ return false;
178
274
  }
179
- if (isOuterClass(variable, reference)) {
180
- return options.classes;
275
+
276
+ const variable = reference.resolved;
277
+
278
+ if (!variable || variable.defs.length === 0) {
279
+ return false;
181
280
  }
182
- if (isOuterVariable(variable, reference)) {
183
- return options.variables;
281
+
282
+ const definitionType = variable.defs[0].type;
283
+
284
+ if (!options.functions && definitionType === "FunctionName") {
285
+ return false;
184
286
  }
287
+
288
+ if (
289
+ (
290
+ !options.variables && definitionType === "Variable" ||
291
+ !options.classes && definitionType === "ClassName"
292
+ ) &&
293
+
294
+ // don't skip checking the reference if it's in the same execution context, because of TDZ
295
+ isFromSeparateExecutionContext(reference)
296
+ ) {
297
+ return false;
298
+ }
299
+
185
300
  return true;
186
301
  }
187
302
 
188
303
  /**
189
- * Finds and validates all variables in a given scope.
190
- * @param {Scope} scope The scope object.
304
+ * Finds and validates all references in a given scope and its child scopes.
305
+ * @param {eslint-scope.Scope} scope The scope object.
191
306
  * @returns {void}
192
- * @private
193
307
  */
194
- function findVariablesInScope(scope) {
195
- scope.references.forEach(reference => {
308
+ function checkReferencesInScope(scope) {
309
+ scope.references.filter(shouldCheck).forEach(reference => {
196
310
  const variable = reference.resolved;
311
+ const definitionIdentifier = variable.defs[0].name;
197
312
 
198
- /*
199
- * Skips when the reference is:
200
- * - initialization's.
201
- * - referring to an undefined variable.
202
- * - referring to a global environment variable (there're no identifiers).
203
- * - located preceded by the variable (except in initializers).
204
- * - allowed by options.
205
- */
206
- if (reference.init ||
207
- !variable ||
208
- variable.identifiers.length === 0 ||
209
- (variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) ||
210
- !isForbidden(variable, reference)
313
+ if (
314
+ reference.identifier.range[1] < definitionIdentifier.range[1] ||
315
+ isEvaluatedDuringInitialization(reference)
211
316
  ) {
212
- return;
317
+ context.report({
318
+ node: reference.identifier,
319
+ messageId: "usedBeforeDefined",
320
+ data: reference.identifier
321
+ });
213
322
  }
214
-
215
- // Reports.
216
- context.report({
217
- node: reference.identifier,
218
- messageId: "usedBeforeDefined",
219
- data: reference.identifier
220
- });
221
323
  });
222
324
 
223
- scope.childScopes.forEach(findVariablesInScope);
325
+ scope.childScopes.forEach(checkReferencesInScope);
224
326
  }
225
327
 
226
328
  return {
227
329
  Program() {
228
- findVariablesInScope(context.getScope());
330
+ checkReferencesInScope(context.getScope());
229
331
  }
230
332
  };
231
333
  }
@@ -58,6 +58,7 @@ function isNegativeLookaround(node) {
58
58
  // Rule Definition
59
59
  //------------------------------------------------------------------------------
60
60
 
61
+ /** @type {import('../shared/types').Rule} */
61
62
  module.exports = {
62
63
  meta: {
63
64
  type: "problem",
@@ -49,6 +49,7 @@ function isValidThisArg(expectedThis, thisArg, sourceCode) {
49
49
  // Rule Definition
50
50
  //------------------------------------------------------------------------------
51
51
 
52
+ /** @type {import('../shared/types').Rule} */
52
53
  module.exports = {
53
54
  meta: {
54
55
  type: "suggestion",
@@ -9,6 +9,7 @@
9
9
  // Rule Definition
10
10
  //------------------------------------------------------------------------------
11
11
 
12
+ /** @type {import('../shared/types').Rule} */
12
13
  module.exports = {
13
14
  meta: {
14
15
  type: "suggestion",
@@ -85,6 +85,7 @@ function hasUselessComputedKey(node) {
85
85
  // Rule Definition
86
86
  //------------------------------------------------------------------------------
87
87
 
88
+ /** @type {import('../shared/types').Rule} */
88
89
  module.exports = {
89
90
  meta: {
90
91
  type: "suggestion",
@@ -64,6 +64,7 @@ function getRight(node) {
64
64
  // Rule Definition
65
65
  //------------------------------------------------------------------------------
66
66
 
67
+ /** @type {import('../shared/types').Rule} */
67
68
  module.exports = {
68
69
  meta: {
69
70
  type: "suggestion",
@@ -132,6 +132,7 @@ function isRedundantSuperCall(body, ctorParams) {
132
132
  // Rule Definition
133
133
  //------------------------------------------------------------------------------
134
134
 
135
+ /** @type {import('../shared/types').Rule} */
135
136
  module.exports = {
136
137
  meta: {
137
138
  type: "suggestion",
@@ -78,6 +78,7 @@ function parseRegExp(regExpText) {
78
78
  return charList;
79
79
  }
80
80
 
81
+ /** @type {import('../shared/types').Rule} */
81
82
  module.exports = {
82
83
  meta: {
83
84
  type: "suggestion",
@@ -15,6 +15,7 @@ const astUtils = require("./utils/ast-utils");
15
15
  // Rule Definition
16
16
  //------------------------------------------------------------------------------
17
17
 
18
+ /** @type {import('../shared/types').Rule} */
18
19
  module.exports = {
19
20
  meta: {
20
21
  type: "suggestion",
@@ -61,6 +61,7 @@ function isInFinally(node) {
61
61
  // Rule Definition
62
62
  //------------------------------------------------------------------------------
63
63
 
64
+ /** @type {import('../shared/types').Rule} */
64
65
  module.exports = {
65
66
  meta: {
66
67
  type: "suggestion",
@@ -179,6 +179,7 @@ function hasNameDisallowedForLetDeclarations(variable) {
179
179
  // Rule Definition
180
180
  //------------------------------------------------------------------------------
181
181
 
182
+ /** @type {import('../shared/types').Rule} */
182
183
  module.exports = {
183
184
  meta: {
184
185
  type: "suggestion",
@@ -8,6 +8,7 @@
8
8
  // Rule Definition
9
9
  //------------------------------------------------------------------------------
10
10
 
11
+ /** @type {import('../shared/types').Rule} */
11
12
  module.exports = {
12
13
  meta: {
13
14
  type: "suggestion",
@@ -14,6 +14,7 @@ const CHAR_LIMIT = 40;
14
14
  // Rule Definition
15
15
  //------------------------------------------------------------------------------
16
16
 
17
+ /** @type {import('../shared/types').Rule} */
17
18
  module.exports = {
18
19
  meta: {
19
20
  type: "suggestion",