@trackunit/eslint-plugin-trackunit 0.0.2

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 (147) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +117 -0
  3. package/package.json +31 -0
  4. package/src/index.d.ts +8 -0
  5. package/src/index.js +20 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/config/fragments/ignores.d.ts +2 -0
  8. package/src/lib/config/fragments/ignores.js +18 -0
  9. package/src/lib/config/fragments/ignores.js.map +1 -0
  10. package/src/lib/config/fragments/import-rules.d.ts +3 -0
  11. package/src/lib/config/fragments/import-rules.js +58 -0
  12. package/src/lib/config/fragments/import-rules.js.map +1 -0
  13. package/src/lib/config/fragments/jest-overrides.d.ts +2 -0
  14. package/src/lib/config/fragments/jest-overrides.js +30 -0
  15. package/src/lib/config/fragments/jest-overrides.js.map +1 -0
  16. package/src/lib/config/fragments/jsdoc-rules.d.ts +3 -0
  17. package/src/lib/config/fragments/jsdoc-rules.js +71 -0
  18. package/src/lib/config/fragments/jsdoc-rules.js.map +1 -0
  19. package/src/lib/config/fragments/module-boundaries.d.ts +2 -0
  20. package/src/lib/config/fragments/module-boundaries.js +92 -0
  21. package/src/lib/config/fragments/module-boundaries.js.map +1 -0
  22. package/src/lib/config/fragments/react-rules.d.ts +5 -0
  23. package/src/lib/config/fragments/react-rules.js +137 -0
  24. package/src/lib/config/fragments/react-rules.js.map +1 -0
  25. package/src/lib/config/fragments/restricted-imports.d.ts +2 -0
  26. package/src/lib/config/fragments/restricted-imports.js +58 -0
  27. package/src/lib/config/fragments/restricted-imports.js.map +1 -0
  28. package/src/lib/config/fragments/testing-library.d.ts +2 -0
  29. package/src/lib/config/fragments/testing-library.js +7 -0
  30. package/src/lib/config/fragments/testing-library.js.map +1 -0
  31. package/src/lib/config/fragments/typescript-rules.d.ts +2 -0
  32. package/src/lib/config/fragments/typescript-rules.js +97 -0
  33. package/src/lib/config/fragments/typescript-rules.js.map +1 -0
  34. package/src/lib/config/index.d.ts +863 -0
  35. package/src/lib/config/index.js +10 -0
  36. package/src/lib/config/index.js.map +1 -0
  37. package/src/lib/config/plugins.d.ts +90 -0
  38. package/src/lib/config/plugins.js +44 -0
  39. package/src/lib/config/plugins.js.map +1 -0
  40. package/src/lib/config/presets/base.d.ts +265 -0
  41. package/src/lib/config/presets/base.js +145 -0
  42. package/src/lib/config/presets/base.js.map +1 -0
  43. package/src/lib/config/presets/e2e.d.ts +10 -0
  44. package/src/lib/config/presets/e2e.js +19 -0
  45. package/src/lib/config/presets/e2e.js.map +1 -0
  46. package/src/lib/config/presets/public-api.d.ts +147 -0
  47. package/src/lib/config/presets/public-api.js +62 -0
  48. package/src/lib/config/presets/public-api.js.map +1 -0
  49. package/src/lib/config/presets/react.d.ts +598 -0
  50. package/src/lib/config/presets/react.js +97 -0
  51. package/src/lib/config/presets/react.js.map +1 -0
  52. package/src/lib/config/presets/server.d.ts +36 -0
  53. package/src/lib/config/presets/server.js +37 -0
  54. package/src/lib/config/presets/server.js.map +1 -0
  55. package/src/lib/config/utils.d.ts +6 -0
  56. package/src/lib/config/utils.js +28 -0
  57. package/src/lib/config/utils.js.map +1 -0
  58. package/src/lib/config-helpers/create-skip-when.d.ts +35 -0
  59. package/src/lib/config-helpers/create-skip-when.js +54 -0
  60. package/src/lib/config-helpers/create-skip-when.js.map +1 -0
  61. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.d.ts +16 -0
  62. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js +83 -0
  63. package/src/lib/rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array.js.map +1 -0
  64. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.d.ts +4 -0
  65. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js +297 -0
  66. package/src/lib/rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match.js.map +1 -0
  67. package/src/lib/rules/no-internal-barrel-files/examples.d.ts +80 -0
  68. package/src/lib/rules/no-internal-barrel-files/examples.js +84 -0
  69. package/src/lib/rules/no-internal-barrel-files/examples.js.map +1 -0
  70. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.d.ts +29 -0
  71. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js +178 -0
  72. package/src/lib/rules/no-internal-barrel-files/no-internal-barrel-files.js.map +1 -0
  73. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.d.ts +5 -0
  74. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js +67 -0
  75. package/src/lib/rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public.js.map +1 -0
  76. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.d.ts +2 -0
  77. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js +34 -0
  78. package/src/lib/rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks.js.map +1 -0
  79. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.d.ts +16 -0
  80. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js +55 -0
  81. package/src/lib/rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop.js.map +1 -0
  82. package/src/lib/rules/no-typescript-assertion/examples.d.ts +1 -0
  83. package/src/lib/rules/no-typescript-assertion/examples.js +45 -0
  84. package/src/lib/rules/no-typescript-assertion/examples.js.map +1 -0
  85. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.d.ts +20 -0
  86. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js +83 -0
  87. package/src/lib/rules/no-typescript-assertion/no-typescript-assertion.js.map +1 -0
  88. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.d.ts +73 -0
  89. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js +333 -0
  90. package/src/lib/rules/prefer-destructured-imports/prefer-destructured-imports.js.map +1 -0
  91. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.d.ts +56 -0
  92. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js +225 -0
  93. package/src/lib/rules/prefer-event-specific-callback-naming/name-suggestion-strategies.js.map +1 -0
  94. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.d.ts +49 -0
  95. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js +75 -0
  96. package/src/lib/rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming.js.map +1 -0
  97. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.d.ts +32 -0
  98. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js +143 -0
  99. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/string-based.js.map +1 -0
  100. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.d.ts +27 -0
  101. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js +196 -0
  102. package/src/lib/rules/prefer-event-specific-callback-naming/strategies/type-based.js.map +1 -0
  103. package/src/lib/rules/prefer-event-specific-callback-naming/utils.d.ts +76 -0
  104. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js +245 -0
  105. package/src/lib/rules/prefer-event-specific-callback-naming/utils.js.map +1 -0
  106. package/src/lib/rules/prefer-field-components/prefer-field-components.d.ts +4 -0
  107. package/src/lib/rules/prefer-field-components/prefer-field-components.js +289 -0
  108. package/src/lib/rules/prefer-field-components/prefer-field-components.js.map +1 -0
  109. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.d.ts +26 -0
  110. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js +402 -0
  111. package/src/lib/rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props.js.map +1 -0
  112. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.d.ts +13 -0
  113. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js +271 -0
  114. package/src/lib/rules/require-classname-alternatives/require-classname-alternatives.js.map +1 -0
  115. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.d.ts +15 -0
  116. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js +245 -0
  117. package/src/lib/rules/require-list-item-virtualization-props/require-list-item-virtualization-props.js.map +1 -0
  118. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.d.ts +17 -0
  119. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js +133 -0
  120. package/src/lib/rules/require-optional-prop-initialization/require-optional-prop-initialization.js.map +1 -0
  121. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.d.ts +12 -0
  122. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js +128 -0
  123. package/src/lib/rules/require-optional-prop-initialization/suggestion-utils.js.map +1 -0
  124. package/src/lib/rules-map.d.ts +66 -0
  125. package/src/lib/rules-map.js +34 -0
  126. package/src/lib/rules-map.js.map +1 -0
  127. package/src/lib/utils/ast-utils.d.ts +85 -0
  128. package/src/lib/utils/ast-utils.js +530 -0
  129. package/src/lib/utils/ast-utils.js.map +1 -0
  130. package/src/lib/utils/classname-utils.d.ts +150 -0
  131. package/src/lib/utils/classname-utils.js +492 -0
  132. package/src/lib/utils/classname-utils.js.map +1 -0
  133. package/src/lib/utils/file-utils.d.ts +14 -0
  134. package/src/lib/utils/file-utils.js +106 -0
  135. package/src/lib/utils/file-utils.js.map +1 -0
  136. package/src/lib/utils/import-utils.d.ts +85 -0
  137. package/src/lib/utils/import-utils.js +193 -0
  138. package/src/lib/utils/import-utils.js.map +1 -0
  139. package/src/lib/utils/nx-utils.d.ts +59 -0
  140. package/src/lib/utils/nx-utils.js +103 -0
  141. package/src/lib/utils/nx-utils.js.map +1 -0
  142. package/src/lib/utils/package-utils.d.ts +38 -0
  143. package/src/lib/utils/package-utils.js +74 -0
  144. package/src/lib/utils/package-utils.js.map +1 -0
  145. package/src/lib/utils/typescript-utils.d.ts +29 -0
  146. package/src/lib/utils/typescript-utils.js +213 -0
  147. package/src/lib/utils/typescript-utils.js.map +1 -0
