@blumintinc/eslint-plugin-blumint 1.12.6 → 1.14.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 (258) hide show
  1. package/README.md +171 -99
  2. package/lib/index.js +300 -17
  3. package/lib/rules/array-methods-this-context.js +20 -2
  4. package/lib/rules/avoid-utils-directory.js +11 -2
  5. package/lib/rules/class-methods-read-top-to-bottom.js +24 -5
  6. package/lib/rules/consistent-callback-naming.js +1 -1
  7. package/lib/rules/dynamic-https-errors.d.ts +3 -1
  8. package/lib/rules/dynamic-https-errors.js +48 -11
  9. package/lib/rules/enforce-assert-safe-object-key.d.ts +8 -0
  10. package/lib/rules/{enforce-assertSafe-object-key.js → enforce-assert-safe-object-key.js} +52 -96
  11. package/lib/rules/enforce-assert-throws.d.ts +3 -1
  12. package/lib/rules/enforce-assert-throws.js +493 -51
  13. package/lib/rules/enforce-boolean-naming-prefixes.d.ts +3 -1
  14. package/lib/rules/enforce-boolean-naming-prefixes.js +820 -39
  15. package/lib/rules/enforce-callable-types.js +4 -4
  16. package/lib/rules/enforce-callback-memo.js +143 -18
  17. package/lib/rules/enforce-centralized-mock-firestore.js +5 -2
  18. package/lib/rules/enforce-console-error.d.ts +3 -0
  19. package/lib/rules/enforce-console-error.js +278 -0
  20. package/lib/rules/enforce-css-media-queries.js +24 -46
  21. package/lib/rules/enforce-dynamic-file-naming.d.ts +2 -0
  22. package/lib/rules/enforce-dynamic-file-naming.js +53 -28
  23. package/lib/rules/enforce-dynamic-firebase-imports.js +100 -19
  24. package/lib/rules/enforce-dynamic-imports.js +1 -1
  25. package/lib/rules/enforce-early-destructuring.d.ts +2 -0
  26. package/lib/rules/enforce-early-destructuring.js +980 -0
  27. package/lib/rules/enforce-empty-object-check.d.ts +11 -0
  28. package/lib/rules/enforce-empty-object-check.js +502 -0
  29. package/lib/rules/enforce-exported-function-types.js +4 -4
  30. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.d.ts +2 -0
  31. package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +262 -0
  32. package/lib/rules/enforce-firestore-doc-ref-generic.js +350 -3
  33. package/lib/rules/enforce-firestore-facade.js +349 -157
  34. package/lib/rules/enforce-firestore-rules-get-access.d.ts +3 -0
  35. package/lib/rules/enforce-firestore-rules-get-access.js +109 -0
  36. package/lib/rules/enforce-firestore-set-merge.js +3 -4
  37. package/lib/rules/enforce-global-constants.d.ts +4 -1
  38. package/lib/rules/enforce-global-constants.js +240 -12
  39. package/lib/rules/enforce-identifiable-firestore-type.js +108 -58
  40. package/lib/rules/enforce-memoize-async.d.ts +2 -1
  41. package/lib/rules/enforce-memoize-async.js +92 -27
  42. package/lib/rules/enforce-memoize-getters.d.ts +3 -0
  43. package/lib/rules/enforce-memoize-getters.js +147 -0
  44. package/lib/rules/enforce-microdiff.js +3 -2
  45. package/lib/rules/enforce-object-literal-as-const.js +4 -4
  46. package/lib/rules/enforce-positive-naming.js +9 -7
  47. package/lib/rules/enforce-props-argument-name.d.ts +2 -7
  48. package/lib/rules/enforce-props-argument-name.js +165 -151
  49. package/lib/rules/enforce-props-naming-consistency.d.ts +2 -0
  50. package/lib/rules/enforce-props-naming-consistency.js +145 -0
  51. package/lib/rules/enforce-querykey-ts.d.ts +9 -0
  52. package/lib/rules/enforce-querykey-ts.js +274 -0
  53. package/lib/rules/enforce-safe-stringify.js +1 -1
  54. package/lib/rules/enforce-serializable-params.js +3 -3
  55. package/lib/rules/enforce-singular-type-names.js +10 -6
  56. package/lib/rules/enforce-stable-hash-spread-props.d.ts +13 -0
  57. package/lib/rules/enforce-stable-hash-spread-props.js +342 -0
  58. package/lib/rules/enforce-storage-context.d.ts +9 -0
  59. package/lib/rules/enforce-storage-context.js +646 -0
  60. package/lib/rules/enforce-timestamp-now.js +23 -7
  61. package/lib/rules/enforce-transform-memoization.d.ts +4 -0
  62. package/lib/rules/enforce-transform-memoization.js +416 -0
  63. package/lib/rules/enforce-typescript-markdown-code-blocks.d.ts +1 -0
  64. package/lib/rules/enforce-typescript-markdown-code-blocks.js +100 -0
  65. package/lib/rules/enforce-unique-cursor-headers.d.ts +16 -0
  66. package/lib/rules/enforce-unique-cursor-headers.js +365 -0
  67. package/lib/rules/enforce-verb-noun-naming.js +90 -14
  68. package/lib/rules/ensure-pointer-events-none.js +28 -2
  69. package/lib/rules/export-if-in-doubt.js +27 -4
  70. package/lib/rules/extract-global-constants.js +92 -53
  71. package/lib/rules/fast-deep-equal-over-microdiff.d.ts +2 -1
  72. package/lib/rules/fast-deep-equal-over-microdiff.js +351 -83
  73. package/lib/rules/firestore-transaction-reads-before-writes.d.ts +1 -0
  74. package/lib/rules/firestore-transaction-reads-before-writes.js +277 -0
  75. package/lib/rules/flatten-push-calls.d.ts +2 -0
  76. package/lib/rules/flatten-push-calls.js +428 -0
  77. package/lib/rules/generic-starts-with-t.js +8 -2
  78. package/lib/rules/global-const-style.js +50 -19
  79. package/lib/rules/jsdoc-above-field.d.ts +11 -0
  80. package/lib/rules/jsdoc-above-field.js +208 -0
  81. package/lib/rules/key-only-outermost-element.js +21 -3
  82. package/lib/rules/logical-top-to-bottom-grouping.d.ts +5 -0
  83. package/lib/rules/logical-top-to-bottom-grouping.js +1258 -0
  84. package/lib/rules/memo-compare-deeply-complex-props.d.ts +3 -0
  85. package/lib/rules/memo-compare-deeply-complex-props.js +788 -0
  86. package/lib/rules/memo-nested-react-components.d.ts +8 -0
  87. package/lib/rules/memo-nested-react-components.js +410 -0
  88. package/lib/rules/memoize-root-level-hocs.d.ts +7 -0
  89. package/lib/rules/memoize-root-level-hocs.js +242 -0
  90. package/lib/rules/no-always-true-false-conditions.d.ts +2 -1
  91. package/lib/rules/no-always-true-false-conditions.js +68 -8
  92. package/lib/rules/no-array-length-in-deps.d.ts +12 -0
  93. package/lib/rules/no-array-length-in-deps.js +314 -0
  94. package/lib/rules/no-async-array-filter.js +5 -2
  95. package/lib/rules/no-async-foreach.js +210 -12
  96. package/lib/rules/no-circular-references.js +18 -17
  97. package/lib/rules/no-class-instance-destructuring.js +55 -12
  98. package/lib/rules/no-complex-cloud-params.js +22 -5
  99. package/lib/rules/no-compositing-layer-props.js +6 -4
  100. package/lib/rules/no-conditional-literals-in-jsx.js +37 -12
  101. package/lib/rules/no-console-error.d.ts +9 -0
  102. package/lib/rules/no-console-error.js +525 -0
  103. package/lib/rules/no-curly-brackets-around-commented-properties.d.ts +2 -0
  104. package/lib/rules/no-curly-brackets-around-commented-properties.js +258 -0
  105. package/lib/rules/no-empty-dependency-use-callbacks.d.ts +11 -0
  106. package/lib/rules/no-empty-dependency-use-callbacks.js +576 -0
  107. package/lib/rules/no-entire-object-hook-deps.d.ts +3 -1
  108. package/lib/rules/no-entire-object-hook-deps.js +320 -68
  109. package/lib/rules/no-excessive-parent-chain.d.ts +5 -0
  110. package/lib/rules/no-excessive-parent-chain.js +273 -0
  111. package/lib/rules/no-explicit-return-type.d.ts +2 -1
  112. package/lib/rules/no-explicit-return-type.js +215 -26
  113. package/lib/rules/no-filter-without-return.js +5 -1
  114. package/lib/rules/no-firestore-jest-mock.d.ts +2 -1
  115. package/lib/rules/no-firestore-jest-mock.js +126 -8
  116. package/lib/rules/no-firestore-object-arrays.js +398 -28
  117. package/lib/rules/no-handler-suffix.d.ts +12 -0
  118. package/lib/rules/no-handler-suffix.js +305 -0
  119. package/lib/rules/no-hungarian.js +14 -14
  120. package/lib/rules/no-inline-component-prop.d.ts +10 -0
  121. package/lib/rules/no-inline-component-prop.js +456 -0
  122. package/lib/rules/no-jsx-in-hooks.js +6 -1
  123. package/lib/rules/no-jsx-whitespace-literal.js +8 -2
  124. package/lib/rules/no-margin-properties.d.ts +7 -1
  125. package/lib/rules/no-margin-properties.js +22 -9
  126. package/lib/rules/no-memoize-on-static.js +9 -1
  127. package/lib/rules/no-misleading-boolean-prefixes.d.ts +7 -0
  128. package/lib/rules/no-misleading-boolean-prefixes.js +331 -0
  129. package/lib/rules/no-misused-switch-case.js +22 -1
  130. package/lib/rules/no-mixed-firestore-transactions.d.ts +3 -1
  131. package/lib/rules/no-mixed-firestore-transactions.js +296 -34
  132. package/lib/rules/no-mock-firebase-admin.js +5 -2
  133. package/lib/rules/no-object-values-on-strings.js +10 -2
  134. package/lib/rules/no-overridable-method-calls-in-constructor.d.ts +1 -0
  135. package/lib/rules/no-overridable-method-calls-in-constructor.js +272 -0
  136. package/lib/rules/no-passthrough-getters.d.ts +4 -0
  137. package/lib/rules/no-passthrough-getters.js +206 -0
  138. package/lib/rules/no-redundant-annotation-assertion.d.ts +2 -0
  139. package/lib/rules/no-redundant-annotation-assertion.js +402 -0
  140. package/lib/rules/no-redundant-param-types.js +16 -6
  141. package/lib/rules/no-redundant-this-params.d.ts +3 -0
  142. package/lib/rules/no-redundant-this-params.js +459 -0
  143. package/lib/rules/no-redundant-usecallback-wrapper.d.ts +8 -0
  144. package/lib/rules/no-redundant-usecallback-wrapper.js +328 -0
  145. package/lib/rules/no-res-error-status-in-onrequest.d.ts +4 -0
  146. package/lib/rules/no-res-error-status-in-onrequest.js +521 -0
  147. package/lib/rules/no-restricted-properties-fix.d.ts +12 -0
  148. package/lib/rules/no-restricted-properties-fix.js +173 -0
  149. package/lib/rules/no-separate-loading-state.d.ts +8 -0
  150. package/lib/rules/no-separate-loading-state.js +133 -0
  151. package/lib/rules/no-stale-state-across-await.d.ts +1 -0
  152. package/lib/rules/no-stale-state-across-await.js +185 -0
  153. package/lib/rules/no-static-constants-in-dynamic-files.d.ts +3 -0
  154. package/lib/rules/no-static-constants-in-dynamic-files.js +149 -0
  155. package/lib/rules/no-try-catch-already-exists-in-transaction.d.ts +1 -0
  156. package/lib/rules/no-try-catch-already-exists-in-transaction.js +342 -0
  157. package/lib/rules/no-type-assertion-returns.js +49 -49
  158. package/lib/rules/no-undefined-null-passthrough.js +217 -40
  159. package/lib/rules/no-unmemoized-memo-without-props.d.ts +8 -0
  160. package/lib/rules/no-unmemoized-memo-without-props.js +426 -0
  161. package/lib/rules/no-unnecessary-destructuring-rename.d.ts +2 -0
  162. package/lib/rules/no-unnecessary-destructuring-rename.js +347 -0
  163. package/lib/rules/no-unnecessary-destructuring.js +14 -4
  164. package/lib/rules/no-unnecessary-verb-suffix.js +2 -3
  165. package/lib/rules/no-unpinned-dependencies.js +36 -5
  166. package/lib/rules/no-unsafe-firestore-spread.js +8 -5
  167. package/lib/rules/no-unused-props.d.ts +5 -2
  168. package/lib/rules/no-unused-props.js +451 -112
  169. package/lib/rules/no-unused-usestate.js +6 -2
  170. package/lib/rules/no-useless-fragment.js +28 -2
  171. package/lib/rules/no-useless-usememo-primitives.d.ts +9 -0
  172. package/lib/rules/no-useless-usememo-primitives.js +393 -0
  173. package/lib/rules/no-usememo-for-pass-by-value.d.ts +13 -0
  174. package/lib/rules/no-usememo-for-pass-by-value.js +757 -0
  175. package/lib/rules/no-uuidv4-base62-as-key.js +18 -13
  176. package/lib/rules/omit-index-html.d.ts +2 -1
  177. package/lib/rules/omit-index-html.js +62 -7
  178. package/lib/rules/optimize-object-boolean-conditions.d.ts +1 -0
  179. package/lib/rules/optimize-object-boolean-conditions.js +236 -0
  180. package/lib/rules/parallelize-async-operations.d.ts +8 -0
  181. package/lib/rules/parallelize-async-operations.js +394 -0
  182. package/lib/rules/prefer-batch-operations.d.ts +1 -3
  183. package/lib/rules/prefer-batch-operations.js +228 -35
  184. package/lib/rules/prefer-block-comments-for-declarations.js +22 -7
  185. package/lib/rules/prefer-clone-deep.js +3 -3
  186. package/lib/rules/prefer-destructuring-no-class.d.ts +2 -1
  187. package/lib/rules/prefer-destructuring-no-class.js +244 -59
  188. package/lib/rules/prefer-docsetter-setall.d.ts +2 -0
  189. package/lib/rules/prefer-docsetter-setall.js +243 -0
  190. package/lib/rules/prefer-document-flattening.d.ts +4 -0
  191. package/lib/rules/prefer-document-flattening.js +239 -0
  192. package/lib/rules/prefer-field-paths-in-transforms.d.ts +7 -0
  193. package/lib/rules/prefer-field-paths-in-transforms.js +251 -0
  194. package/lib/rules/prefer-fragment-component.js +4 -4
  195. package/lib/rules/prefer-fragment-shorthand.js +2 -1
  196. package/lib/rules/prefer-getter-over-parameterless-method.d.ts +13 -0
  197. package/lib/rules/prefer-getter-over-parameterless-method.js +648 -0
  198. package/lib/rules/prefer-global-router-state-key.d.ts +7 -3
  199. package/lib/rules/prefer-global-router-state-key.js +305 -31
  200. package/lib/rules/prefer-memoized-props.d.ts +3 -0
  201. package/lib/rules/prefer-memoized-props.js +445 -0
  202. package/lib/rules/prefer-next-dynamic.d.ts +9 -0
  203. package/lib/rules/prefer-next-dynamic.js +357 -0
  204. package/lib/rules/prefer-nullish-coalescing-boolean-props.d.ts +1 -0
  205. package/lib/rules/prefer-nullish-coalescing-boolean-props.js +435 -0
  206. package/lib/rules/prefer-nullish-coalescing-override.d.ts +7 -0
  207. package/lib/rules/prefer-nullish-coalescing-override.js +188 -0
  208. package/lib/rules/prefer-params-over-parent-id.d.ts +5 -0
  209. package/lib/rules/prefer-params-over-parent-id.js +277 -0
  210. package/lib/rules/prefer-settings-object.js +23 -15
  211. package/lib/rules/prefer-type-alias-over-typeof-constant.d.ts +3 -0
  212. package/lib/rules/prefer-type-alias-over-typeof-constant.js +259 -0
  213. package/lib/rules/prefer-type-over-interface.js +7 -2
  214. package/lib/rules/prefer-url-tostring-over-tojson.d.ts +2 -0
  215. package/lib/rules/prefer-url-tostring-over-tojson.js +169 -0
  216. package/lib/rules/prefer-use-deep-compare-memo.d.ts +4 -0
  217. package/lib/rules/prefer-use-deep-compare-memo.js +431 -0
  218. package/lib/rules/prefer-usecallback-over-usememo-for-functions.js +25 -2
  219. package/lib/rules/prefer-usememo-over-useeffect-usestate.js +24 -5
  220. package/lib/rules/prefer-utility-function-over-private-static.js +34 -2
  221. package/lib/rules/prevent-children-clobber.d.ts +2 -0
  222. package/lib/rules/prevent-children-clobber.js +536 -0
  223. package/lib/rules/react-memoize-literals.d.ts +4 -0
  224. package/lib/rules/react-memoize-literals.js +495 -0
  225. package/lib/rules/react-usememo-should-be-component.d.ts +2 -1
  226. package/lib/rules/react-usememo-should-be-component.js +144 -78
  227. package/lib/rules/require-dynamic-firebase-imports.js +2 -1
  228. package/lib/rules/require-hooks-default-params.js +17 -16
  229. package/lib/rules/require-https-error-cause.d.ts +4 -0
  230. package/lib/rules/require-https-error-cause.js +136 -0
  231. package/lib/rules/require-https-error.js +43 -21
  232. package/lib/rules/require-image-optimized.js +2 -2
  233. package/lib/rules/require-memo.js +12 -2
  234. package/lib/rules/require-memoize-jsx-returners.d.ts +3 -0
  235. package/lib/rules/require-memoize-jsx-returners.js +485 -0
  236. package/lib/rules/require-usememo-object-literals.js +9 -4
  237. package/lib/rules/semantic-function-prefixes.js +38 -18
  238. package/lib/rules/sync-onwrite-name-func.js +5 -1
  239. package/lib/rules/test-file-location-enforcement.d.ts +1 -0
  240. package/lib/rules/test-file-location-enforcement.js +57 -0
  241. package/lib/rules/use-custom-link.js +6 -1
  242. package/lib/rules/use-custom-router.js +6 -1
  243. package/lib/rules/use-latest-callback.d.ts +3 -0
  244. package/lib/rules/use-latest-callback.js +271 -0
  245. package/lib/rules/vertically-group-related-functions.d.ts +16 -0
  246. package/lib/rules/vertically-group-related-functions.js +480 -0
  247. package/lib/utils/ASTHelpers.d.ts +13 -1
  248. package/lib/utils/ASTHelpers.js +34 -0
  249. package/lib/utils/createRule.js +1 -1
  250. package/lib/utils/getMethodName.d.ts +27 -0
  251. package/lib/utils/getMethodName.js +35 -0
  252. package/lib/utils/graph/ClassGraphSorterReadability.js +1 -1
  253. package/lib/utils/ruleTester.d.ts +1 -0
  254. package/lib/utils/ruleTester.js +4 -1
  255. package/lib/utils/tsTypeClassifier.d.ts +30 -0
  256. package/lib/utils/tsTypeClassifier.js +149 -0
  257. package/package.json +23 -14
  258. package/lib/rules/enforce-assertSafe-object-key.d.ts +0 -2
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noOverridableMethodCallsInConstructor = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ const getMethodName_1 = require("../utils/getMethodName");
7
+ exports.noOverridableMethodCallsInConstructor = (0, createRule_1.createRule)({
8
+ name: 'no-overridable-method-calls-in-constructor',
9
+ meta: {
10
+ type: 'problem',
11
+ docs: {
12
+ description: 'Disallow calling overridable methods in constructors to prevent unexpected behavior',
13
+ recommended: 'error',
14
+ },
15
+ fixable: undefined,
16
+ schema: [],
17
+ messages: {
18
+ noOverridableMethodCallsInConstructor: 'What\'s wrong: Constructor calls overridable or abstract {{target}} member "{{methodName}}". \u2192 Why it matters: This executes subclass overrides before the subclass constructor finishes initializing its fields, which can read undefined state or run side effects on a partially constructed instance. \u2192 How to fix: Move the call to a post-construction initializer, or make "{{methodName}}" private or static so construction never executes overridable code.',
19
+ },
20
+ },
21
+ defaultOptions: [],
22
+ create(context) {
23
+ const sourceCode = context.getSourceCode();
24
+ /**
25
+ * Checks if a method is overridable (not private and not static)
26
+ */
27
+ function isOverridableMethod(node) {
28
+ // Private methods are not overridable
29
+ if (node.accessibility === 'private') {
30
+ return false;
31
+ }
32
+ // ES private methods (#foo) are non-overridable
33
+ if (node.key.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
34
+ return false;
35
+ }
36
+ // Static methods are not overridable in the same way as instance methods
37
+ if (node.static) {
38
+ return false;
39
+ }
40
+ return true;
41
+ }
42
+ /**
43
+ * Checks if a method is abstract
44
+ */
45
+ function isAbstractMethod(node) {
46
+ return node.abstract === true;
47
+ }
48
+ /**
49
+ * Collects all method names from a class, categorized by whether they are overridable
50
+ */
51
+ function collectMethodNames(classNode) {
52
+ const overridableMethods = new Set();
53
+ const abstractMethods = new Set();
54
+ for (const member of classNode.body.body) {
55
+ if (member.type === utils_1.AST_NODE_TYPES.MethodDefinition) {
56
+ const methodName = getMethodNameFromDefinition(member);
57
+ if (methodName) {
58
+ if (isAbstractMethod(member)) {
59
+ abstractMethods.add(methodName);
60
+ }
61
+ else if (isOverridableMethod(member)) {
62
+ overridableMethods.add(methodName);
63
+ }
64
+ }
65
+ }
66
+ else if (member.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition) {
67
+ const methodName = getMethodNameFromDefinition(member);
68
+ if (methodName) {
69
+ abstractMethods.add(methodName);
70
+ }
71
+ }
72
+ }
73
+ return { overridableMethods, abstractMethods };
74
+ }
75
+ /**
76
+ * Gets the method name from a method definition
77
+ */
78
+ function getMethodNameFromDefinition(method) {
79
+ const name = (0, getMethodName_1.getMethodName)(method, sourceCode, {
80
+ computedFallbackToText: false,
81
+ });
82
+ return name || null; // Computed property names are not handled
83
+ }
84
+ /**
85
+ * Checks if a call expression is calling a method on 'this' or 'super'
86
+ */
87
+ function isThisOrSuperMethodCall(node) {
88
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
89
+ !node.callee.computed // Ignore computed properties like this[methodName]()
90
+ ) {
91
+ const object = node.callee.object;
92
+ const property = node.callee.property;
93
+ // Check if it's a call on 'this'
94
+ if (object.type === utils_1.AST_NODE_TYPES.ThisExpression &&
95
+ property.type === utils_1.AST_NODE_TYPES.Identifier) {
96
+ return {
97
+ isMethodCall: true,
98
+ methodName: property.name,
99
+ isSuper: false,
100
+ };
101
+ }
102
+ // Check if it's a call on 'super'
103
+ if (object.type === utils_1.AST_NODE_TYPES.Super &&
104
+ property.type === utils_1.AST_NODE_TYPES.Identifier) {
105
+ return {
106
+ isMethodCall: true,
107
+ methodName: property.name,
108
+ isSuper: true,
109
+ };
110
+ }
111
+ // Check for method chaining: this.method().anotherMethod()
112
+ // In this case, object is a CallExpression
113
+ if (object.type === utils_1.AST_NODE_TYPES.CallExpression) {
114
+ const nestedCall = isThisOrSuperMethodCall(object);
115
+ if (nestedCall.isMethodCall) {
116
+ return nestedCall; // Return the nested method call info
117
+ }
118
+ }
119
+ }
120
+ return { isMethodCall: false, methodName: null, isSuper: false };
121
+ }
122
+ /**
123
+ * Checks if a member expression is accessing a property on 'this' or 'super'
124
+ */
125
+ function isThisOrSuperPropertyAccess(node) {
126
+ if (!node.computed) {
127
+ // Ignore computed properties like this[propertyName]
128
+ const object = node.object;
129
+ const property = node.property;
130
+ // Check if it's access on 'this'
131
+ if (object.type === utils_1.AST_NODE_TYPES.ThisExpression &&
132
+ property.type === utils_1.AST_NODE_TYPES.Identifier) {
133
+ // Skip 'constructor' property as it's not an overridable method
134
+ if (property.name === 'constructor') {
135
+ return {
136
+ isPropertyAccess: false,
137
+ propertyName: null,
138
+ isSuper: false,
139
+ };
140
+ }
141
+ return {
142
+ isPropertyAccess: true,
143
+ propertyName: property.name,
144
+ isSuper: false,
145
+ };
146
+ }
147
+ // Check if it's access on 'super'
148
+ if (object.type === utils_1.AST_NODE_TYPES.Super &&
149
+ property.type === utils_1.AST_NODE_TYPES.Identifier) {
150
+ return {
151
+ isPropertyAccess: true,
152
+ propertyName: property.name,
153
+ isSuper: true,
154
+ };
155
+ }
156
+ }
157
+ return { isPropertyAccess: false, propertyName: null, isSuper: false };
158
+ }
159
+ return {
160
+ // Process class declarations and expressions
161
+ 'ClassDeclaration, ClassExpression'(node) {
162
+ const { overridableMethods, abstractMethods } = collectMethodNames(node);
163
+ // Find the constructor method
164
+ const ctorMethod = node.body.body.find((member) => member.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
165
+ member.kind === 'constructor');
166
+ if (!ctorMethod || !ctorMethod.value.body) {
167
+ return; // No constructor or constructor has no body
168
+ }
169
+ // Function to recursively check for method calls in the constructor
170
+ function checkForMethodCalls(bodyNode) {
171
+ if (!bodyNode || typeof bodyNode !== 'object') {
172
+ return;
173
+ }
174
+ // Check for method calls
175
+ if (bodyNode.type === utils_1.AST_NODE_TYPES.CallExpression) {
176
+ const { isMethodCall, methodName, isSuper } = isThisOrSuperMethodCall(bodyNode);
177
+ if (isMethodCall && methodName) {
178
+ // Abstract methods are always a problem when called from constructor
179
+ // This includes super calls to abstract methods
180
+ if (abstractMethods.has(methodName)) {
181
+ context.report({
182
+ node: bodyNode,
183
+ messageId: 'noOverridableMethodCallsInConstructor',
184
+ data: {
185
+ methodName,
186
+ target: isSuper ? 'super' : 'this',
187
+ },
188
+ });
189
+ }
190
+ // Overridable methods are a problem when called on 'this'
191
+ else if (overridableMethods.has(methodName) && !isSuper) {
192
+ context.report({
193
+ node: bodyNode,
194
+ messageId: 'noOverridableMethodCallsInConstructor',
195
+ data: {
196
+ methodName,
197
+ target: 'this',
198
+ },
199
+ });
200
+ }
201
+ }
202
+ }
203
+ // Check for property access (getters/setters) - only if not part of a call expression
204
+ else if (bodyNode.type === utils_1.AST_NODE_TYPES.MemberExpression) {
205
+ // Check if this MemberExpression is the callee of a CallExpression
206
+ // If so, skip it as it will be handled by the CallExpression check
207
+ const parent = bodyNode.parent;
208
+ if (parent &&
209
+ parent.type === utils_1.AST_NODE_TYPES.CallExpression &&
210
+ parent.callee === bodyNode) {
211
+ return; // Skip this MemberExpression as it's part of a method call
212
+ }
213
+ const { isPropertyAccess, propertyName, isSuper } = isThisOrSuperPropertyAccess(bodyNode);
214
+ if (isPropertyAccess && propertyName) {
215
+ // Abstract methods are always a problem when accessed from constructor
216
+ if (abstractMethods.has(propertyName)) {
217
+ context.report({
218
+ node: bodyNode,
219
+ messageId: 'noOverridableMethodCallsInConstructor',
220
+ data: {
221
+ methodName: propertyName,
222
+ target: isSuper ? 'super' : 'this',
223
+ },
224
+ });
225
+ }
226
+ // Overridable methods are a problem when accessed on 'this'
227
+ else if (overridableMethods.has(propertyName) && !isSuper) {
228
+ context.report({
229
+ node: bodyNode,
230
+ messageId: 'noOverridableMethodCallsInConstructor',
231
+ data: {
232
+ methodName: propertyName,
233
+ target: 'this',
234
+ },
235
+ });
236
+ }
237
+ }
238
+ }
239
+ // Avoid circular references by not checking 'parent' property
240
+ const keysToSkip = new Set(['parent', 'loc', 'range']);
241
+ // Don't traverse into function expressions or arrow functions as they create new scopes
242
+ if (bodyNode.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
243
+ bodyNode.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
244
+ bodyNode.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
245
+ return;
246
+ }
247
+ // Recursively check all child nodes
248
+ for (const key in bodyNode) {
249
+ if (keysToSkip.has(key))
250
+ continue;
251
+ const child = bodyNode[key];
252
+ if (child && typeof child === 'object') {
253
+ if ('type' in child) {
254
+ checkForMethodCalls(child);
255
+ }
256
+ else if (Array.isArray(child)) {
257
+ child.forEach((item) => {
258
+ if (item && typeof item === 'object' && 'type' in item) {
259
+ checkForMethodCalls(item);
260
+ }
261
+ });
262
+ }
263
+ }
264
+ }
265
+ }
266
+ // Start checking from the constructor body
267
+ checkForMethodCalls(ctorMethod.value.body);
268
+ },
269
+ };
270
+ },
271
+ });
272
+ //# sourceMappingURL=no-overridable-method-calls-in-constructor.js.map
@@ -0,0 +1,4 @@
1
+ import { TSESTree } from '@typescript-eslint/utils';
2
+ export declare const noPassthroughGetters: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"noPassthroughGetter", never[], {
3
+ MethodDefinition(node: TSESTree.MethodDefinition): void;
4
+ }>;
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noPassthroughGetters = void 0;
4
+ const createRule_1 = require("../utils/createRule");
5
+ const utils_1 = require("@typescript-eslint/utils");
6
+ const getMethodName_1 = require("../utils/getMethodName");
7
+ const COMPLEX_EXPRESSION_TYPES = new Set([
8
+ utils_1.AST_NODE_TYPES.CallExpression,
9
+ utils_1.AST_NODE_TYPES.TemplateLiteral,
10
+ utils_1.AST_NODE_TYPES.NewExpression,
11
+ utils_1.AST_NODE_TYPES.BinaryExpression,
12
+ utils_1.AST_NODE_TYPES.ArrayExpression,
13
+ utils_1.AST_NODE_TYPES.ObjectExpression,
14
+ ]);
15
+ exports.noPassthroughGetters = (0, createRule_1.createRule)({
16
+ create(context) {
17
+ const sourceCode = context.getSourceCode();
18
+ return {
19
+ // Target getter methods in classes
20
+ MethodDefinition(node) {
21
+ // Only check getter methods
22
+ if (node.kind !== 'get') {
23
+ return;
24
+ }
25
+ // Skip if the getter has decorators (like @Memoize)
26
+ if (node.decorators && node.decorators.length > 0) {
27
+ return;
28
+ }
29
+ const methodBody = node.value.body;
30
+ if (!methodBody) {
31
+ return;
32
+ }
33
+ // Check if the getter body is a simple return statement
34
+ if (methodBody.body.length === 1 &&
35
+ methodBody.body[0].type === 'ReturnStatement') {
36
+ const returnStatement = methodBody
37
+ .body[0];
38
+ // Skip if there's no return argument
39
+ if (!returnStatement.argument) {
40
+ return;
41
+ }
42
+ // Skip if the return statement uses super
43
+ if (containsSuper(returnStatement.argument)) {
44
+ return;
45
+ }
46
+ // Skip if the return statement includes type assertions or casting
47
+ if (hasTypeAssertion(returnStatement.argument)) {
48
+ return;
49
+ }
50
+ // Skip if the return statement includes null/undefined handling
51
+ if (hasNullUndefinedHandling(returnStatement.argument)) {
52
+ return;
53
+ }
54
+ // Skip if the return statement includes computed property access or function calls
55
+ if (hasComputedPropertyOrFunctionCall(returnStatement.argument)) {
56
+ return;
57
+ }
58
+ // Check if the return statement is accessing a property from a constructor parameter
59
+ if (isConstructorParameterPropertyAccess(returnStatement.argument)) {
60
+ const getterName = (0, getMethodName_1.getMethodName)(node, sourceCode, {
61
+ computedFallbackToText: false,
62
+ }) || 'getter';
63
+ const propertyPath = getMemberPath(returnStatement.argument) ??
64
+ 'nested property on a constructor-injected object';
65
+ context.report({
66
+ node,
67
+ messageId: 'noPassthroughGetter',
68
+ data: {
69
+ getterName,
70
+ propertyPath,
71
+ },
72
+ });
73
+ }
74
+ }
75
+ },
76
+ };
77
+ /**
78
+ * Check if the node is a simple property access from a constructor parameter
79
+ * like this.settings.property or this.settings['property'] or this.settings.nested.deep.property
80
+ */
81
+ function isConstructorParameterPropertyAccess(node) {
82
+ // Check for member expressions like this.settings.property
83
+ if (node.type === 'MemberExpression') {
84
+ return isConstructorParameterAccess(node);
85
+ }
86
+ return false;
87
+ }
88
+ /**
89
+ * Check if the node is accessing a property from a constructor parameter
90
+ * Patterns to match: this.constructorParam.property, this.constructorParam['property'], this.constructorParam.nested.deep.property
91
+ * Patterns to NOT match: this.property, SomeClass.property, this.methodCall()
92
+ */
93
+ function isConstructorParameterAccess(node) {
94
+ let current = node.object;
95
+ let depth = 0;
96
+ // Walk up member expressions until we reach a base
97
+ while (current && current.type === 'MemberExpression') {
98
+ depth += 1;
99
+ current = current.object;
100
+ }
101
+ // Require at least one nesting and a base of `this`
102
+ return depth >= 1 && current?.type === 'ThisExpression';
103
+ }
104
+ /**
105
+ * Check if the node contains a reference to super
106
+ */
107
+ function containsSuper(node) {
108
+ let current = node;
109
+ while (current && current.type === 'MemberExpression') {
110
+ if (current.object.type === 'Super') {
111
+ return true;
112
+ }
113
+ current = current.object;
114
+ }
115
+ return false;
116
+ }
117
+ function getMemberPath(node) {
118
+ if (node.type === 'ThisExpression') {
119
+ return 'this';
120
+ }
121
+ if (node.type === 'Identifier') {
122
+ return node.name;
123
+ }
124
+ if (node.type !== 'MemberExpression') {
125
+ return null;
126
+ }
127
+ const objectPath = getMemberPath(node.object);
128
+ if (!objectPath) {
129
+ return null;
130
+ }
131
+ if (node.computed && node.property.type === 'Literal') {
132
+ const literalValue = typeof node.property.value === 'string'
133
+ ? JSON.stringify(node.property.value)
134
+ : String(node.property.value);
135
+ return `${objectPath}[${literalValue}]`;
136
+ }
137
+ if (node.property.type === 'Identifier') {
138
+ return `${objectPath}.${node.property.name}`;
139
+ }
140
+ return null;
141
+ }
142
+ /**
143
+ * Check if the node has a type assertion or casting
144
+ */
145
+ function hasTypeAssertion(node) {
146
+ if (node.type === 'TSAsExpression' || node.type === 'TSTypeAssertion') {
147
+ return true;
148
+ }
149
+ if (node.type === 'MemberExpression') {
150
+ return hasTypeAssertion(node.object);
151
+ }
152
+ return false;
153
+ }
154
+ /**
155
+ * Check if the node handles null/undefined values
156
+ */
157
+ function hasNullUndefinedHandling(node) {
158
+ // Check for logical expressions like this.settings.property || []
159
+ if (node.type === 'LogicalExpression') {
160
+ return true;
161
+ }
162
+ // Check for conditional expressions like this.settings.property ? this.settings.property : []
163
+ if (node.type === 'ConditionalExpression') {
164
+ return true;
165
+ }
166
+ // Check for optional chaining like this.settings?.property
167
+ if (node.type === 'MemberExpression' && node.optional) {
168
+ return true;
169
+ }
170
+ // The nullish coalescing check is already covered by the LogicalExpression check above
171
+ return false;
172
+ }
173
+ /**
174
+ * Check if the node includes computed property access or function calls
175
+ */
176
+ function hasComputedPropertyOrFunctionCall(node) {
177
+ if (COMPLEX_EXPRESSION_TYPES.has(node.type)) {
178
+ return true;
179
+ }
180
+ // Check for member expressions with computed properties like this.settings[key]
181
+ if (node.type === 'MemberExpression') {
182
+ // If the property is computed with a dynamic expression (not a literal), it's not a simple property access
183
+ if (node.computed && node.property.type !== 'Literal') {
184
+ return true;
185
+ }
186
+ // Recursively check the object part
187
+ return hasComputedPropertyOrFunctionCall(node.object);
188
+ }
189
+ return false;
190
+ }
191
+ },
192
+ name: 'no-passthrough-getters',
193
+ meta: {
194
+ type: 'suggestion',
195
+ docs: {
196
+ description: 'Avoid getter methods that only re-expose nested properties on constructor-injected objects without adding behavior',
197
+ recommended: 'error',
198
+ },
199
+ schema: [],
200
+ messages: {
201
+ noPassthroughGetter: 'Getter "{{getterName}}" only forwards nested property "{{propertyPath}}" from an object provided via the constructor. This indirection hides the real source of state and expands the class API without adding behavior. Read the constructor-injected object directly or add logic that justifies a getter (validation, memoization, fallback).',
202
+ },
203
+ },
204
+ defaultOptions: [],
205
+ });
206
+ //# sourceMappingURL=no-passthrough-getters.js.map
@@ -0,0 +1,2 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ export declare const noRedundantAnnotationAssertion: TSESLint.RuleModule<"redundantAnnotationAndAssertion", [], TSESLint.RuleListener>;