@eslint-react/core 5.2.1-next.1 → 5.2.2-beta.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 (3) hide show
  1. package/dist/index.d.ts +116 -47
  2. package/dist/index.js +179 -35
  3. package/package.json +6 -6
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as ast from "@eslint-react/ast";
1
+ import { ClassExpression, Directive, FunctionExpression, MethodOrPropertyDefinition } from "@eslint-react/ast";
2
2
  import { TSESTree } from "@typescript-eslint/types";
3
3
  import { RuleContext } from "@eslint-react/eslint";
4
4
  import { RegExpLike } from "@eslint-react/shared";
@@ -112,6 +112,14 @@ declare const isUseStateCall: isAPICall.ReturnType;
112
112
  declare const isUseSyncExternalStoreCall: isAPICall.ReturnType;
113
113
  declare const isUseTransitionCall: isAPICall.ReturnType;
114
114
  //#endregion
115
+ //#region src/class.d.ts
116
+ /**
117
+ * Get the class identifier of a class node
118
+ * @param node The class node to get the identifier from
119
+ * @returns The class identifier or null if not found
120
+ */
121
+ declare function getClassId(node: ClassExpression): TSESTree.BindingName | null;
122
+ //#endregion
115
123
  //#region src/semantic.d.ts
116
124
  /**
117
125
  * Represents a semantic node in the AST
@@ -139,9 +147,9 @@ interface SemanticNode {
139
147
  */
140
148
  interface SemanticFunc extends SemanticNode {
141
149
  /** The identifier of the function */
142
- id: ast.FunctionID;
150
+ id: null | TSESTree.Node;
143
151
  /** The AST node of the function */
144
- node: ast.TSESTreeFunction;
152
+ node: FunctionExpression;
145
153
  /** The name of the function */
146
154
  name: string | null;
147
155
  /** The return type annotation of the function */
@@ -149,7 +157,7 @@ interface SemanticFunc extends SemanticNode {
149
157
  /** The body of the function */
150
158
  body: TSESTree.BlockStatement | TSESTree.Expression;
151
159
  /** The directives of the function (ex: "use strict", "use client", "use server", etc.) */
152
- directives: ast.TSESTreeDirective[];
160
+ directives: Directive[];
153
161
  /** The parameters of the function */
154
162
  parameters: TSESTree.Parameter[];
155
163
  /** The type parameters of the function */
@@ -166,68 +174,68 @@ interface ClassComponentSemanticNode extends SemanticNode {
166
174
  displayName: null | TSESTree.Expression;
167
175
  flag: bigint;
168
176
  hint: bigint;
169
- methods: ast.TSESTreeMethodOrProperty[];
170
- node: ast.TSESTreeClass;
177
+ methods: MethodOrPropertyDefinition[];
178
+ node: ClassExpression;
171
179
  }
172
180
  /**
173
181
  * @param node The AST node to check.
174
182
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
175
183
  */
176
- declare function isClassComponent(node: TSESTree.Node): node is ast.TSESTreeClass;
184
+ declare function isClassComponent(node: TSESTree.Node): node is ClassExpression;
177
185
  /**
178
186
  * @param node The AST node to check.
179
187
  * @param context The rule context.
180
188
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
181
189
  */
182
- declare function isClassComponent(node: TSESTree.Node, context: RuleContext): node is ast.TSESTreeClass;
183
- declare function isClassComponentLoose(node: TSESTree.Node): node is ast.TSESTreeClass;
190
+ declare function isClassComponent(node: TSESTree.Node, context: RuleContext): node is ClassExpression;
191
+ declare function isClassComponentLoose(node: TSESTree.Node): node is ClassExpression;
184
192
  /**
185
193
  * @param node The AST node to check.
186
194
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
187
195
  */
188
196
  declare function isPureComponent(node: TSESTree.Node): boolean;
189
197
  /** @deprecated Class components are legacy. */
190
- declare const isRender: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
198
+ declare const isRender: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
191
199
  /** @deprecated Class components are legacy. */
192
- declare const isComponentDidCatch: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
200
+ declare const isComponentDidCatch: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
193
201
  /** @deprecated Class components are legacy. */
194
- declare const isComponentDidMount: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
202
+ declare const isComponentDidMount: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
195
203
  /** @deprecated Class components are legacy. */
196
- declare const isComponentDidUpdate: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
204
+ declare const isComponentDidUpdate: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
197
205
  /** @deprecated Class components are legacy. */
198
- declare const isComponentWillMount: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
206
+ declare const isComponentWillMount: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
199
207
  /** @deprecated Class components are legacy. */
200
- declare const isComponentWillReceiveProps: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
208
+ declare const isComponentWillReceiveProps: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
201
209
  /** @deprecated Class components are legacy. */
202
- declare const isComponentWillUnmount: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
210
+ declare const isComponentWillUnmount: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
203
211
  /** @deprecated Class components are legacy. */
204
- declare const isComponentWillUpdate: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
212
+ declare const isComponentWillUpdate: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
205
213
  /** @deprecated Class components are legacy. */
206
- declare const isGetChildContext: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
214
+ declare const isGetChildContext: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
207
215
  /** @deprecated Class components are legacy. */
208
- declare const isGetInitialState: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
216
+ declare const isGetInitialState: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
209
217
  /** @deprecated Class components are legacy. */
210
- declare const isGetSnapshotBeforeUpdate: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
218
+ declare const isGetSnapshotBeforeUpdate: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
211
219
  /** @deprecated Class components are legacy. */
212
- declare const isShouldComponentUpdate: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
220
+ declare const isShouldComponentUpdate: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
213
221
  /** @deprecated Class components are legacy. */
214
- declare const isUnsafeComponentWillMount: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
222
+ declare const isUnsafeComponentWillMount: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
215
223
  /** @deprecated Class components are legacy. */
216
- declare const isUnsafeComponentWillReceiveProps: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
224
+ declare const isUnsafeComponentWillReceiveProps: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
217
225
  /** @deprecated Class components are legacy. */
218
- declare const isUnsafeComponentWillUpdate: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
226
+ declare const isUnsafeComponentWillUpdate: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
219
227
  /** @deprecated Class components are legacy. */
220
- declare const isGetDefaultProps: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
228
+ declare const isGetDefaultProps: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
221
229
  /** @deprecated Class components are legacy. */
222
- declare const isGetDerivedStateFromProps: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
230
+ declare const isGetDerivedStateFromProps: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
223
231
  /** @deprecated Class components are legacy. */
224
- declare const isGetDerivedStateFromError: (node: TSESTree.Node) => node is ast.TSESTreeMethodOrProperty;
232
+ declare const isGetDerivedStateFromError: (node: TSESTree.Node) => node is MethodOrPropertyDefinition;
225
233
  /**
226
234
  * @param node The AST node to check.
227
235
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
228
236
  */
229
- declare function isRenderMethodLike(node: TSESTree.Node): node is ast.TSESTreeMethodOrProperty;
230
- declare function isRenderMethodCallback(node: ast.TSESTreeFunction): boolean;
237
+ declare function isRenderMethodLike(node: TSESTree.Node): node is MethodOrPropertyDefinition;
238
+ declare function isRenderMethodCallback(node: FunctionExpression): boolean;
231
239
  /**
232
240
  * @param node The call expression node to check.
233
241
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
@@ -259,31 +267,92 @@ declare function getClassComponentCollector(context: RuleContext): getClassCompo
259
267
  //#endregion
260
268
  //#region src/function.d.ts
261
269
  /**
262
- * Represents the kind of a React function
270
+ * Type representing the return type of `getFunctionId`.
271
+ */
272
+ type FunctionID = ReturnType<typeof getFunctionId>;
273
+ /**
274
+ * Represents various AST paths for function declarations.
275
+ * Each tuple type represents a specific function definition pattern.
276
+ */
277
+ type FunctionInitPath = readonly [TSESTree.FunctionDeclaration] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, FunctionExpression] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, FunctionExpression] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.CallExpression, TSESTree.CallExpression, FunctionExpression] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, FunctionExpression] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, FunctionExpression] | readonly [TSESTree.VariableDeclaration, TSESTree.VariableDeclarator, TSESTree.ObjectExpression, TSESTree.Property, TSESTree.CallExpression, TSESTree.CallExpression, FunctionExpression] | readonly [TSESTree.ClassDeclaration | TSESTree.ClassExpression, TSESTree.ClassBody, TSESTree.MethodDefinition, FunctionExpression] | readonly [TSESTree.ClassDeclaration | TSESTree.ClassExpression, TSESTree.ClassBody, TSESTree.PropertyDefinition, FunctionExpression];
278
+ /**
279
+ * Represents the kind of a function.
263
280
  */