@@ -0,0 +1,530 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isIdentifierFromRenderPropCallback = exports.isIdentifierFromParameter = exports.isParameterOnlyUsedInJSX = exports.isReactComponent = exports.isParameterUsedInFunction = exports.isParameterInitialized = exports.hasExistingBodyInitializations = exports.isParameterExplicitlyDestructured = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ /**
6
+ * Utility functions for analyzing AST nodes and function structure in ESLint rules.
7
+ *
8
+ * ## Core Utilities
9
+ * - `isInParameterList()` - Check if a node is in a function's parameter list
10
+ *
11
+ * ## Parameter Analysis (Parameter → Usage)
12
+ * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured
13
+ * - `isParameterInitialized()` - Check if parameter has a default value
14
+ * - `isParameterUsedInFunction()` - Check if parameter is used in function body
15
+ * - `getParameterRestUsage()` - Get info about parameter accessed via rest params
16
+ * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body
17
+ *
18
+ * ## Identifier Origin Analysis (Usage → Origin)
19
+ * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)
20
+ * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter
21
+ * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter
22
+ *
23
+ * ## JSX/React Specific
24
+ * - `isReactComponent()` - Check if function is likely a React component
25
+ * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes
26
+ */
27
+ /**
28
+ * Helper function to check if a node is in the parameter list
29
+ */
30
+ const isInParameterList = (node, functionNode) => {
31
+ let current = node.parent;
32
+ while (current) {
33
+ // Check if current node is one of the function parameters
34
+ const isParam = functionNode.params.some(param => param === current);
35
+ if (isParam) {
36
+ return true;
37
+ }
38
+ current = current.parent;
39
+ }
40
+ return false;
41
+ };
42
+ /**
43
+ * Check if a parameter is explicitly destructured in the parameter list
44
+ * (vs. captured in rest parameters like ...restOptions)
45
+ */
46
+ const isParameterExplicitlyDestructured = (parameter, paramName) => {
47
+ if (parameter.type !== utils_1.AST_NODE_TYPES.ObjectPattern) {
48
+ return false;
49
+ }
50
+ // Check if the parameter is explicitly listed in the destructuring
51
+ return parameter.properties.some(property => {
52
+ if (property.type === utils_1.AST_NODE_TYPES.Property && property.key.type === utils_1.AST_NODE_TYPES.Identifier) {
53
+ return property.key.name === paramName;
54
+ }
55
+ return false;
56
+ });
57
+ };
58
+ exports.isParameterExplicitlyDestructured = isParameterExplicitlyDestructured;
59
+ /**
60
+ * Check if there are any existing parameter initializations in the function body
61
+ */
62
+ const hasExistingBodyInitializations = (functionBody) => {
63
+ for (const stmt of functionBody) {
64
+ // Check for destructuring with defaults: const { param = defaultValue } = params
65
+ if (stmt.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
66
+ stmt.declarations.length === 1 &&
67
+ stmt.declarations[0].id.type === utils_1.AST_NODE_TYPES.ObjectPattern &&
68
+ stmt.declarations[0].id.properties.some(prop => prop.type === utils_1.AST_NODE_TYPES.Property && prop.value.type === utils_1.AST_NODE_TYPES.AssignmentPattern)) {
69
+ return true;
70
+ }
71
+ // Check for variable declarations with defaults: const param = params.param ?? defaultValue
72
+ if (stmt.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
73
+ stmt.declarations.length === 1 &&
74
+ stmt.declarations[0].init?.type === utils_1.AST_NODE_TYPES.LogicalExpression &&
75
+ (stmt.declarations[0].init.operator === "??" || stmt.declarations[0].init.operator === "||")) {
76
+ return true;
77
+ }
78
+ }
79
+ return false;
80
+ };
81
+ exports.hasExistingBodyInitializations = hasExistingBodyInitializations;
82
+ /**
83
+ * Check if a parameter is initialized in the function body or parameter defaults
84
+ */
85
+ const isParameterInitialized = (functionBody, paramName, parameter) => {
86
+ // First check if the parameter has a default value in the parameter destructuring
87
+ if (parameter && parameter.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
88
+ for (const property of parameter.properties) {
89
+ if (property.type === utils_1.AST_NODE_TYPES.Property && property.value.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
90
+ // Handle both identifier keys (paramName) and string literal keys ("param-name")
91
+ const keyName = property.key.type === utils_1.AST_NODE_TYPES.Identifier
92
+ ? property.key.name
93
+ : property.key.type === utils_1.AST_NODE_TYPES.Literal && typeof property.key.value === "string"
94
+ ? property.key.value
95
+ : null;
96
+ if (keyName === paramName) {
97
+ return true; // Found default value in parameter: {paramName = defaultValue}
98
+ }
99
+ }
100
+ }
101
+ }
102
+ // Then check for initialization patterns in the function body
103
+ for (const stmt of functionBody) {
104
+ // Check for destructuring with defaults: const { param = defaultValue } = params
105
+ if (stmt.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
106
+ stmt.declarations.length === 1 &&
107
+ stmt.declarations[0].id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
108
+ const pattern = stmt.declarations[0].id;
109
+ for (const property of pattern.properties) {
110
+ if (property.type === utils_1.AST_NODE_TYPES.Property &&
111
+ property.key.type === utils_1.AST_NODE_TYPES.Identifier &&
112
+ property.key.name === paramName &&
113
+ property.value.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
114
+ return true;
115
+ }
116
+ }
117
+ }
118
+ // Check for variable declarations with defaults: const param = params.param ?? defaultValue
119
+ if (stmt.type === utils_1.AST_NODE_TYPES.VariableDeclaration &&
120
+ stmt.declarations.length === 1 &&
121
+ stmt.declarations[0].id.type === utils_1.AST_NODE_TYPES.Identifier &&
122
+ stmt.declarations[0].id.name === paramName &&
123
+ stmt.declarations[0].init?.type === utils_1.AST_NODE_TYPES.LogicalExpression &&
124
+ (stmt.declarations[0].init.operator === "??" || stmt.declarations[0].init.operator === "||")) {
125
+ return true;
126
+ }
127
+ }
128
+ return false;
129
+ };
130
+ exports.isParameterInitialized = isParameterInitialized;
131
+ /**
132
+ * Check if a parameter is used within the function body
133
+ */
134
+ const isParameterUsedInFunction = (context, functionNode, paramName) => {
135
+ // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection
136
+ const scope = context.sourceCode.getScope(functionNode);
137
+ const variable = utils_1.ASTUtils.findVariable(scope, paramName);
138
+ if (variable) {
139
+ // Check if the variable has any references (excluding the parameter definition)
140
+ const references = variable.references.filter(ref => {
141
+ // Exclude the parameter declaration itself
142
+ const refNode = ref.identifier;
143
+ return !isInParameterList(refNode, functionNode);
144
+ });
145
+ // Additional check: if the variable is only referenced in object literal shorthand property names
146
+ // (like { placement: result.placement }), it's not actually using the parameter variable
147
+ const actualUsageReferences = references.filter(ref => {
148
+ const parent = ref.identifier.parent;
149
+ // Skip if this is just a property key in an object literal
150
+ // Example: { placement: result.placement } - the first 'placement' is just a key, not usage
151
+ if (parent.type === utils_1.AST_NODE_TYPES.Property &&
152
+ parent.key === ref.identifier &&
153
+ parent.value !== ref.identifier &&
154
+ !parent.shorthand) {
155
+ return false;
156
+ }
157
+ return true;
158
+ });
159
+ if (actualUsageReferences.length > 0) {
160
+ return true;
161
+ }
162
+ }
163
+ // If direct variable reference not found, check for member access on rest parameters
164
+ // e.g., rest.paramName, params.paramName, etc.
165
+ const restParameters = [];
166
+ // Look for rest elements in both direct params and inside object patterns
167
+ functionNode.params.forEach(param => {
168
+ if (param.type === utils_1.AST_NODE_TYPES.RestElement && param.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
169
+ // Direct rest parameter: (...rest: Params)
170
+ restParameters.push({ name: param.argument.name, param });
171
+ }
172
+ else if (param.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
173
+ // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)
174
+ param.properties.forEach(property => {
175
+ if (property.type === utils_1.AST_NODE_TYPES.RestElement && property.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
176
+ restParameters.push({ name: property.argument.name, param });
177
+ }
178
+ });
179
+ }
180
+ });
181
+ if (restParameters.length === 0) {
182
+ return false;
183
+ }
184
+ // Check if the function body contains rest.paramName patterns
185
+ const functionText = context.sourceCode.getText(functionNode);
186
+ for (const restParam of restParameters) {
187
+ const pattern = new RegExp(`\\b${restParam.name}\\.${paramName}\\b`);
188
+ if (pattern.test(functionText)) {
189
+ return true;
190
+ }
191
+ }
192
+ return false;
193
+ };
194
+ exports.isParameterUsedInFunction = isParameterUsedInFunction;
195
+ /**
196
+ * Check if a parameter is accessed via rest parameters (e.g., rest.paramName)
197
+ * and return information about the rest parameter usage
198
+ */
199
+ const getParameterRestUsage = (context, functionNode, paramName) => {
200
+ // Look for rest elements in both direct params and inside object patterns
201
+ const restParameters = [];
202
+ functionNode.params.forEach(param => {
203
+ if (param.type === utils_1.AST_NODE_TYPES.RestElement && param.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
204
+ // Direct rest parameter: (...rest: Params)
205
+ restParameters.push({ name: param.argument.name, param });
206
+ }
207
+ else if (param.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
208
+ // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)
209
+ param.properties.forEach(property => {
210
+ if (property.type === utils_1.AST_NODE_TYPES.RestElement && property.argument.type === utils_1.AST_NODE_TYPES.Identifier) {
211
+ restParameters.push({ name: property.argument.name, param });
212
+ }
213
+ });
214
+ }
215
+ });
216
+ if (restParameters.length === 0) {
217
+ return { isUsedViaRest: false };
218
+ }
219
+ // Check if the function body contains rest.paramName patterns
220
+ const functionText = context.sourceCode.getText(functionNode);
221
+ for (const restParam of restParameters) {
222
+ const pattern = new RegExp(`\\b${restParam.name}\\.${paramName}\\b`);
223
+ if (pattern.test(functionText)) {
224
+ return {
225
+ isUsedViaRest: true,
226
+ restParamName: restParam.name,
227
+ restParam: restParam.param,
228
+ };
229
+ }
230
+ }
231
+ return { isUsedViaRest: false };
232
+ };
233
+ /**
234
+ * Check if a function is likely a React component based on naming and JSX usage
235
+ */
236
+ const isReactComponent = (node) => {
237
+ // Check if function name starts with uppercase (React convention)
238
+ const functionName = node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;
239
+ const startsWithUppercase = /^[A-Z]/;
240
+ if (functionName && startsWithUppercase.test(functionName)) {
241
+ return true;
242
+ }
243
+ // Check if the function returns JSX
244
+ const hasJSXReturn = (body) => {
245
+ if (body.type === utils_1.AST_NODE_TYPES.JSXElement || body.type === utils_1.AST_NODE_TYPES.JSXFragment) {
246
+ return true;
247
+ }
248
+ // Handle conditional expressions that contain JSX: condition ? <JSX /> : null
249
+ if (body.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
250
+ return hasJSXReturn(body.consequent) || hasJSXReturn(body.alternate);
251
+ }
252
+ if (body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
253
+ return body.body.some(stmt => {
254
+ if (stmt.type === utils_1.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
255
+ return hasJSXReturn(stmt.argument);
256
+ }
257
+ return false;
258
+ });
259
+ }
260
+ return false;
261
+ };
262
+ return hasJSXReturn(node.body);
263
+ };
264
+ exports.isReactComponent = isReactComponent;
265
+ /**
266
+ * Check if a parameter is only used in JSX attributes (pass-through to child components)
267
+ * and nowhere else in the function body
268
+ */
269
+ const isParameterOnlyUsedInJSX = (context, functionNode, paramName) => {
270
+ // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection
271
+ const scope = context.sourceCode.getScope(functionNode);
272
+ const variable = utils_1.ASTUtils.findVariable(scope, paramName);
273
+ if (!variable) {
274
+ return false;
275
+ }
276
+ // Get all references to the parameter (excluding the parameter definition)
277
+ const references = variable.references.filter(ref => {
278
+ const refNode = ref.identifier;
279
+ return !isInParameterList(refNode, functionNode);
280
+ });
281
+ if (references.length === 0) {
282
+ return false;
283
+ }
284
+ // Check if all references are only in JSX attribute expressions
285
+ const allReferencesAreJSXAttributes = references.every(ref => {
286
+ const identifier = ref.identifier;
287
+ let current = identifier.parent;
288
+ // Walk up the AST to find if this identifier is used in a JSX attribute
289
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions
290
+ while (current) {
291
+ // Check if we're in a JSX attribute expression: <Component prop={value} />
292
+ if (current.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
293
+ const jsxParent = current.parent;
294
+ if (jsxParent.type === utils_1.AST_NODE_TYPES.JSXAttribute) {
295
+ return true;
296
+ }
297
+ }
298
+ // Check if we're in a JSX spread attribute: <Component {...props} />
299
+ if (current.type === utils_1.AST_NODE_TYPES.JSXSpreadAttribute) {
300
+ return true;
301
+ }
302
+ // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)
303
+ // These are acceptable for pass-through props since they're tracking the JSX usage
304
+ if (current.type === utils_1.AST_NODE_TYPES.ArrayExpression) {
305
+ const callParent = current.parent;
306
+ if (callParent.type === utils_1.AST_NODE_TYPES.CallExpression &&
307
+ callParent.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
308
+ (callParent.callee.name.startsWith("use") ||
309
+ callParent.callee.name === "useMemo" ||
310
+ callParent.callee.name === "useCallback" ||
311
+ callParent.callee.name === "useEffect")) {
312
+ return true; // Allow dependency array usage
313
+ }
314
+ }
315
+ // Stop if we reach certain node types that indicate we're not in JSX context
316
+ if (current.type === utils_1.AST_NODE_TYPES.VariableDeclarator ||
317
+ current.type === utils_1.AST_NODE_TYPES.AssignmentExpression ||
318
+ current.type === utils_1.AST_NODE_TYPES.CallExpression ||
319
+ current.type === utils_1.AST_NODE_TYPES.LogicalExpression ||
320
+ current.type === utils_1.AST_NODE_TYPES.ConditionalExpression ||
321
+ current.type === utils_1.AST_NODE_TYPES.BinaryExpression) {
322
+ return false;
323
+ }
324
+ if (!current.parent) {
325
+ break;
326
+ }
327
+ current = current.parent;
328
+ }
329
+ return false;
330
+ });
331
+ return allReferencesAreJSXAttributes;
332
+ };
333
+ exports.isParameterOnlyUsedInJSX = isParameterOnlyUsedInJSX;
334
+ /**
335
+ * Checks if a variable is a function parameter.
336
+ */
337
+ const isVariableAParameter = (variable) => {
338
+ return variable.defs.some(def => def.type === "Parameter");
339
+ };
340
+ /**
341
+ * Traces an identifier back to determine if it originates from a function parameter.
342
+ * Returns detailed information about how the identifier relates to the parameter.
343
+ *
344
+ * This is used to distinguish between:
345
+ * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature
346
+ * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body
347
+ * - Direct parameter: `(onClose) => ...` - direct-parameter
348
+ * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter
349
+ * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter
350
+ *
351
+ * @param identifier - The identifier node to check
352
+ * @param context - The ESLint rule context
353
+ * @returns ParameterOriginResult with isFromParameter and originType if applicable
354
+ * @example
355
+ * // Direct parameter
356
+ * const MyComponent = (onClose) => <button onClick={onClose} />;
357
+ * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: "direct-parameter" }
358
+ * @example
359
+ * // Destructured in signature
360
+ * const MyComponent = ({ onClose }) => <button onClick={onClose} />;
361
+ * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: "destructured-in-signature" }
362
+ * @example
363
+ * // Destructured in body
364
+ * const MyComponent = (props) => {
365
+ * const { onClose } = props;
366
+ * return <button onClick={onClose} />;
367
+ * };
368
+ * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: "destructured-in-body" }
369
+ * @example
370
+ * // Not from parameter (internal function)
371
+ * const MyComponent = () => {
372
+ * const handleClose = () => {};
373
+ * return <button onClick={handleClose} />;
374
+ * };
375
+ * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }
376
+ */
377
+ const getIdentifierParameterOrigin = (identifier, context) => {
378
+ const scope = context.sourceCode.getScope(identifier);
379
+ const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;
380
+ if (!variable) {
381
+ return { isFromParameter: false };
382
+ }
383
+ // Check the variable's definitions
384
+ for (const definition of variable.defs) {
385
+ // Check if defined as a direct function parameter
386
+ if (definition.type === "Parameter") {
387
+ // Direct parameter: (onClose) => ...
388
+ return { isFromParameter: true, originType: "direct-parameter" };
389
+ }
390
+ // Check for destructured variable in body: const { onClose } = props
391
+ // definition.type is "Variable" and definition.node is VariableDeclarator
392
+ if (definition.type === "Variable") {
393
+ const declarator = definition.node;
394
+ // Check if the left side is an ObjectPattern (destructuring)
395
+ if (declarator.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
396
+ const init = declarator.init;
397
+ // Check if destructured from an identifier that is a parameter
398
+ if (init?.type === utils_1.AST_NODE_TYPES.Identifier) {
399
+ const initScope = context.sourceCode.getScope(init);
400
+ const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;
401
+ if (initVariable && isVariableAParameter(initVariable)) {
402
+ return { isFromParameter: true, originType: "destructured-in-body" };
403
+ }
404
+ }
405
+ }
406
+ }
407
+ // Check if it's a destructured parameter directly in function signature
408
+ // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...
409
+ if (definition.node.type === utils_1.AST_NODE_TYPES.Property) {
410
+ // Check direct parent - should be ObjectPattern for destructured props
411
+ const objectPattern = definition.node.parent;
412
+ if (objectPattern.type !== utils_1.AST_NODE_TYPES.ObjectPattern) {
413
+ continue;
414
+ }
415
+ // Check if this ObjectPattern is a function parameter
416
+ const objectPatternParent = objectPattern.parent;
417
+ if (objectPatternParent.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
418
+ objectPatternParent.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
419
+ objectPatternParent.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
420
+ // Check if the ObjectPattern is in the params
421
+ const isParam = objectPatternParent.params.includes(objectPattern);
422
+ if (isParam) {
423
+ return { isFromParameter: true, originType: "destructured-in-signature" };
424
+ }
425
+ }
426
+ // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...
427
+ if (objectPatternParent.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
428
+ const assignmentParent = objectPatternParent.parent;
429
+ if (assignmentParent.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
430
+ assignmentParent.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
431
+ assignmentParent.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
432
+ const isParam = assignmentParent.params.includes(objectPatternParent);
433
+ if (isParam) {
434
+ return { isFromParameter: true, originType: "destructured-in-signature" };
435
+ }
436
+ }
437
+ }
438
+ }
439
+ }
440
+ return { isFromParameter: false };
441
+ };
442
+ /**
443
+ * Checks if an identifier originates from a function parameter.
444
+ * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.
445
+ *
446
+ * Use this when you only need to know if an identifier comes from a parameter,
447
+ * without needing to know how it was destructured.
448
+ *
449
+ * @param identifier - The identifier node to check
450
+ * @param context - The ESLint rule context
451
+ * @returns true if the identifier originates from a function parameter
452
+ * @see getIdentifierParameterOrigin for detailed origin information
453
+ */
454
+ const isIdentifierFromParameter = (identifier, context) => getIdentifierParameterOrigin(identifier, context).isFromParameter;
455
+ exports.isIdentifierFromParameter = isIdentifierFromParameter;
456
+ /**
457
+ * Checks if an identifier's parameter comes from a render prop callback.
458
+ *
459
+ * Render prop pattern: `{callback => <Component onClick={callback} />}`
460
+ *
461
+ * The function detects when:
462
+ * 1. The identifier comes from a parameter
463
+ * 2. That parameter's function is inside a JSXExpressionContainer
464
+ * 3. Which is a child of a JSXElement (render prop pattern)
465
+ *
466
+ * This is used to distinguish between:
467
+ * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged
468
+ * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged
469
+ *
470
+ * @param identifier - The identifier node to check
471
+ * @param context - The ESLint rule context
472
+ * @returns true if the identifier comes from a render prop callback parameter
473
+ * @example
474
+ * // Render prop callback - returns true
475
+ * <MoreMenu>
476
+ * {close => <MenuItem onClick={close} />}
477
+ * </MoreMenu>
478
+ * // isIdentifierFromRenderPropCallback(close) => true
479
+ * @example
480
+ * // React component prop - returns false
481
+ * const Modal = ({ onClose }) => <button onClick={onClose} />;
482
+ * // isIdentifierFromRenderPropCallback(onClose) => false
483
+ */
484
+ const isIdentifierFromRenderPropCallback = (identifier, context) => {
485
+ // First check if it even comes from a parameter
486
+ if (!(0, exports.isIdentifierFromParameter)(identifier, context)) {
487
+ return false;
488
+ }
489
+ // Get the variable that this identifier resolves to
490
+ const scope = context.sourceCode.getScope(identifier);
491
+ const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;
492
+ if (!variable) {
493
+ return false;
494
+ }
495
+ // Check each definition of this variable
496
+ for (const definition of variable.defs) {
497
+ if (definition.type !== "Parameter") {
498
+ continue;
499
+ }
500
+ // Find the function that contains this parameter by walking up from the definition node
501
+ let functionNode = null;
502
+ let current = definition.node;
503
+ do {
504
+ if (current.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
505
+ current.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
506
+ current.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
507
+ functionNode = current;
508
+ break;
509
+ }
510
+ current = current.parent;
511
+ } while (current !== undefined);
512
+ if (!functionNode) {
513
+ continue;
514
+ }
515
+ // Check if the function is inside a JSXExpressionContainer (render prop pattern)
516
+ // Pattern: <Component>{callback => ...}</Component>
517
+ const parent = functionNode.parent;
518
+ if (parent.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
519
+ // Verify the JSXExpressionContainer is a child of a JSXElement
520
+ const jsxContainerParent = parent.parent;
521
+ if (jsxContainerParent.type === utils_1.AST_NODE_TYPES.JSXElement ||
522
+ jsxContainerParent.type === utils_1.AST_NODE_TYPES.JSXFragment) {
523
+ return true;
524
+ }
525
+ }
526
+ }
527
+ return false;
528
+ };
529
+ exports.isIdentifierFromRenderPropCallback = isIdentifierFromRenderPropCallback;
530
+ //# sourceMappingURL=ast-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/ast-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ASTUtils, AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for analyzing AST nodes and function structure in ESLint rules.\n *\n * ## Core Utilities\n * - `isInParameterList()` - Check if a node is in a function's parameter list\n *\n * ## Parameter Analysis (Parameter → Usage)\n * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured\n * - `isParameterInitialized()` - Check if parameter has a default value\n * - `isParameterUsedInFunction()` - Check if parameter is used in function body\n * - `getParameterRestUsage()` - Get info about parameter accessed via rest params\n * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body\n *\n * ## Identifier Origin Analysis (Usage → Origin)\n * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)\n * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter\n * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter\n *\n * ## JSX/React Specific\n * - `isReactComponent()` - Check if function is likely a React component\n * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes\n */\n\n/**\n * Helper function to check if a node is in the parameter list\n */\nconst isInParameterList = (\n node: TSESTree.Node,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): boolean => {\n let current = node.parent;\n while (current) {\n // Check if current node is one of the function parameters\n const isParam = functionNode.params.some(param => param === current);\n if (isParam) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\n\n/**\n * Check if a parameter is explicitly destructured in the parameter list\n * (vs. captured in rest parameters like ...restOptions)\n */\nexport const isParameterExplicitlyDestructured = (parameter: TSESTree.Parameter, paramName: string): boolean => {\n if (parameter.type !== AST_NODE_TYPES.ObjectPattern) {\n return false;\n }\n\n // Check if the parameter is explicitly listed in the destructuring\n return parameter.properties.some(property => {\n if (property.type === AST_NODE_TYPES.Property && property.key.type === AST_NODE_TYPES.Identifier) {\n return property.key.name === paramName;\n }\n return false;\n });\n};\n\n/**\n * Check if there are any existing parameter initializations in the function body\n */\nexport const hasExistingBodyInitializations = (functionBody: Array<TSESTree.Statement>): boolean => {\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern &&\n stmt.declarations[0].id.properties.some(\n prop => prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.AssignmentPattern\n )\n ) {\n return true;\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a parameter is initialized in the function body or parameter defaults\n */\nexport const isParameterInitialized = (\n functionBody: Array<TSESTree.Statement>,\n paramName: string,\n parameter?: TSESTree.Parameter\n): boolean => {\n // First check if the parameter has a default value in the parameter destructuring\n if (parameter && parameter.type === AST_NODE_TYPES.ObjectPattern) {\n for (const property of parameter.properties) {\n if (property.type === AST_NODE_TYPES.Property && property.value.type === AST_NODE_TYPES.AssignmentPattern) {\n // Handle both identifier keys (paramName) and string literal keys (\"param-name\")\n const keyName =\n property.key.type === AST_NODE_TYPES.Identifier\n ? property.key.name\n : property.key.type === AST_NODE_TYPES.Literal && typeof property.key.value === \"string\"\n ? property.key.value\n : null;\n\n if (keyName === paramName) {\n return true; // Found default value in parameter: {paramName = defaultValue}\n }\n }\n }\n }\n\n // Then check for initialization patterns in the function body\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern\n ) {\n const pattern = stmt.declarations[0].id;\n for (const property of pattern.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === paramName &&\n property.value.type === AST_NODE_TYPES.AssignmentPattern\n ) {\n return true;\n }\n }\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.Identifier &&\n stmt.declarations[0].id.name === paramName &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is used within the function body\n */\nexport const isParameterUsedInFunction = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (variable) {\n // Check if the variable has any references (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n // Exclude the parameter declaration itself\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n // Additional check: if the variable is only referenced in object literal shorthand property names\n // (like { placement: result.placement }), it's not actually using the parameter variable\n const actualUsageReferences = references.filter(ref => {\n const parent = ref.identifier.parent;\n\n // Skip if this is just a property key in an object literal\n // Example: { placement: result.placement } - the first 'placement' is just a key, not usage\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === ref.identifier &&\n parent.value !== ref.identifier &&\n !parent.shorthand\n ) {\n return false;\n }\n\n return true;\n });\n\n if (actualUsageReferences.length > 0) {\n return true;\n }\n }\n\n // If direct variable reference not found, check for member access on rest parameters\n // e.g., rest.paramName, params.paramName, etc.\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n // Look for rest elements in both direct params and inside object patterns\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return false;\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is accessed via rest parameters (e.g., rest.paramName)\n * and return information about the rest parameter usage\n */\nconst getParameterRestUsage = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): { isUsedViaRest: boolean; restParamName?: string; restParam?: TSESTree.Parameter } | null => {\n // Look for rest elements in both direct params and inside object patterns\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return { isUsedViaRest: false };\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return {\n isUsedViaRest: true,\n restParamName: restParam.name,\n restParam: restParam.param,\n };\n }\n }\n\n return { isUsedViaRest: false };\n};\n\n/**\n * Check if a function is likely a React component based on naming and JSX usage\n */\nexport const isReactComponent = (node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression): boolean => {\n // Check if function name starts with uppercase (React convention)\n const functionName = node.type === AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;\n const startsWithUppercase = /^[A-Z]/;\n if (functionName && startsWithUppercase.test(functionName)) {\n return true;\n }\n\n // Check if the function returns JSX\n const hasJSXReturn = (body: TSESTree.Node): boolean => {\n if (body.type === AST_NODE_TYPES.JSXElement || body.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n // Handle conditional expressions that contain JSX: condition ? <JSX /> : null\n if (body.type === AST_NODE_TYPES.ConditionalExpression) {\n return hasJSXReturn(body.consequent) || hasJSXReturn(body.alternate);\n }\n if (body.type === AST_NODE_TYPES.BlockStatement) {\n return body.body.some(stmt => {\n if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) {\n return hasJSXReturn(stmt.argument);\n }\n return false;\n });\n }\n return false;\n };\n\n return hasJSXReturn(node.body);\n};\n\n/**\n * Check if a parameter is only used in JSX attributes (pass-through to child components)\n * and nowhere else in the function body\n */\nexport const isParameterOnlyUsedInJSX = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (!variable) {\n return false;\n }\n\n // Get all references to the parameter (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n if (references.length === 0) {\n return false;\n }\n\n // Check if all references are only in JSX attribute expressions\n const allReferencesAreJSXAttributes = references.every(ref => {\n const identifier = ref.identifier;\n let current = identifier.parent;\n\n // Walk up the AST to find if this identifier is used in a JSX attribute\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions\n while (current) {\n // Check if we're in a JSX attribute expression: <Component prop={value} />\n if (current.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const jsxParent = current.parent;\n if (jsxParent.type === AST_NODE_TYPES.JSXAttribute) {\n return true;\n }\n }\n\n // Check if we're in a JSX spread attribute: <Component {...props} />\n if (current.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n return true;\n }\n\n // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)\n // These are acceptable for pass-through props since they're tracking the JSX usage\n if (current.type === AST_NODE_TYPES.ArrayExpression) {\n const callParent = current.parent;\n if (\n callParent.type === AST_NODE_TYPES.CallExpression &&\n callParent.callee.type === AST_NODE_TYPES.Identifier &&\n (callParent.callee.name.startsWith(\"use\") ||\n callParent.callee.name === \"useMemo\" ||\n callParent.callee.name === \"useCallback\" ||\n callParent.callee.name === \"useEffect\")\n ) {\n return true; // Allow dependency array usage\n }\n }\n\n // Stop if we reach certain node types that indicate we're not in JSX context\n if (\n current.type === AST_NODE_TYPES.VariableDeclarator ||\n current.type === AST_NODE_TYPES.AssignmentExpression ||\n current.type === AST_NODE_TYPES.CallExpression ||\n current.type === AST_NODE_TYPES.LogicalExpression ||\n current.type === AST_NODE_TYPES.ConditionalExpression ||\n current.type === AST_NODE_TYPES.BinaryExpression\n ) {\n return false;\n }\n\n if (!current.parent) {\n break;\n }\n current = current.parent;\n }\n\n return false;\n });\n\n return allReferencesAreJSXAttributes;\n};\n\n// ============================================================\n// Identifier Origin Analysis (traces usage back to definition)\n// ============================================================\n\n/**\n * Result of tracing an identifier back to its origin.\n * Used to distinguish between different ways an identifier can come from a function parameter.\n */\nexport type ParameterOriginResult =\n | {\n isFromParameter: true;\n /**\n * How the identifier relates to the parameter:\n * - \"direct-parameter\": Direct parameter, e.g., `(onClose) => ...`\n * - \"destructured-in-signature\": Destructured in function signature, e.g., `({ onClose }) => ...`\n * - \"destructured-in-body\": Destructured in function body, e.g., `const { onClose } = props`\n */\n originType: \"direct-parameter\" | \"destructured-in-signature\" | \"destructured-in-body\";\n }\n | { isFromParameter: false };\n\n/**\n * Checks if a variable is a function parameter.\n */\nconst isVariableAParameter = (variable: { defs: ReadonlyArray<{ type: string }> }): boolean => {\n return variable.defs.some(def => def.type === \"Parameter\");\n};\n\n/**\n * Traces an identifier back to determine if it originates from a function parameter.\n * Returns detailed information about how the identifier relates to the parameter.\n *\n * This is used to distinguish between:\n * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature\n * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body\n * - Direct parameter: `(onClose) => ...` - direct-parameter\n * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter\n * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns ParameterOriginResult with isFromParameter and originType if applicable\n * @example\n * // Direct parameter\n * const MyComponent = (onClose) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"direct-parameter\" }\n * @example\n * // Destructured in signature\n * const MyComponent = ({ onClose }) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-signature\" }\n * @example\n * // Destructured in body\n * const MyComponent = (props) => {\n * const { onClose } = props;\n * return <button onClick={onClose} />;\n * };\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-body\" }\n * @example\n * // Not from parameter (internal function)\n * const MyComponent = () => {\n * const handleClose = () => {};\n * return <button onClick={handleClose} />;\n * };\n * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }\n */\nconst getIdentifierParameterOrigin = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): ParameterOriginResult => {\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return { isFromParameter: false };\n }\n\n // Check the variable's definitions\n for (const definition of variable.defs) {\n // Check if defined as a direct function parameter\n if (definition.type === \"Parameter\") {\n // Direct parameter: (onClose) => ...\n return { isFromParameter: true, originType: \"direct-parameter\" };\n }\n\n // Check for destructured variable in body: const { onClose } = props\n // definition.type is \"Variable\" and definition.node is VariableDeclarator\n if (definition.type === \"Variable\") {\n const declarator = definition.node;\n\n // Check if the left side is an ObjectPattern (destructuring)\n if (declarator.id.type === AST_NODE_TYPES.ObjectPattern) {\n const init = declarator.init;\n\n // Check if destructured from an identifier that is a parameter\n if (init?.type === AST_NODE_TYPES.Identifier) {\n const initScope = context.sourceCode.getScope(init);\n const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;\n\n if (initVariable && isVariableAParameter(initVariable)) {\n return { isFromParameter: true, originType: \"destructured-in-body\" };\n }\n }\n }\n }\n\n // Check if it's a destructured parameter directly in function signature\n // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...\n if (definition.node.type === AST_NODE_TYPES.Property) {\n // Check direct parent - should be ObjectPattern for destructured props\n const objectPattern = definition.node.parent;\n if (objectPattern.type !== AST_NODE_TYPES.ObjectPattern) {\n continue;\n }\n\n // Check if this ObjectPattern is a function parameter\n const objectPatternParent = objectPattern.parent;\n\n if (\n objectPatternParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n // Check if the ObjectPattern is in the params\n const isParam = objectPatternParent.params.includes(objectPattern);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n\n // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...\n if (objectPatternParent.type === AST_NODE_TYPES.AssignmentPattern) {\n const assignmentParent = objectPatternParent.parent;\n\n if (\n assignmentParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n const isParam = assignmentParent.params.includes(objectPatternParent);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n }\n }\n }\n\n return { isFromParameter: false };\n};\n\n/**\n * Checks if an identifier originates from a function parameter.\n * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.\n *\n * Use this when you only need to know if an identifier comes from a parameter,\n * without needing to know how it was destructured.\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier originates from a function parameter\n * @see getIdentifierParameterOrigin for detailed origin information\n */\nexport const isIdentifierFromParameter = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => getIdentifierParameterOrigin(identifier, context).isFromParameter;\n\n/**\n * Checks if an identifier's parameter comes from a render prop callback.\n *\n * Render prop pattern: `{callback => <Component onClick={callback} />}`\n *\n * The function detects when:\n * 1. The identifier comes from a parameter\n * 2. That parameter's function is inside a JSXExpressionContainer\n * 3. Which is a child of a JSXElement (render prop pattern)\n *\n * This is used to distinguish between:\n * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged\n * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier comes from a render prop callback parameter\n * @example\n * // Render prop callback - returns true\n * <MoreMenu>\n * {close => <MenuItem onClick={close} />}\n * </MoreMenu>\n * // isIdentifierFromRenderPropCallback(close) => true\n * @example\n * // React component prop - returns false\n * const Modal = ({ onClose }) => <button onClick={onClose} />;\n * // isIdentifierFromRenderPropCallback(onClose) => false\n */\nexport const isIdentifierFromRenderPropCallback = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // First check if it even comes from a parameter\n if (!isIdentifierFromParameter(identifier, context)) {\n return false;\n }\n\n // Get the variable that this identifier resolves to\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return false;\n }\n\n // Check each definition of this variable\n for (const definition of variable.defs) {\n if (definition.type !== \"Parameter\") {\n continue;\n }\n\n // Find the function that contains this parameter by walking up from the definition node\n let functionNode:\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n | TSESTree.FunctionDeclaration\n | null = null;\n\n let current: TSESTree.Node | undefined = definition.node;\n do {\n if (\n current.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n functionNode = current;\n break;\n }\n current = current.parent;\n } while (current !== undefined);\n\n if (!functionNode) {\n continue;\n }\n\n // Check if the function is inside a JSXExpressionContainer (render prop pattern)\n // Pattern: <Component>{callback => ...}</Component>\n const parent = functionNode.parent;\n if (parent.type === AST_NODE_TYPES.JSXExpressionContainer) {\n // Verify the JSXExpressionContainer is a child of a JSXElement\n const jsxContainerParent = parent.parent;\n if (\n jsxContainerParent.type === AST_NODE_TYPES.JSXElement ||\n jsxContainerParent.type === AST_NODE_TYPES.JSXFragment\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n"]}