@eslint-react/core 2.0.0-next.150 → 2.0.0-next.152

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 +158 -75
  2. package/dist/index.js +199 -136
  3. package/package.json +6 -6
package/dist/index.d.ts CHANGED
@@ -188,7 +188,14 @@ declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.Retu
188
188
  * @returns `true` if node is a render function, `false` if not
189
189
  */
190
190
  declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
191
- declare function isValidComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
191
+ /**
192
+ * Determines if a function node represents a valid React component definition
193
+ * @param context The rule context
194
+ * @param node The function node to check
195
+ * @param hint Component detection hints as bit flags
196
+ * @returns `true` if the node is a valid component definition, `false` otherwise
197
+ */
198
+ declare function isComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
192
199
  //#endregion
193
200
  //#region src/component/component-id.d.ts
194
201
  declare function getFunctionComponentId(context: RuleContext, node: AST.TSESTreeFunction): TSESTree.Identifier | TSESTree.Identifier[] | unit;
@@ -214,23 +221,24 @@ declare function isPureComponent(node: TSESTree.Node): boolean;
214
221
  type ComponentKind = "classComponent" | "functionComponent";
215
222
  //#endregion
216
223
  //#region src/component/component-method.d.ts
217
- declare function isComponentDidCatch(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
218
- declare function isComponentDidMount(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
219
- declare function isComponentDidUpdate(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
220
- declare function isComponentWillMount(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
221
- declare function isComponentWillReceiveProps(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
222
- declare function isComponentWillUnmount(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
223
- declare function isComponentWillUpdate(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
224
- declare function isGetChildContext(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
225
- declare function isGetDefaultProps(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
226
- declare function isGetInitialState(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
227
- declare function isGetSnapshotBeforeUpdate(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
228
- declare function isShouldComponentUpdate(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
229
- declare function isUnsafeComponentWillMount(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
230
- declare function isUnsafeComponentWillReceiveProps(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
231
- declare function isUnsafeComponentWillUpdate(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
232
- declare function isGetDerivedStateFromProps(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
233
- declare function isGetDerivedStateFromError(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
224
+ declare const isRender: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
225
+ declare const isComponentDidCatch: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
226
+ declare const isComponentDidMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
227
+ declare const isComponentDidUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
228
+ declare const isComponentWillMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
229
+ declare const isComponentWillReceiveProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
230
+ declare const isComponentWillUnmount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
231
+ declare const isComponentWillUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
232
+ declare const isGetChildContext: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
233
+ declare const isGetInitialState: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
234
+ declare const isGetSnapshotBeforeUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
235
+ declare const isShouldComponentUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
236
+ declare const isUnsafeComponentWillMount: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
237
+ declare const isUnsafeComponentWillReceiveProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
238
+ declare const isUnsafeComponentWillUpdate: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
239
+ declare const isGetDefaultProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
240
+ declare const isGetDerivedStateFromProps: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
241
+ declare const isGetDerivedStateFromError: (node: TSESTree.Node) => node is AST.TSESTreeMethodOrProperty;
234
242
  //#endregion
235
243
  //#region src/component/component-name.d.ts
236
244
  declare function isComponentName(name: string): boolean;
@@ -238,33 +246,6 @@ declare function isComponentNameLoose(name: string): boolean;
238
246
  declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
239
247
  declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
240
248
  //#endregion
241
- //#region src/component/component-render.d.ts
242
- /**
243
- * Check whether given node is a render function of a class component
244
- * @example
245
- * ```tsx
246
- * class Component extends React.Component {
247
- * render() {
248
- * return <div />;
249
- * }
250
- * }
251
- * ```
252
- * @param node The AST node to check
253
- * @returns `true` if node is a render function, `false` if not
254
- */
255
- declare function isRenderLike(node: TSESTree.Node): node is AST.TSESTreeMethodOrProperty;
256
- /**
257
- * Check whether given node is a function of a render function of a class component
258
- * @example
259
- * ```tsx
260
- * class Component extends React.Component {
261
- * render = () => <div />;
262
- * ```
263
- * @param node The AST node to check
264
- * @returns `true` if node is a render function, `false` if not
265
- */
266
- declare function isFunctionOfRender(node: AST.TSESTreeFunction): boolean;
267
- //#endregion
268
249
  //#region src/component/component-render-method.d.ts
269
250
  /**
270
251
  * Check whether given node is a render method of a class component
@@ -378,6 +359,11 @@ declare function useHookCollector(): useHookCollector.ReturnType;
378
359
  declare function isReactHookId(id: TSESTree.Identifier | TSESTree.MemberExpression): boolean;
379
360
  //#endregion
380
361
  //#region src/hook/hook-is.d.ts
362
+ /**
363
+ * Determines if a function node is a React Hook based on its name.
364
+ * @param node The function node to check
365
+ * @returns True if the function is a React Hook, false otherwise
366
+ */
381
367
  declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
382
368
  /**
383
369
  * Check if the given node is a React Hook call by its name.
@@ -385,9 +371,33 @@ declare function isReactHook(node: AST.TSESTreeFunction | unit): boolean;
385
371
  * @returns `true` if the node is a React Hook call, `false` otherwise.
386
372
  */
387
373
  declare function isReactHookCall(node: TSESTree.Node | unit): boolean;
374
+ /**
375
+ * Checks if a node is a call to a specific React hook, with React import validation.
376
+ * Returns a function that accepts a hook name to check against.
377
+ * @param context The rule context
378
+ * @param node The AST node to check
379
+ * @returns A function that takes a hook name and returns boolean
380
+ */
388
381
  declare function isReactHookCallWithName(context: RuleContext, node: TSESTree.Node | unit): (name: string) => boolean;
382
+ /**
383
+ * Lightweight version of isReactHookCallWithName that doesn't check imports.
384
+ * @param node The AST node to check
385
+ * @returns A function that takes a hook name and returns boolean
386
+ */
389
387
  declare function isReactHookCallWithNameLoose(node: TSESTree.Node | unit): (name: string) => boolean;
388
+ /**
389
+ * Checks if a node is a call to a specific React hook or one of its aliases.
390
+ * @param context The rule context
391
+ * @param name The primary hook name to check
392
+ * @param alias Optional array of alias names to also accept
393
+ * @returns Function that checks if a node matches the hook name or aliases
394
+ */
390
395
  declare function isReactHookCallWithNameAlias(context: RuleContext, name: string, alias?: unit | string[]): (node: TSESTree.CallExpression) => boolean;
396
+ /**
397
+ * Detects useEffect calls and variations (useLayoutEffect, etc.) using regex pattern.
398
+ * @param node The AST node to check
399
+ * @returns True if the node is a useEffect-like call
400
+ */
391
401
  declare function isUseEffectCallLoose(node: TSESTree.Node | unit): boolean;
392
402
  declare const isUseCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
393
403
  declare const isUseActionStateCall: (context: RuleContext, node: TSESTree.Node | undefined) => boolean;
@@ -421,12 +431,14 @@ declare function isReactHookName(name: string): boolean;
421
431
  //#endregion
422
432
  //#region src/jsx/jsx-attribute.d.ts
423
433
  /**
424
- * Get the JSX attribute node with the given name
425
- * @param context The ESLint rule context
426
- * @param name The name of the attribute
427
- * @param attributes The attributes to search
428
- * @param initialScope The initial scope to use for variable resolution
429
- * @returns The JSX attribute node or undefined
434
+ * Searches for a specific JSX attribute by name in a list of attributes
435
+ * Returns the last matching attribute (rightmost in JSX)
436
+ *
437
+ * @param context - ESLint rule context
438
+ * @param name - The name of the attribute to find
439
+ * @param attributes - Array of JSX attributes to search through
440
+ * @param initialScope - Optional scope for resolving variables
441
+ * @returns The found attribute or undefined
430
442
  */
431
443
  declare function getAttribute(context: RuleContext, name: string, attributes: (TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute)[], initialScope?: Scope): TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute | unit;
432
444
  //#endregion
@@ -441,18 +453,27 @@ declare function getAttributeName(context: RuleContext, node: TSESTree$1.JSXAttr
441
453
  //#endregion
442
454
  //#region src/jsx/jsx-attribute-value.d.ts
443
455
  /**
444
- * Get a StaticValue of the attribute value
445
- * @param context The rule context
446
- * @param node The JSX attribute node
447
- * @param name The name of the attribute
448
- * @returns The StaticValue of the attribute value
456
+ * Extracts the value of a JSX attribute by name
457
+ * @param context - ESLint rule context
458
+ * @param node - JSX attribute or spread attribute node
459
+ * @param name - Name of the attribute to extract
460
+ * @returns The extracted attribute value in a structured format
449
461
  */
450
462
  declare function getAttributeValue(context: RuleContext, node: TSESTree$1.JSXAttribute | TSESTree$1.JSXSpreadAttribute, name: string): Exclude<VAR.LazyValue, {
451
463
  kind: "lazy";
452
464
  }>;
453
465
  //#endregion
454
466
  //#region src/jsx/jsx-detection-hint.d.ts
467
+ /**
468
+ * BitFlags for configuring JSX detection behavior
469
+ * Uses BigInt for bit operations to support many flags
470
+ */
455
471
  type JSXDetectionHint = bigint;
472
+ /**
473
+ * Flags to control JSX detection behavior:
474
+ * - Skip* flags: Ignore specific node types when detecting JSX
475
+ * - Strict* flags: Enforce stricter rules for container types
476
+ */
456
477
  declare const JSXDetectionHint: {
457
478
  readonly None: 0n;
458
479
  readonly SkipUndefined: bigint;
@@ -467,59 +488,115 @@ declare const JSXDetectionHint: {
467
488
  readonly StrictLogical: bigint;
468
489
  readonly StrictConditional: bigint;
469
490
  };
491
+ /**
492
+ * Default JSX detection configuration
493
+ * Skips undefined and boolean literals (common in React)
494
+ */
470
495
  declare const DEFAULT_JSX_DETECTION_HINT: bigint;
471
496
  //#endregion
472
497
  //#region src/jsx/jsx-detection.d.ts
473
498
  /**
474
- * Check if a node is a `JSXText` or a `Literal` node
499
+ * Checks if a node is a `JSXText` or a `Literal` node
475
500
  * @param node The AST node to check
476
501
  * @returns `true` if the node is a `JSXText` or a `Literal` node
477
502
  */
478
503
  declare function isJsxText(node: TSESTree$1.Node | null | unit): node is TSESTree$1.JSXText | TSESTree$1.Literal;
479
504
  /**
480
- * Heuristic decision to determine if a node is a JSX-like node.
481
- * @param code The sourceCode object
505
+ * Determines if a node represents JSX-like content based on heuristics
506
+ * Supports configuration through hint flags to customize detection behavior
507
+ *
508
+ * @param code The source code with scope lookup capability
482
509
  * @param code.getScope The function to get the scope of a node
483
- * @param node The AST node to check
484
- * @param hint The `JSXDetectionHint` to use
485
- * @returns boolean
510
+ * @param node The AST node to analyze
511
+ * @param hint The configuration flags to adjust detection behavior
512
+ * @returns boolean Whether the node is considered JSX-like
486
513
  */
487
514
  declare function isJsxLike(code: {
488
515
  getScope: (node: TSESTree$1.Node) => Scope;
489
516
  }, node: TSESTree$1.Node | unit | null, hint?: JSXDetectionHint): boolean;
490
517
  //#endregion
491
518
  //#region src/jsx/jsx-element-is.d.ts
519
+ /**
520
+ * Determines if a JSX element is a host element
521
+ * Host elements in React start with lowercase letters (e.g., div, span)
522
+ *
523
+ * @param context - ESLint rule context
524
+ * @param node - AST node to check
525
+ * @returns boolean indicating if the element is a host element
526
+ */
492
527
  declare function isHostElement(context: RuleContext, node: TSESTree.Node): boolean;
528
+ /**
529
+ * Determines if a JSX element is a React Fragment
530
+ * Fragments can be imported from React and used like <Fragment> or <React.Fragment>
531
+ *
532
+ * @param context - ESLint rule context
533
+ * @param node - AST node to check
534
+ * @returns boolean indicating if the element is a Fragment with type narrowing
535
+ */
493
536
  declare function isFragmentElement(context: RuleContext, node: TSESTree.Node): node is TSESTree.JSXElement;
494
537
  //#endregion
495
538
  //#region src/jsx/jsx-element-type.d.ts
496
539
  /**
497
- * Get the stringified type of a JSX element
498
- * @param context The ESLint rule context
499
- * @param node The JSX element node
500
- * @returns The type of the element
540
+ * Extracts the element type name from a JSX element or fragment
541
+ * For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
542
+ * For JSX fragments, returns an empty string
543
+ *
544
+ * @param context - ESLint rule context
545
+ * @param node - JSX element or fragment node
546
+ * @returns String representation of the element type
501
547
  */
502
548
  declare function getElementType(context: RuleContext, node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
503
549
  //#endregion
504
550
  //#region src/jsx/jsx-has.d.ts
551
+ /**
552
+ * Checks if a JSX element has a specific attribute
553
+ *
554
+ * @param context - ESLint rule context
555
+ * @param name - Name of the attribute to check for
556
+ * @param attributes - List of JSX attributes from opening element
557
+ * @param initialScope - Optional scope for resolving variables in spread attributes
558
+ * @returns boolean indicating whether the attribute exists
559
+ */
505
560
  declare function hasAttribute(context: RuleContext, name: string, attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
561
+ /**
562
+ * Checks if a JSX element has at least one of the specified attributes
563
+ *
564
+ * @param context - ESLint rule context
565
+ * @param names - Array of attribute names to check for
566
+ * @param attributes - List of JSX attributes from opening element
567
+ * @param initialScope - Optional scope for resolving variables in spread attributes
568
+ * @returns boolean indicating whether any of the attributes exist
569
+ */
506
570
  declare function hasAnyAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
571
+ /**
572
+ * Checks if a JSX element has all of the specified attributes
573
+ *
574
+ * @param context - ESLint rule context
575
+ * @param names - Array of attribute names to check for
576
+ * @param attributes - List of JSX attributes from opening element
577
+ * @param initialScope - Optional scope for resolving variables in spread attributes
578
+ * @returns boolean indicating whether all of the attributes exist
579
+ */
507
580
  declare function hasEveryAttribute(context: RuleContext, names: string[], attributes: TSESTree.JSXOpeningElement["attributes"], initialScope?: Scope): boolean;
508
581
  //#endregion
509
582
  //#region src/jsx/jsx-hierarchy.d.ts
510
583
  /**
511
- * Find the parent JSX attribute node of a node
512
- * @param node The node to find the parent attribute of
513
- * @param test The test to apply to the parent attribute
514
- * @returns The parent attribute node or undefined
584
+ * Traverses up the AST to find a parent JSX attribute node that matches a given test
585
+ *
586
+ * @param node - The starting AST node
587
+ * @param test - Optional predicate function to test if the attribute meets criteria
588
+ * Defaults to always returning true (matches any attribute)
589
+ * @returns The first matching JSX attribute node found when traversing upwards, or undefined
515
590
  */
516
591
  declare function findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | unit;
517
592
  //#endregion
518
593
  //#region src/jsx/jsx-stringify.d.ts
519
594
  /**
520
- * Get the stringified representation of a JSX node
521
- * @param node The JSX node
522
- * @returns The stringified representation
595
+ * Converts a JSX AST node to its string representation
596
+ * Handles different JSX node types and returns their textual form
597
+ *
598
+ * @param node - JSX node from TypeScript ESTree
599
+ * @returns String representation of the JSX node
523
600
  */
524
601
  declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXClosingElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXText): string;
525
602
  //#endregion
@@ -636,7 +713,13 @@ type TypeVariant = "any" | "bigint" | "boolean" | "enum" | "never" | "nullish" |
636
713
  declare function getTypeVariants(types: ts.Type[]): Set<TypeVariant>;
637
714
  //#endregion
638
715
  //#region src/utils/get-instance-id.d.ts
639
- /** @internal */
716
+ /**
717
+ * Gets the identifier node of an instance based on AST node relationships.
718
+ * Used for tracking where hooks or components are being assigned in the code.
719
+ * @param node The current AST node to evaluate
720
+ * @param prev The previous AST node in the traversal (used for context)
721
+ * @internal
722
+ */
640
723
  declare function getInstanceId(node: TSESTree.Node, prev?: TSESTree.Node): TSESTree.ArrayExpression | TSESTree.ArrayPattern | TSESTree.ArrowFunctionExpression | TSESTree.AssignmentExpression | TSESTree.AwaitExpression | TSESTree.BinaryExpression | 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.LogicalExpression | TSESTree.MemberExpressionComputedName | TSESTree.MemberExpressionNonComputedName | TSESTree.MetaProperty | TSESTree.NewExpression | TSESTree.ObjectExpression | TSESTree.ObjectPattern | TSESTree.PrivateIdentifier | TSESTree.SequenceExpression | TSESTree.Super | TSESTree.TaggedTemplateExpression | TSESTree.TemplateLiteral | TSESTree.ThisExpression | TSESTree.TSAsExpression | TSESTree.TSInstantiationExpression | TSESTree.TSNonNullExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion | TSESTree.UnaryExpression | TSESTree.UpdateExpression | TSESTree.YieldExpression | undefined;
641
724
  //#endregion
642
725
  //#region src/utils/is-from-react.d.ts
@@ -696,4 +779,4 @@ declare const isForwardRefCall: isReactAPICall.ReturnType;
696
779
  declare const isMemoCall: isReactAPICall.ReturnType;
697
780
  declare const isLazyCall: isReactAPICall.ReturnType;
698
781
  //#endregion
699
- export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, EffectKind, FunctionComponent, Hook, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, TypeVariant, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRender, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRenderFunctionLoose, isRenderLike, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, isValidComponentDefinition, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
782
+ export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, EffectKind, FunctionComponent, Hook, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, TypeVariant, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/dist/index.js CHANGED
@@ -73,7 +73,13 @@ function isChildrenOfCreateElement(context, node) {
73
73
 
74
74
  //#endregion
75
75
  //#region src/utils/get-instance-id.ts
76
- /** @internal */
76
+ /**
77
+ * Gets the identifier node of an instance based on AST node relationships.
78
+ * Used for tracking where hooks or components are being assigned in the code.
79
+ * @param node The current AST node to evaluate
80
+ * @param prev The previous AST node in the traversal (used for context)
81
+ * @internal
82
+ */
77
83
  function getInstanceId(node, prev) {
78
84
  switch (true) {
79
85
  case node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev: return node.id;
@@ -171,6 +177,11 @@ function isReactHookName(name) {
171
177
 
172
178
  //#endregion
173
179
  //#region src/hook/hook-is.ts
180
+ /**
181
+ * Determines if a function node is a React Hook based on its name.
182
+ * @param node The function node to check
183
+ * @returns True if the function is a React Hook, false otherwise
184
+ */
174
185
  function isReactHook(node) {
175
186
  if (node == null) return false;
176
187
  const id = AST.getFunctionId(node);
@@ -188,6 +199,13 @@ function isReactHookCall(node) {
188
199
  if (node.callee.type === AST_NODE_TYPES.MemberExpression) return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);
189
200
  return false;
190
201
  }
202
+ /**
203
+ * Checks if a node is a call to a specific React hook, with React import validation.
204
+ * Returns a function that accepts a hook name to check against.
205
+ * @param context The rule context
206
+ * @param node The AST node to check
207
+ * @returns A function that takes a hook name and returns boolean
208
+ */
191
209
  function isReactHookCallWithName(context, node) {
192
210
  if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
193
211
  const { importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource, skipImportCheck = true } = coerceSettings(context.settings);
@@ -200,6 +218,11 @@ function isReactHookCallWithName(context, node) {
200
218
  }
201
219
  };
202
220
  }
221
+ /**
222
+ * Lightweight version of isReactHookCallWithName that doesn't check imports.
223
+ * @param node The AST node to check
224
+ * @returns A function that takes a hook name and returns boolean
225
+ */
203
226
  function isReactHookCallWithNameLoose(node) {
204
227
  if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
205
228
  return (name) => {
@@ -210,6 +233,13 @@ function isReactHookCallWithNameLoose(node) {
210
233
  }
211
234
  };
212
235
  }
236
+ /**
237
+ * Checks if a node is a call to a specific React hook or one of its aliases.
238
+ * @param context The rule context
239
+ * @param name The primary hook name to check
240
+ * @param alias Optional array of alias names to also accept
241
+ * @returns Function that checks if a node matches the hook name or aliases
242
+ */
213
243
  function isReactHookCallWithNameAlias(context, name, alias = []) {
214
244
  const { importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource, skipImportCheck = true } = coerceSettings(context.settings);
215
245
  return (node) => {
@@ -221,6 +251,11 @@ function isReactHookCallWithNameAlias(context, name, alias = []) {
221
251
  }
222
252
  };
223
253
  }
254
+ /**
255
+ * Detects useEffect calls and variations (useLayoutEffect, etc.) using regex pattern.
256
+ * @param node The AST node to check
257
+ * @returns True if the node is a useEffect-like call
258
+ */
224
259
  function isUseEffectCallLoose(node) {
225
260
  if (node == null) return false;
226
261
  if (node.type !== AST_NODE_TYPES.CallExpression) return false;
@@ -320,9 +355,11 @@ function isReactHookId(id) {
320
355
  //#endregion
321
356
  //#region src/jsx/jsx-stringify.ts
322
357
  /**
323
- * Get the stringified representation of a JSX node
324
- * @param node The JSX node
325
- * @returns The stringified representation
358
+ * Converts a JSX AST node to its string representation
359
+ * Handles different JSX node types and returns their textual form
360
+ *
361
+ * @param node - JSX node from TypeScript ESTree
362
+ * @returns String representation of the JSX node
326
363
  */
327
364
  function stringifyJsx(node) {
328
365
  switch (node.type) {
@@ -352,12 +389,14 @@ function getAttributeName(context, node) {
352
389
  //#endregion
353
390
  //#region src/jsx/jsx-attribute.ts
354
391
  /**
355
- * Get the JSX attribute node with the given name
356
- * @param context The ESLint rule context
357
- * @param name The name of the attribute
358
- * @param attributes The attributes to search
359
- * @param initialScope The initial scope to use for variable resolution
360
- * @returns The JSX attribute node or undefined
392
+ * Searches for a specific JSX attribute by name in a list of attributes
393
+ * Returns the last matching attribute (rightmost in JSX)
394
+ *
395
+ * @param context - ESLint rule context
396
+ * @param name - The name of the attribute to find
397
+ * @param attributes - Array of JSX attributes to search through
398
+ * @param initialScope - Optional scope for resolving variables
399
+ * @returns The found attribute or undefined
361
400
  */
362
401
  function getAttribute(context, name, attributes, initialScope) {
363
402
  return attributes.findLast((attr) => {
@@ -379,11 +418,11 @@ function getAttribute(context, name, attributes, initialScope) {
379
418
  //#endregion
380
419
  //#region src/jsx/jsx-attribute-value.ts
381
420
  /**
382
- * Get a StaticValue of the attribute value
383
- * @param context The rule context
384
- * @param node The JSX attribute node
385
- * @param name The name of the attribute
386
- * @returns The StaticValue of the attribute value
421
+ * Extracts the value of a JSX attribute by name
422
+ * @param context - ESLint rule context
423
+ * @param node - JSX attribute or spread attribute node
424
+ * @param name - Name of the attribute to extract
425
+ * @returns The extracted attribute value in a structured format
387
426
  */
388
427
  function getAttributeValue(context, node, name) {
389
428
  const initialScope = context.sourceCode.getScope(node);
@@ -433,6 +472,11 @@ function getAttributeValue(context, node, name) {
433
472
 
434
473
  //#endregion
435
474
  //#region src/jsx/jsx-detection-hint.ts
475
+ /**
476
+ * Flags to control JSX detection behavior:
477
+ * - Skip* flags: Ignore specific node types when detecting JSX
478
+ * - Strict* flags: Enforce stricter rules for container types
479
+ */
436
480
  const JSXDetectionHint = {
437
481
  None: 0n,
438
482
  SkipUndefined: 1n << 0n,
@@ -447,12 +491,16 @@ const JSXDetectionHint = {
447
491
  StrictLogical: 1n << 9n,
448
492
  StrictConditional: 1n << 10n
449
493
  };
494
+ /**
495
+ * Default JSX detection configuration
496
+ * Skips undefined and boolean literals (common in React)
497
+ */
450
498
  const DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
451
499
 
452
500
  //#endregion
453
501
  //#region src/jsx/jsx-detection.ts
454
502
  /**
455
- * Check if a node is a `JSXText` or a `Literal` node
503
+ * Checks if a node is a `JSXText` or a `Literal` node
456
504
  * @param node The AST node to check
457
505
  * @returns `true` if the node is a `JSXText` or a `Literal` node
458
506
  */
@@ -461,12 +509,14 @@ function isJsxText(node) {
461
509
  return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
462
510
  }
463
511
  /**
464
- * Heuristic decision to determine if a node is a JSX-like node.
465
- * @param code The sourceCode object
512
+ * Determines if a node represents JSX-like content based on heuristics
513
+ * Supports configuration through hint flags to customize detection behavior
514
+ *
515
+ * @param code The source code with scope lookup capability
466
516
  * @param code.getScope The function to get the scope of a node
467
- * @param node The AST node to check
468
- * @param hint The `JSXDetectionHint` to use
469
- * @returns boolean
517
+ * @param node The AST node to analyze
518
+ * @param hint The configuration flags to adjust detection behavior
519
+ * @returns boolean Whether the node is considered JSX-like
470
520
  */
471
521
  function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
472
522
  if (node == null) return false;
@@ -530,10 +580,13 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
530
580
  //#endregion
531
581
  //#region src/jsx/jsx-element-type.ts
532
582
  /**
533
- * Get the stringified type of a JSX element
534
- * @param context The ESLint rule context
535
- * @param node The JSX element node
536
- * @returns The type of the element
583
+ * Extracts the element type name from a JSX element or fragment
584
+ * For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
585
+ * For JSX fragments, returns an empty string
586
+ *
587
+ * @param context - ESLint rule context
588
+ * @param node - JSX element or fragment node
589
+ * @returns String representation of the element type
537
590
  */
538
591
  function getElementType(context, node) {
539
592
  if (node.type === AST_NODE_TYPES.JSXFragment) return "";
@@ -542,9 +595,25 @@ function getElementType(context, node) {
542
595
 
543
596
  //#endregion
544
597
  //#region src/jsx/jsx-element-is.ts
598
+ /**
599
+ * Determines if a JSX element is a host element
600
+ * Host elements in React start with lowercase letters (e.g., div, span)
601
+ *
602
+ * @param context - ESLint rule context
603
+ * @param node - AST node to check
604
+ * @returns boolean indicating if the element is a host element
605
+ */
545
606
  function isHostElement(context, node) {
546
607
  return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
547
608
  }
609
+ /**
610
+ * Determines if a JSX element is a React Fragment
611
+ * Fragments can be imported from React and used like <Fragment> or <React.Fragment>
612
+ *
613
+ * @param context - ESLint rule context
614
+ * @param node - AST node to check
615
+ * @returns boolean indicating if the element is a Fragment with type narrowing
616
+ */
548
617
  function isFragmentElement(context, node) {
549
618
  if (node.type !== AST_NODE_TYPES.JSXElement) return false;
550
619
  return getElementType(context, node).split(".").at(-1) === "Fragment";
@@ -552,12 +621,39 @@ function isFragmentElement(context, node) {
552
621
 
553
622
  //#endregion
554
623
  //#region src/jsx/jsx-has.ts
624
+ /**
625
+ * Checks if a JSX element has a specific attribute
626
+ *
627
+ * @param context - ESLint rule context
628
+ * @param name - Name of the attribute to check for
629
+ * @param attributes - List of JSX attributes from opening element
630
+ * @param initialScope - Optional scope for resolving variables in spread attributes
631
+ * @returns boolean indicating whether the attribute exists
632
+ */
555
633
  function hasAttribute(context, name, attributes, initialScope) {
556
634
  return getAttribute(context, name, attributes, initialScope) != null;
557
635
  }
636
+ /**
637
+ * Checks if a JSX element has at least one of the specified attributes
638
+ *
639
+ * @param context - ESLint rule context
640
+ * @param names - Array of attribute names to check for
641
+ * @param attributes - List of JSX attributes from opening element
642
+ * @param initialScope - Optional scope for resolving variables in spread attributes
643
+ * @returns boolean indicating whether any of the attributes exist
644
+ */
558
645
  function hasAnyAttribute(context, names, attributes, initialScope) {
559
646
  return names.some((n) => hasAttribute(context, n, attributes, initialScope));
560
647
  }
648
+ /**
649
+ * Checks if a JSX element has all of the specified attributes
650
+ *
651
+ * @param context - ESLint rule context
652
+ * @param names - Array of attribute names to check for
653
+ * @param attributes - List of JSX attributes from opening element
654
+ * @param initialScope - Optional scope for resolving variables in spread attributes
655
+ * @returns boolean indicating whether all of the attributes exist
656
+ */
561
657
  function hasEveryAttribute(context, names, attributes, initialScope) {
562
658
  return names.every((n) => hasAttribute(context, n, attributes, initialScope));
563
659
  }
@@ -565,10 +661,12 @@ function hasEveryAttribute(context, names, attributes, initialScope) {
565
661
  //#endregion
566
662
  //#region src/jsx/jsx-hierarchy.ts
567
663
  /**
568
- * Find the parent JSX attribute node of a node
569
- * @param node The node to find the parent attribute of
570
- * @param test The test to apply to the parent attribute
571
- * @returns The parent attribute node or undefined
664
+ * Traverses up the AST to find a parent JSX attribute node that matches a given test
665
+ *
666
+ * @param node - The starting AST node
667
+ * @param test - Optional predicate function to test if the attribute meets criteria
668
+ * Defaults to always returning true (matches any attribute)
669
+ * @returns The first matching JSX attribute node found when traversing upwards, or undefined
572
670
  */
573
671
  function findParentAttribute(node, test = constTrue) {
574
672
  const guard = (node$1) => {
@@ -649,21 +747,26 @@ function isRenderMethodLike(node) {
649
747
 
650
748
  //#endregion
651
749
  //#region src/component/component-definition.ts
652
- const isFunctionOfClassMethod = isMatching({
653
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
654
- parent: AST_NODE_TYPES.MethodDefinition
655
- });
656
- const isFunctionOfClassProperty = isMatching({
657
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
658
- parent: AST_NODE_TYPES.Property
659
- });
660
- const isFunctionOfObjectMethod = isMatching({
661
- type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
662
- parent: {
663
- type: AST_NODE_TYPES.Property,
664
- parent: { type: AST_NODE_TYPES.ObjectExpression }
750
+ /**
751
+ * Function pattern matchers for different contexts
752
+ */
753
+ const functionPatterns = {
754
+ classMethod: {
755
+ type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
756
+ parent: AST_NODE_TYPES.MethodDefinition
757
+ },
758
+ classProperty: {
759
+ type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
760
+ parent: AST_NODE_TYPES.Property
761
+ },
762
+ objectMethod: {
763
+ type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
764
+ parent: {
765
+ type: AST_NODE_TYPES.Property,
766
+ parent: { type: AST_NODE_TYPES.ObjectExpression }
767
+ }
665
768
  }
666
- });
769
+ };
667
770
  /**
668
771
  * Check whether given node is a function of a render method of a class component
669
772
  * @example
@@ -677,15 +780,31 @@ const isFunctionOfObjectMethod = isMatching({
677
780
  * @returns `true` if node is a render function, `false` if not
678
781
  */
679
782
  function isFunctionOfRenderMethod(node) {
680
- if (!isRenderMethodLike(node.parent)) return false;
681
- return isClassComponent(node.parent.parent.parent);
783
+ return isRenderMethodLike(node.parent) && isClassComponent(node.parent.parent.parent);
784
+ }
785
+ /**
786
+ * Checks if a function node should be excluded based on detection hints
787
+ * @param node The function node to check
788
+ * @param hint Component detection hints as bit flags
789
+ * @returns `true` if the function should be excluded, `false` otherwise
790
+ */
791
+ function shouldExcludeBasedOnHint(node, hint) {
792
+ if (hint & ComponentDetectionHint.SkipObjectMethod && isMatching(functionPatterns.objectMethod)(node)) return true;
793
+ if (hint & ComponentDetectionHint.SkipClassMethod && isMatching(functionPatterns.classMethod)(node)) return true;
794
+ if (hint & ComponentDetectionHint.SkipClassProperty && isMatching(functionPatterns.classProperty)(node)) return true;
795
+ if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return true;
796
+ return false;
682
797
  }
683
- function isValidComponentDefinition(context, node, hint) {
798
+ /**
799
+ * Determines if a function node represents a valid React component definition
800
+ * @param context The rule context
801
+ * @param node The function node to check
802
+ * @param hint Component detection hints as bit flags
803
+ * @returns `true` if the node is a valid component definition, `false` otherwise
804
+ */
805
+ function isComponentDefinition(context, node, hint) {
684
806
  if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) return false;
685
- if (hint & ComponentDetectionHint.SkipObjectMethod && isFunctionOfObjectMethod(node.parent)) return false;
686
- if (hint & ComponentDetectionHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) return false;
687
- if (hint & ComponentDetectionHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) return false;
688
- if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return false;
807
+ if (shouldExcludeBasedOnHint(node, hint)) return false;
689
808
  const significantParent = AST.findParentNode(node, AST.isOneOf([
690
809
  AST_NODE_TYPES.JSXExpressionContainer,
691
810
  AST_NODE_TYPES.ArrowFunctionExpression,
@@ -823,7 +942,7 @@ function useComponentCollector(context, options = {}) {
823
942
  const entry = getCurrentEntry();
824
943
  if (entry == null) return;
825
944
  const { body } = entry.node;
826
- const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) && isValidComponentDefinition(context, entry.node, hint);
945
+ const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) && isComponentDefinition(context, entry.node, hint);
827
946
  if (!isComponent) return;
828
947
  const initPath = AST.getFunctionInitPath(entry.node);
829
948
  const id = getFunctionComponentId(context, entry.node);
@@ -859,7 +978,7 @@ function useComponentCollector(context, options = {}) {
859
978
  "ReturnStatement[type]"(node) {
860
979
  const entry = getCurrentEntry();
861
980
  if (entry == null) return;
862
- const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) && isValidComponentDefinition(context, entry.node, hint);
981
+ const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) && isComponentDefinition(context, entry.node, hint);
863
982
  if (!isComponent) return;
864
983
  entry.isComponent = true;
865
984
  const initPath = AST.getFunctionInitPath(entry.node);
@@ -925,57 +1044,34 @@ function useComponentCollectorLegacy() {
925
1044
 
926
1045
  //#endregion
927
1046
  //#region src/component/component-method.ts
928
- function isComponentDidCatch(node) {
929
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
930
- }
931
- function isComponentDidMount(node) {
932
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
933
- }
934
- function isComponentDidUpdate(node) {
935
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidUpdate";
936
- }
937
- function isComponentWillMount(node) {
938
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillMount";
939
- }
940
- function isComponentWillReceiveProps(node) {
941
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillReceiveProps";
942
- }
943
- function isComponentWillUnmount(node) {
944
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
945
- }
946
- function isComponentWillUpdate(node) {
947
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUpdate";
948
- }
949
- function isGetChildContext(node) {
950
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getChildContext";
951
- }
952
- function isGetDefaultProps(node) {
953
- return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDefaultProps";
954
- }
955
- function isGetInitialState(node) {
956
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getInitialState";
957
- }
958
- function isGetSnapshotBeforeUpdate(node) {
959
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getSnapshotBeforeUpdate";
960
- }
961
- function isShouldComponentUpdate(node) {
962
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "shouldComponentUpdate";
963
- }
964
- function isUnsafeComponentWillMount(node) {
965
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillMount";
966
- }
967
- function isUnsafeComponentWillReceiveProps(node) {
968
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillReceiveProps";
969
- }
970
- function isUnsafeComponentWillUpdate(node) {
971
- return AST.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillUpdate";
972
- }
973
- function isGetDerivedStateFromProps(node) {
974
- return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
975
- }
976
- function isGetDerivedStateFromError(node) {
977
- return AST.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
1047
+ /**
1048
+ * Create a lifecycle method checker function
1049
+ * @param methodName The lifecycle method name
1050
+ * @param isStatic Whether the method is static
1051
+ */
1052
+ function createLifecycleChecker(methodName, isStatic) {
1053
+ return function(node) {
1054
+ return AST.isMethodOrProperty(node) && node.static === isStatic && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === methodName;
1055
+ };
978
1056
  }
1057
+ const isRender = createLifecycleChecker("render", false);
1058
+ const isComponentDidCatch = createLifecycleChecker("componentDidCatch", false);
1059
+ const isComponentDidMount = createLifecycleChecker("componentDidMount", false);
1060
+ const isComponentDidUpdate = createLifecycleChecker("componentDidUpdate", false);
1061
+ const isComponentWillMount = createLifecycleChecker("componentWillMount", false);
1062
+ const isComponentWillReceiveProps = createLifecycleChecker("componentWillReceiveProps", false);
1063
+ const isComponentWillUnmount = createLifecycleChecker("componentWillUnmount", false);
1064
+ const isComponentWillUpdate = createLifecycleChecker("componentWillUpdate", false);
1065
+ const isGetChildContext = createLifecycleChecker("getChildContext", false);
1066
+ const isGetInitialState = createLifecycleChecker("getInitialState", false);
1067
+ const isGetSnapshotBeforeUpdate = createLifecycleChecker("getSnapshotBeforeUpdate", false);
1068
+ const isShouldComponentUpdate = createLifecycleChecker("shouldComponentUpdate", false);
1069
+ const isUnsafeComponentWillMount = createLifecycleChecker("UNSAFE_componentWillMount", false);
1070
+ const isUnsafeComponentWillReceiveProps = createLifecycleChecker("UNSAFE_componentWillReceiveProps", false);
1071
+ const isUnsafeComponentWillUpdate = createLifecycleChecker("UNSAFE_componentWillUpdate", false);
1072
+ const isGetDefaultProps = createLifecycleChecker("getDefaultProps", true);
1073
+ const isGetDerivedStateFromProps = createLifecycleChecker("getDerivedStateFromProps", true);
1074
+ const isGetDerivedStateFromError = createLifecycleChecker("getDerivedStateFromError", true);
979
1075
 
980
1076
  //#endregion
981
1077
  //#region src/component/component-phase.ts
@@ -985,39 +1081,6 @@ const ComponentPhaseRelevance = birecord({
985
1081
  });
986
1082
  const isInversePhase = dual(2, (a, b) => ComponentPhaseRelevance.get(a) === b);
987
1083
 
988
- //#endregion
989
- //#region src/component/component-render.ts
990
- /**
991
- * Check whether given node is a render function of a class component
992
- * @example
993
- * ```tsx
994
- * class Component extends React.Component {
995
- * render() {
996
- * return <div />;
997
- * }
998
- * }
999
- * ```
1000
- * @param node The AST node to check
1001
- * @returns `true` if node is a render function, `false` if not
1002
- */
1003
- function isRenderLike(node) {
1004
- return AST.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
1005
- }
1006
- /**
1007
- * Check whether given node is a function of a render function of a class component
1008
- * @example
1009
- * ```tsx
1010
- * class Component extends React.Component {
1011
- * render = () => <div />;
1012
- * ```
1013
- * @param node The AST node to check
1014
- * @returns `true` if node is a render function, `false` if not
1015
- */
1016
- function isFunctionOfRender(node) {
1017
- if (!isRenderLike(node.parent)) return false;
1018
- return isClassComponent(node.parent.parent.parent);
1019
- }
1020
-
1021
1084
  //#endregion
1022
1085
  //#region src/component/component-render-prop.ts
1023
1086
  /**
@@ -1178,4 +1241,4 @@ function getTypeVariants(types) {
1178
1241
  }
1179
1242
 
1180
1243
  //#endregion
1181
- export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRender, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRenderFunctionLoose, isRenderLike, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, isValidComponentDefinition, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
1244
+ export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, REACT_BUILTIN_HOOK_NAMES, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, getTypeVariants, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAnyType, isAssignmentToThisState, isBigIntType, isBooleanType, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isEnumType, isFalseLiteralType, isFalsyBigIntType, isFalsyNumberType, isFalsyStringType, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isNeverType, isNullishType, isNumberType, isObjectType, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isStringType, isThisSetState, isTrueLiteralType, isTruthyBigIntType, isTruthyNumberType, isTruthyStringType, isUnknownType, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "2.0.0-next.150",
3
+ "version": "2.0.0-next.152",
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": {
@@ -34,11 +34,11 @@
34
34
  "birecord": "^0.1.1",
35
35
  "ts-api-utils": "^2.1.0",
36
36
  "ts-pattern": "^5.8.0",
37
- "@eslint-react/ast": "2.0.0-next.150",
38
- "@eslint-react/eff": "2.0.0-next.150",
39
- "@eslint-react/kit": "2.0.0-next.150",
40
- "@eslint-react/shared": "2.0.0-next.150",
41
- "@eslint-react/var": "2.0.0-next.150"
37
+ "@eslint-react/ast": "2.0.0-next.152",
38
+ "@eslint-react/eff": "2.0.0-next.152",
39
+ "@eslint-react/shared": "2.0.0-next.152",
40
+ "@eslint-react/kit": "2.0.0-next.152",
41
+ "@eslint-react/var": "2.0.0-next.152"
42
42
  },
43
43
  "devDependencies": {
44
44
  "tsdown": "^0.14.2",