264
281
  type FunctionKind = "client-function" | "server-function";
265
282
  /**
266
- * Represents a React Client Function
283
+ * Represents a client function semantic node.
267
284
  */
268
285
  interface ClientFunctionSemanticNode extends SemanticFunc {
269
286
  /**
270
- * The kind of function
287
+ * The kind of function.
271
288
  */
272
289
  kind: "client-function";
273
290
  }
274
291
  /**
275
- * Represents a React Server Function
292
+ * Represents a server function semantic node.
276
293
  */
277
294
  interface ServerFunctionSemanticNode extends SemanticFunc {
278
295
  /**
279
- * The kind of function
296
+ * The kind of function.
280
297
  */
281
298
  kind: "server-function";
282
299
  }
283
300
  /**
284
- * Represents a React Function
301
+ * Represents a function semantic node.
285
302
  */
286
303
  type FunctionSemanticNode = ClientFunctionSemanticNode | ServerFunctionSemanticNode;
304
+ /**
305
+ * Gets the static identifier of a function AST node.
306
+ *
307
+ * @remarks
308
+ * For function declarations this is straightforward. For anonymous function
309
+ * expressions it is more complex. This function roughly detects the same AST
310
+ * nodes as the ECMAScript spec's `IsAnonymousFunctionDefinition()` with some
311
+ * exceptions to better fit our use case.
312
+ *
313
+ * Ported from {@link https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts#L860 | RulesOfHooks.ts}
314
+ *
315
+ * @param node - The function node to analyze.
316
+ * @returns The identifier node if found, `null` otherwise.
317
+ */
318
+ declare function getFunctionId(node: TSESTree.Expression | FunctionExpression): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.PrivateInExpression | TSESTree.SymmetricBinaryExpression | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.ClassExpression | TSESTree.ConditionalExpression | TSESTree.FunctionExpression | TSESTree.Identifier | TSESTree.ImportExpression | TSESTree.JSXElement | TSESTree.JSXFragment | TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral | TSESTree.TemplateLiteral | TSESTree.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | TSESTree.PrivateIdentifier | null;
319
+ /**
320
+ * Identifies the initialization path of a function node in the AST.
321
+ *
322
+ * @param node - The function node to analyze.
323
+ * @returns The function initialization path or `null` if not identifiable.
324
+ */
325
+ declare function getFunctionInitPath(node: FunctionExpression): null | FunctionInitPath;
326
+ /**
327
+ * Checks if a specific function call exists in the function initialization path.
328
+ *
329
+ * @param callName - The name of the call to check for (e.g., "memo", "forwardRef").
330
+ * @param initPath - The function initialization path to search in.
331
+ * @returns `true` if the call exists in the path, `false` otherwise.
332
+ */
333
+ declare function isFunctionHasCallInInitPath(callName: string, initPath: FunctionInitPath): boolean;
334
+ /**
335
+ * Checks if a function is empty.
336
+ *
337
+ * @param node - The function node to check.
338
+ * @returns `true` if the function is empty, `false` otherwise.
339
+ */
340
+ declare function isFunctionEmpty(node: FunctionExpression): boolean;
341
+ /**
342
+ * Gets all directive expression statements from the top of a function body.
343
+ *
344
+ * @param node - The function AST node.
345
+ * @returns An array of directive expression statements.
346
+ */
347
+ declare function getFunctionDirectives(node: FunctionExpression): Directive[];
348
+ /**
349
+ * Checks if a directive with the given name exists in the function directives.
350
+ *
351
+ * @param node - The function AST node.
352
+ * @param name - The directive name to check (e.g., "use memo", "use no memo").
353
+ * @returns `true` if the directive exists, `false` otherwise.
354
+ */
355
+ declare function isFunctionHasDirective(node: FunctionExpression, name: string): boolean;
287
356
  //#endregion
288
357
  //#region src/function-component.d.ts
289
358
  /**
@@ -293,7 +362,7 @@ interface FunctionComponentSemanticNode extends SemanticNode {
293
362
  /**
294
363
  * The identifier or identifier sequence of the component
295
364
  */
296
- id: ast.FunctionID;
365
+ id: FunctionID;
297
366
  /**
298
367
  * The kind of component
299
368
  */
@@ -301,7 +370,7 @@ interface FunctionComponentSemanticNode extends SemanticNode {
301
370
  /**
302
371
  * The AST node of the function
303
372
  */
304
- node: ast.TSESTreeFunction;
373
+ node: FunctionExpression;
305
374
  /**
306
375
  * Flags describing the component's characteristics
307
376
  */
@@ -317,7 +386,7 @@ interface FunctionComponentSemanticNode extends SemanticNode {
317
386
  /**
318
387
  * The initialization path of the function
319
388
  */
320
- initPath: null | ast.FunctionInitPath;
389
+ initPath: null | FunctionInitPath;
321
390
  /**
322
391
  * Indicates if the component is inside an export default declaration
323
392
  */
@@ -337,7 +406,7 @@ interface FunctionComponentSemanticNode extends SemanticNode {
337
406
  /**
338
407
  * The directives used in the function (ex: "use strict", "use client", etc.)
339
408
  */
340
- directives: ast.TSESTreeDirective[];
409
+ directives: Directive[];
341
410
  }
342
411
  /**
343
412
  * Component flag constants
@@ -376,7 +445,7 @@ declare function isFunctionComponentWrapperCallback(context: RuleContext, node:
376
445
  * @param node The AST node to get the function component identifier from
377
446
  * @internal
378
447
  */
379
- declare function getFunctionComponentId(context: RuleContext, node: ast.TSESTreeFunction): ast.FunctionID;
448
+ declare function getFunctionComponentId(context: RuleContext, node: FunctionExpression): FunctionID;
380
449
  /**
381
450
  * Check if a string matches the strict component name pattern
382
451
  * @param name The name to check
@@ -394,7 +463,7 @@ declare function isFunctionComponentNameLoose(name: string): boolean;
394
463
  * @param allowNone Whether to allow no name
395
464
  * @returns Whether the function has a loose component name
396
465
  */
397
- declare function isFunctionWithLooseComponentName(context: RuleContext, fn: ast.TSESTreeFunction, allowNone?: boolean): boolean;
466
+ declare function isFunctionWithLooseComponentName(context: RuleContext, fn: FunctionExpression, allowNone?: boolean): boolean;
398
467
  type FunctionComponentDetectionHint = bigint;
399
468
  /**
400
469
  * Hints for component collector
@@ -433,7 +502,7 @@ declare const DEFAULT_COMPONENT_DETECTION_HINT: bigint;
433
502
  * @param hint Component detection hints (bit flags) to customize detection logic
434
503
  * @returns `true` if the node is considered a component definition
435
504
  */
436
- declare function isFunctionComponentDefinition(context: RuleContext, node: ast.TSESTreeFunction, hint: bigint): boolean;
505
+ declare function isFunctionComponentDefinition(context: RuleContext, node: FunctionExpression, hint: bigint): boolean;
437
506
  //#endregion
438
507
  //#region src/function-component-collector.d.ts
439
508
  declare namespace getFunctionComponentCollector {
@@ -462,9 +531,9 @@ declare function getFunctionComponentCollector(context: RuleContext, options?: g
462
531
  */
463
532
  interface HookSemanticNode extends SemanticNode {
464
533
  /** The identifier of the hook */
465
- id: ast.FunctionID;
534
+ id: FunctionID;
466
535
  /** The AST node of the hook */
467
- node: ast.TSESTreeFunction;
536
+ node: FunctionExpression;
468
537
  /** The kind of hook */
469
538
  kind: "hook";
470
539
  /** List of expressions returned by the hook */
@@ -472,7 +541,7 @@ interface HookSemanticNode extends SemanticNode {
472
541
  /** The other hooks called by the hook */
473
542
  hookCalls: TSESTree.CallExpression[];
474
543
  /** The directives used in the function (ex: "use strict", "use client", etc.) */
475
- directives: ast.TSESTreeDirective[];
544
+ directives: Directive[];
476
545
  }
477
546
  declare const REACT_BUILTIN_HOOK_NAMES: readonly ["use", "useActionState", "useCallback", "useContext", "useDebugValue", "useDeferredValue", "useEffect", "useFormStatus", "useId", "useImperativeHandle", "useInsertionEffect", "useLayoutEffect", "useMemo", "useOptimistic", "useReducer", "useRef", "useState", "useSyncExternalStore", "useTransition"];
478
547
  /**
@@ -493,7 +562,7 @@ declare function isHookId(id: TSESTree.Node): id is TSESTree.Identifier | TSESTr
493
562
  * @param node The function node to check
494
563
  * @returns True if the function is a React Hook, false otherwise
495
564
  */
496
- declare function isHookDefinition(node: ast.TSESTreeFunction | null): boolean;
565
+ declare function isHookDefinition(node: FunctionExpression | null): boolean;
497
566
  /**
498
567
  * Check if the given node is a React Hook call by its name.
499
568
  * @param node The node to check.
@@ -669,4 +738,4 @@ type TypeVariant = "any" | "bigint" | "boolean" | "enum" | "never" | "nullish" |
669
738
  */
670
739
  declare function getTypeVariants(types: ts.Type[]): Set<TypeVariant>;
671
740
  //#endregion
672
- export { ClassComponentSemanticNode, ClientFunctionSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, FunctionComponentDetectionHint, FunctionComponentFlag, FunctionComponentSemanticNode, FunctionKind, FunctionSemanticNode, HookSemanticNode, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, TypeVariant, getClassComponentCollector, getFullyQualifiedNameEx, getFunctionComponentCollector, getFunctionComponentFlagFromInitPath, getFunctionComponentId, getHookCollector, getTypeVariants, isAPI, isAPICall, isAPIFromReact, isAPIFromReactNative, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanLiteralType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isClassComponentLoose, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFunctionComponentDefinition, isFunctionComponentName, isFunctionComponentNameLoose, isFunctionComponentWrapperCall, isFunctionComponentWrapperCallback, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHookCall, isHookDefinition, isHookId, isHookName, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isStringType, isThisSetStateCall, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUse, isUseActionState, isUseActionStateCall, isUseCall, isUseCallback, isUseCallbackCall, isUseContext, isUseContextCall, isUseDebugValue, isUseDebugValueCall, isUseDeferredValue, isUseDeferredValueCall, isUseEffect, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatus, isUseFormStatusCall, isUseId, isUseIdCall, isUseImperativeHandle, isUseImperativeHandleCall, isUseInsertionEffect, isUseInsertionEffectCall, isUseLayoutEffect, isUseLayoutEffectCall, isUseMemo, isUseMemoCall, isUseOptimistic, isUseOptimisticCall, isUseReducer, isUseReducerCall, isUseRef, isUseRefCall, isUseState, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStore, isUseSyncExternalStoreCall, isUseTransition, isUseTransitionCall };
741
+ export { ClassComponentSemanticNode, ClientFunctionSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, FunctionComponentDetectionHint, FunctionComponentFlag, FunctionComponentSemanticNode, FunctionID, FunctionInitPath, FunctionKind, FunctionSemanticNode, HookSemanticNode, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, TypeVariant, getClassComponentCollector, getClassId, getFullyQualifiedNameEx, getFunctionComponentCollector, getFunctionComponentFlagFromInitPath, getFunctionComponentId, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHookCollector, getTypeVariants, isAPI, isAPICall, isAPIFromReact, isAPIFromReactNative, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanLiteralType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isClassComponentLoose, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFunctionComponentDefinition, isFunctionComponentName, isFunctionComponentNameLoose, isFunctionComponentWrapperCall, isFunctionComponentWrapperCallback, isFunctionEmpty, isFunctionHasCallInInitPath, isFunctionHasDirective, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHookCall, isHookDefinition, isHookId, isHookName, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isStringType, isThisSetStateCall, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUse, isUseActionState, isUseActionStateCall, isUseCall, isUseCallback, isUseCallbackCall, isUseContext, isUseContextCall, isUseDebugValue, isUseDebugValueCall, isUseDeferredValue, isUseDeferredValueCall, isUseEffect, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatus, isUseFormStatusCall, isUseId, isUseIdCall, isUseImperativeHandle, isUseImperativeHandleCall, isUseInsertionEffect, isUseInsertionEffectCall, isUseLayoutEffect, isUseLayoutEffectCall, isUseMemo, isUseMemoCall, isUseOptimistic, isUseOptimisticCall, isUseReducer, isUseReducerCall, isUseRef, isUseRefCall, isUseState, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStore, isUseSyncExternalStoreCall, isUseTransition, isUseTransitionCall };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as ast from "@eslint-react/ast";
1
+ import { Check, Extract, Select, Traverse, is, isOneOf } from "@eslint-react/ast";
2
2
  import { resolveImportSource } from "@eslint-react/var";
3
3
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
4
4
  import "@eslint-react/eslint";
@@ -145,7 +145,7 @@ function isAPI(api) {
145
145
  const func = (context, node) => {
146
146
  if (node == null) return false;
147
147
  const getText = (n) => context.sourceCode.getText(n);
148
- const name = ast.getFullyQualifiedName(node, getText);
148
+ const name = Extract.fullyQualifiedName(node, getText);
149
149
  if (name === api) return true;
150
150
  if (name.endsWith(`.${api}`)) return true;
151
151
  return false;
@@ -161,7 +161,7 @@ function isAPICall(api) {
161
161
  const func = (context, node) => {
162
162
  if (node == null) return false;
163
163
  if (node.type !== AST_NODE_TYPES.CallExpression) return false;
164
- return isAPI(api)(context, ast.getUnderlyingExpression(node.callee));
164
+ return isAPI(api)(context, Extract.unwrapped(node.callee));
165
165
  };
166
166
  return dual(2, func);
167
167
  }
@@ -254,6 +254,19 @@ const isUseStateCall = isAPICall("useState");
254
254
  const isUseSyncExternalStoreCall = isAPICall("useSyncExternalStore");
255
255
  const isUseTransitionCall = isAPICall("useTransition");
256
256
 
257
+ //#endregion
258
+ //#region src/class.ts
259
+ /**
260
+ * Get the class identifier of a class node
261
+ * @param node The class node to get the identifier from
262
+ * @returns The class identifier or null if not found
263
+ */
264
+ function getClassId(node) {
265
+ if (node.id != null) return node.id;
266
+ if (node.parent.type === AST_NODE_TYPES.VariableDeclarator) return node.parent.id;
267
+ return null;
268
+ }
269
+
257
270
  //#endregion
258
271
  //#region src/class-component.ts
259
272
  function isClassComponent(node, context) {
@@ -298,7 +311,7 @@ function isPureComponent(node) {
298
311
  return false;
299
312
  }
300
313
  function createLifecycleChecker(methodName, isStatic = false) {
301
- return (node) => ast.isMethodOrProperty(node) && node.static === isStatic && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === methodName;
314
+ return (node) => Check.isMethodOrProperty(node) && node.static === isStatic && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === methodName;
302
315
  }
303
316
  /** @deprecated Class components are legacy. */
304
317
  const isRender = createLifecycleChecker("render");
@@ -341,7 +354,7 @@ const isGetDerivedStateFromError = createLifecycleChecker("getDerivedStateFromEr
341
354
  * @deprecated Class components are legacy. This function exists only to support legacy rules.
342
355
  */
343
356
  function isRenderMethodLike(node) {
344
- return ast.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && ast.isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression])(node.parent.parent);
357
+ return Check.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression])(node.parent.parent);
345
358
  }
346
359
  function isRenderMethodCallback(node) {
347
360
  const parent = node.parent;
@@ -354,7 +367,7 @@ function isRenderMethodCallback(node) {
354
367
  */
355
368
  function isThisSetStateCall(node) {
356
369
  const { callee } = node;
357
- return callee.type === AST_NODE_TYPES.MemberExpression && ast.isThisExpressionLoose(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
370
+ return callee.type === AST_NODE_TYPES.MemberExpression && Check.thisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
358
371
  }
359
372
  /**
360
373
  * @param node The assignment expression node to check.
@@ -362,7 +375,7 @@ function isThisSetStateCall(node) {
362
375
  */
363
376
  function isAssignmentToThisState(node) {
364
377
  const { left } = node;
365
- return left.type === AST_NODE_TYPES.MemberExpression && ast.isThisExpressionLoose(left.object) && ast.getPropertyName(left.property) === "state";
378
+ return left.type === AST_NODE_TYPES.MemberExpression && Check.thisExpression(left.object) && Extract.propertyName(left.property) === "state";
366
379
  }
367
380
 
368
381
  //#endregion
@@ -379,9 +392,9 @@ function getClassComponentCollector(context) {
379
392
  const getText = (n) => context.sourceCode.getText(n);
380
393
  const collect = (node) => {
381
394
  if (!isClassComponent(node)) return;
382
- const id = ast.getClassId(node);
395
+ const id = getClassId(node);
383
396
  const key = ulid();
384
- const name = id == null ? null : ast.getFullyQualifiedName(id, getText);
397
+ const name = id == null ? null : Extract.fullyQualifiedName(id, getText);
385
398
  components.set(key, {
386
399
  id,
387
400
  key,
@@ -403,6 +416,137 @@ function getClassComponentCollector(context) {
403
416
  };
404
417
  }
405
418
 
419
+ //#endregion
420
+ //#region src/function.ts
421
+ /**
422
+ * Gets the static identifier of a function AST node.
423
+ *
424
+ * @remarks
425
+ * For function declarations this is straightforward. For anonymous function
426
+ * expressions it is more complex. This function roughly detects the same AST
427
+ * nodes as the ECMAScript spec's `IsAnonymousFunctionDefinition()` with some
428
+ * exceptions to better fit our use case.
429
+ *
430
+ * Ported from {@link https://github.com/facebook/react/blob/bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts#L860 | RulesOfHooks.ts}
431
+ *
432
+ * @param node - The function node to analyze.
433
+ * @returns The identifier node if found, `null` otherwise.
434
+ */
435
+ function getFunctionId(node) {
436
+ switch (true) {
437
+ case "id" in node && node.id != null: return node.id;
438
+ case node.parent.type === AST_NODE_TYPES.VariableDeclarator && node.parent.init === node: return node.parent.id;
439
+ case node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.right === node && node.parent.operator === "=": return node.parent.left;
440
+ case node.parent.type === AST_NODE_TYPES.Property && node.parent.value === node && !node.parent.computed: return node.parent.key;
441
+ case Check.isMethodOrProperty(node.parent) && node.parent.value === node: return node.parent.key;
442
+ case node.parent.type === AST_NODE_TYPES.AssignmentPattern && node.parent.right === node: return node.parent.left;
443
+ case node.parent.type === AST_NODE_TYPES.ConditionalExpression: return getFunctionId(node.parent);
444
+ case Check.isTypeAssertionExpression(node.parent): return getFunctionId(node.parent);
445
+ }
446
+ return null;
447
+ }
448
+ /**
449
+ * Identifies the initialization path of a function node in the AST.
450
+ *
451
+ * @param node - The function node to analyze.
452
+ * @returns The function initialization path or `null` if not identifiable.
453
+ */
454
+ function getFunctionInitPath(node) {
455
+ if (node.type === AST_NODE_TYPES.FunctionDeclaration) return [node];
456
+ let parent = node.parent;
457
+ while (Check.isTypeExpression(parent)) parent = parent.parent;
458
+ switch (true) {
459
+ case parent.type === AST_NODE_TYPES.VariableDeclarator: return [
460
+ parent.parent,
461
+ parent,
462
+ node
463
+ ];
464
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
465
+ parent.parent.parent,
466
+ parent.parent,
467
+ parent,
468
+ node
469
+ ];
470
+ case parent.type === AST_NODE_TYPES.CallExpression && parent.parent.type === AST_NODE_TYPES.CallExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
471
+ parent.parent.parent.parent,
472
+ parent.parent.parent,
473
+ parent.parent,
474
+ parent,
475
+ node
476
+ ];
477
+ case parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator: return [
478
+ parent.parent.parent.parent,
479
+ parent.parent.parent,
480
+ parent.parent,
481
+ parent,
482
+ node
483
+ ];
484
+ case parent.type === AST_NODE_TYPES.MethodDefinition: return [
485
+ parent.parent.parent,
486
+ parent.parent,
487
+ parent,
488
+ node
489
+ ];
490
+ case parent.type === AST_NODE_TYPES.PropertyDefinition: return [
491
+ parent.parent.parent,
492
+ parent.parent,
493
+ parent,
494
+ node
495
+ ];
496
+ }
497
+ return null;
498
+ }
499
+ /**
500
+ * Checks if a specific function call exists in the function initialization path.
501
+ *
502
+ * @param callName - The name of the call to check for (e.g., "memo", "forwardRef").
503
+ * @param initPath - The function initialization path to search in.
504
+ * @returns `true` if the call exists in the path, `false` otherwise.
505
+ */
506
+ function isFunctionHasCallInInitPath(callName, initPath) {
507
+ return initPath.some((node) => {
508
+ if (node.type !== AST_NODE_TYPES.CallExpression) return false;
509
+ const { callee } = node;
510
+ if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === callName;
511
+ if (callee.type === AST_NODE_TYPES.MemberExpression && "name" in callee.property) return callee.property.name === callName;
512
+ return false;
513
+ });
514
+ }
515
+ /**
516
+ * Checks if a function is empty.
517
+ *
518
+ * @param node - The function node to check.
519
+ * @returns `true` if the function is empty, `false` otherwise.
520
+ */
521
+ function isFunctionEmpty(node) {
522
+ return node.body.type === AST_NODE_TYPES.BlockStatement && node.body.body.length === 0;
523
+ }
524
+ /**
525
+ * Gets all directive expression statements from the top of a function body.
526
+ *
527
+ * @param node - The function AST node.
528
+ * @returns An array of directive expression statements.
529
+ */
530
+ function getFunctionDirectives(node) {
531
+ const directives = [];
532
+ if (node.body.type !== AST_NODE_TYPES.BlockStatement) return directives;
533
+ for (const stmt of node.body.body) {
534
+ if (!Check.directive(stmt)) continue;
535
+ directives.push(stmt);
536
+ }
537
+ return directives;
538
+ }
539
+ /**
540
+ * Checks if a directive with the given name exists in the function directives.
541
+ *
542
+ * @param node - The function AST node.
543
+ * @param name - The directive name to check (e.g., "use memo", "use no memo").
544
+ * @returns `true` if the directive exists, `false` otherwise.
545
+ */
546
+ function isFunctionHasDirective(node, name) {
547
+ return getFunctionDirectives(node).some((d) => d.directive === name);
548
+ }
549
+
406
550
  //#endregion
407
551
  //#region src/function-component.ts
408
552
  /**
@@ -423,8 +567,8 @@ const FunctionComponentFlag = {
423
567
  */
424
568
  function getFunctionComponentFlagFromInitPath(initPath) {
425
569
  let flag = FunctionComponentFlag.None;
426
- if (initPath != null && ast.hasCallInFunctionInitPath("memo", initPath)) flag |= FunctionComponentFlag.Memo;
427
- if (initPath != null && ast.hasCallInFunctionInitPath("forwardRef", initPath)) flag |= FunctionComponentFlag.ForwardRef;
570
+ if (initPath != null && isFunctionHasCallInInitPath("memo", initPath)) flag |= FunctionComponentFlag.Memo;
571
+ if (initPath != null && isFunctionHasCallInInitPath("forwardRef", initPath)) flag |= FunctionComponentFlag.ForwardRef;
428
572
  return flag;
429
573
  }
430
574
  /**
@@ -444,9 +588,9 @@ function isFunctionComponentWrapperCall(context, node) {
444
588
  * @returns `true` if the node is a callback function passed to a component wrapper
445
589
  */
446
590
  function isFunctionComponentWrapperCallback(context, node) {
447
- if (!ast.isFunction(node)) return false;
591
+ if (!Check.isFunction(node)) return false;
448
592
  let parent = node.parent;
449
- while (ast.isTypeExpression(parent)) parent = parent.parent;
593
+ while (Check.isTypeExpression(parent)) parent = parent.parent;
450
594
  if (parent.type !== AST_NODE_TYPES.CallExpression) return false;
451
595
  return isFunctionComponentWrapperCall(context, parent);
452
596
  }
@@ -457,10 +601,10 @@ function isFunctionComponentWrapperCallback(context, node) {
457
601
  * @internal
458
602
  */
459
603
  function getFunctionComponentId(context, node) {
460
- const functionId = ast.getFunctionId(node);
604
+ const functionId = getFunctionId(node);
461
605
  if (functionId != null) return functionId;
462
606
  let parent = node.parent;
463
- while (ast.isTypeExpression(parent)) parent = parent.parent;
607
+ while (Check.isTypeExpression(parent)) parent = parent.parent;
464
608
  if (parent.type === AST_NODE_TYPES.CallExpression && isFunctionComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator) return parent.parent.id;
465
609
  if (parent.type === AST_NODE_TYPES.CallExpression && isFunctionComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isFunctionComponentWrapperCall(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator) return parent.parent.parent.id;
466
610
  return null;
@@ -526,15 +670,15 @@ function isFunctionComponentDefinition(context, node, hint) {
526
670
  case isRenderMethodCallback(node): return false;
527
671
  }
528
672
  let parent = node.parent;
529
- while (ast.isTypeExpression(parent)) parent = parent.parent;
673
+ while (Check.isTypeExpression(parent)) parent = parent.parent;
530
674
  switch (true) {
531
- case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression:
675
+ case isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression:
532
676
  if (hint & FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsObjectMethod) return false;
533
677
  break;
534
- case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.MethodDefinition:
678
+ case isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.MethodDefinition:
535
679
  if (hint & FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsClassMethod) return false;
536
680
  break;
537
- case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property:
681
+ case isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property:
538
682
  if (hint & FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsClassProperty) return false;
539
683
  break;
540
684
  case parent.type === AST_NODE_TYPES.ArrayPattern:
@@ -549,11 +693,11 @@ function isFunctionComponentDefinition(context, node, hint) {
549
693
  case parent.type === AST_NODE_TYPES.CallExpression && parent.callee.type === AST_NODE_TYPES.MemberExpression && parent.callee.property.type === AST_NODE_TYPES.Identifier && parent.callee.property.name === "flatMap":
550
694
  if (hint & FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayFlatMapCallback) return false;
551
695
  break;
552
- case parent.type === AST_NODE_TYPES.CallExpression && ast.getFunctionId(node) == null && !isFunctionComponentWrapperCall(context, parent) && !isCreateElementCall(context, parent):
696
+ case parent.type === AST_NODE_TYPES.CallExpression && getFunctionId(node) == null && !isFunctionComponentWrapperCall(context, parent) && !isCreateElementCall(context, parent):
553
697
  if (hint & FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArbitraryCallExpressionCallback) return false;
554
698
  break;
555
699
  }
556
- const significantParent = ast.findParent(node, ast.isOneOf([
700
+ const significantParent = Traverse.findParent(node, isOneOf([
557
701
  AST_NODE_TYPES.JSXExpressionContainer,
558
702
  AST_NODE_TYPES.ArrowFunctionExpression,
559
703
  AST_NODE_TYPES.FunctionExpression,
@@ -616,7 +760,7 @@ function isHookId(id) {
616
760
  */
617
761
  function isHookDefinition(node) {
618
762
  if (node == null) return false;
619
- const id = ast.getFunctionId(node);
763
+ const id = getFunctionId(node);
620
764
  switch (id?.type) {
621
765
  case AST_NODE_TYPES.Identifier: return isHookName(id.name);
622
766
  case AST_NODE_TYPES.MemberExpression: return "name" in id.property && isHookName(id.property.name);
@@ -661,7 +805,7 @@ function isUseStateLikeCall(node, additionalStateHooks = { test: constFalse }) {
661
805
  if (node.type !== AST_NODE_TYPES.CallExpression) return false;
662
806
  switch (true) {
663
807
  case node.callee.type === AST_NODE_TYPES.Identifier: return node.callee.name === "useState" || additionalStateHooks.test(node.callee.name);
664
- case node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier: return ast.getPropertyName(node.callee.property) === "useState" || additionalStateHooks.test(node.callee.property.name);
808
+ case node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier: return Extract.propertyName(node.callee.property) === "useState" || additionalStateHooks.test(node.callee.property.name);
665
809
  }
666
810
  return false;
667
811
  }
@@ -679,9 +823,9 @@ function isUseEffectSetupCallback(node) {
679
823
  */
680
824
  function isUseEffectCleanupCallback(node) {
681
825
  if (node == null) return false;
682
- const returnStatement = ast.findParent(node, ast.is(AST_NODE_TYPES.ReturnStatement));
683
- const enclosingFunction = ast.findParent(node, ast.isFunction);
684
- if (enclosingFunction !== ast.findParent(returnStatement, ast.isFunction)) return false;
826
+ const returnStatement = Traverse.findParent(node, is(AST_NODE_TYPES.ReturnStatement));
827
+ const enclosingFunction = Traverse.findParent(node, Check.isFunction);
828
+ if (enclosingFunction !== Traverse.findParent(returnStatement, Check.isFunction)) return false;
685
829
  return isUseEffectSetupCallback(enclosingFunction);
686
830
  }
687
831
 
@@ -701,13 +845,13 @@ function getFunctionComponentCollector(context, options = {}) {
701
845
  const getCurrentEntry = () => functionEntries.at(-1) ?? null;
702
846
  const onFunctionEnter = (node) => {
703
847
  const key = ulid();
704
- const exp = ast.findParent(node, (n) => n.type === AST_NODE_TYPES.ExportDefaultDeclaration);
848
+ const exp = Traverse.findParent(node, (n) => n.type === AST_NODE_TYPES.ExportDefaultDeclaration);
705
849
  const isExportDefault = exp != null;
706
- const isExportDefaultDeclaration = exp != null && ast.getUnderlyingExpression(exp.declaration) === node;
850
+ const isExportDefaultDeclaration = exp != null && Extract.unwrapped(exp.declaration) === node;
707
851
  const id = getFunctionComponentId(context, node);
708
- const name = id == null ? null : ast.getFullyQualifiedName(id, getText);
709
- const initPath = ast.getFunctionInitPath(node);
710
- const directives = ast.getFunctionDirectives(node);
852
+ const name = id == null ? null : Extract.fullyQualifiedName(id, getText);
853
+ const initPath = getFunctionInitPath(node);
854
+ const directives = getFunctionDirectives(node);
711
855
  const entry = {
712
856
  id,
713
857
  key,
@@ -749,7 +893,7 @@ function getFunctionComponentCollector(context, options = {}) {
749
893
  if (!components.has(entry.key) && !isJsxLike(context, body, hint)) return;
750
894
  components.set(entry.key, entry);
751
895
  },
752
- ...collectDisplayName ? { [ast.SEL_DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
896
+ ...collectDisplayName ? { [Select.displayNameAssignment](node) {
753
897
  const { left, right } = node;
754
898
  if (left.type !== AST_NODE_TYPES.MemberExpression) return;
755
899
  const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : null;
@@ -791,13 +935,13 @@ function getHookCollector(context) {
791
935
  const getText = (n) => context.sourceCode.getText(n);
792
936
  const getCurrentEntry = () => functionEntries.at(-1) ?? null;
793
937
  const onFunctionEnter = (node) => {
794
- const id = ast.getFunctionId(node);
938
+ const id = getFunctionId(node);
795
939
  const key = ulid();
796
940
  const entry = {
797
941
  id,
798
942
  key,
799
943
  kind: "hook",
800
- name: id == null ? null : ast.getFullyQualifiedName(id, getText),
944
+ name: id == null ? null : Extract.fullyQualifiedName(id, getText),
801
945
  directives: [],
802
946
  flag: 0n,
803
947
  hint: 0n,
@@ -989,4 +1133,4 @@ function getTypeVariants(types) {
989
1133
  }
990
1134
 
991
1135
  //#endregion
992
- export { DEFAULT_COMPONENT_DETECTION_HINT, FunctionComponentDetectionHint, FunctionComponentFlag, REACT_BUILTIN_HOOK_NAMES, getClassComponentCollector, getFullyQualifiedNameEx, getFunctionComponentCollector, getFunctionComponentFlagFromInitPath, getFunctionComponentId, getHookCollector, getTypeVariants, isAPI, isAPICall, isAPIFromReact, isAPIFromReactNative, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanLiteralType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isClassComponentLoose, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFunctionComponentDefinition, isFunctionComponentName, isFunctionComponentNameLoose, isFunctionComponentWrapperCall, isFunctionComponentWrapperCallback, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHookCall, isHookDefinition, isHookId, isHookName, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isStringType, isThisSetStateCall, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUse, isUseActionState, isUseActionStateCall, isUseCall, isUseCallback, isUseCallbackCall, isUseContext, isUseContextCall, isUseDebugValue, isUseDebugValueCall, isUseDeferredValue, isUseDeferredValueCall, isUseEffect, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatus, isUseFormStatusCall, isUseId, isUseIdCall, isUseImperativeHandle, isUseImperativeHandleCall, isUseInsertionEffect, isUseInsertionEffectCall, isUseLayoutEffect, isUseLayoutEffectCall, isUseMemo, isUseMemoCall, isUseOptimistic, isUseOptimisticCall, isUseReducer, isUseReducerCall, isUseRef, isUseRefCall, isUseState, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStore, isUseSyncExternalStoreCall, isUseTransition, isUseTransitionCall };
1136
+ export { DEFAULT_COMPONENT_DETECTION_HINT, FunctionComponentDetectionHint, FunctionComponentFlag, REACT_BUILTIN_HOOK_NAMES, getClassComponentCollector, getClassId, getFullyQualifiedNameEx, getFunctionComponentCollector, getFunctionComponentFlagFromInitPath, getFunctionComponentId, getFunctionDirectives, getFunctionId, getFunctionInitPath, getHookCollector, getTypeVariants, isAPI, isAPICall, isAPIFromReact, isAPIFromReactNative, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanLiteralType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isClassComponentLoose, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFunctionComponentDefinition, isFunctionComponentName, isFunctionComponentNameLoose, isFunctionComponentWrapperCall, isFunctionComponentWrapperCallback, isFunctionEmpty, isFunctionHasCallInInitPath, isFunctionHasDirective, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHookCall, isHookDefinition, isHookId, isHookName, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isStringType, isThisSetStateCall, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUse, isUseActionState, isUseActionStateCall, isUseCall, isUseCallback, isUseCallbackCall, isUseContext, isUseContextCall, isUseDebugValue, isUseDebugValueCall, isUseDeferredValue, isUseDeferredValueCall, isUseEffect, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatus, isUseFormStatusCall, isUseId, isUseIdCall, isUseImperativeHandle, isUseImperativeHandleCall, isUseInsertionEffect, isUseInsertionEffectCall, isUseLayoutEffect, isUseLayoutEffectCall, isUseMemo, isUseMemoCall, isUseOptimistic, isUseOptimisticCall, isUseReducer, isUseReducerCall, isUseRef, isUseRefCall, isUseState, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStore, isUseSyncExternalStoreCall, isUseTransition, isUseTransitionCall };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "5.2.1-next.1",
3
+ "version": "5.2.2-beta.0",
4
4
  "description": "ESLint React's ESLint utility module for static analysis of React core APIs and patterns.",
5
5
  "homepage": "https://github.com/Rel1cx/eslint-react",
6
6
  "bugs": {
@@ -35,11 +35,11 @@
35
35
  "@typescript-eslint/utils": "^8.58.1",
36
36
  "ts-pattern": "^5.9.0",
37
37
  "ulid": "^3.0.2",
38
- "@eslint-react/ast": "5.2.1-next.1",
39
- "@eslint-react/eslint": "5.2.1-next.1",
40
- "@eslint-react/jsx": "5.2.1-next.1",
41
- "@eslint-react/shared": "5.2.1-next.1",
42
- "@eslint-react/var": "5.2.1-next.1"
38
+ "@eslint-react/ast": "5.2.2-beta.0",
39
+ "@eslint-react/jsx": "5.2.2-beta.0",
40
+ "@eslint-react/shared": "5.2.2-beta.0",
41
+ "@eslint-react/eslint": "5.2.2-beta.0",
42
+ "@eslint-react/var": "5.2.2-beta.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@typescript-eslint/typescript-estree": "^8.58.1",