@eslint-react/core 2.3.13-next.0 → 2.3.13-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +123 -45
  2. package/dist/index.js +236 -187
  3. package/package.json +5 -5
package/dist/index.d.ts CHANGED
@@ -1,21 +1,12 @@
1
- import { TSESTree } from "@typescript-eslint/types";
2
1
  import * as AST from "@eslint-react/ast";
3
2
  import { unit } from "@eslint-react/eff";
4
3
  import { RuleContext } from "@eslint-react/shared";
5
- import * as birecord0 from "birecord";
4
+ import { TSESTree } from "@typescript-eslint/types";
6
5
  import { ESLintUtils, TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
6
+ import * as birecord0 from "birecord";
7
7
  import { Scope } from "@typescript-eslint/scope-manager";
8
8
  import * as typescript0 from "typescript";
9
9
 
10
- //#region src/component/component-children.d.ts
11
- /**
12
- * Determines whether inside `createElement`'s children.
13
- * @param context The rule context
14
- * @param node The AST node to check
15
- * @returns `true` if the node is inside createElement's children
16
- */
17
- declare function isChildrenOfCreateElement(context: RuleContext, node: TSESTree.Node): boolean;
18
- //#endregion
19
10
  //#region src/component/component-detection-hint.d.ts
20
11
  type ComponentDetectionHint = bigint;
21
12
  /**
@@ -93,34 +84,94 @@ interface SemanticNode {
93
84
  //#region src/component/component-flag.d.ts
94
85
  type ComponentFlag = bigint;
95
86
  declare const ComponentFlag: {
87
+ /** No flags set */
96
88
  None: bigint;
89
+ /** Indicates the component is a pure component (e.g. extends PureComponent) */
97
90
  PureComponent: bigint;
91
+ /** Indicates the component creates elements using `createElement` instead of JSX */
98
92
  CreateElement: bigint;
93
+ /** Indicates the component is memoized (e.g. React.memo) */
99
94
  Memo: bigint;
95
+ /** Indicates the component forwards a ref (e.g. React.forwardRef) */
100
96
  ForwardRef: bigint;
97
+ /** Indicates the component is asynchronous */
101
98
  Async: bigint;
102
99
  };
103
100
  //#endregion
104
101
  //#region src/component/component-semantic-node.d.ts
102
+ /**
103
+ * Represents a React function component
104
+ */
105
105
  interface FunctionComponent extends SemanticNode {
106
+ /**
107
+ * The identifier or identifier sequence of the component
108
+ */
106
109
  id: unit | TSESTree.Identifier | TSESTree.Identifier[];
110
+ /**
111
+ * The kind of component
112
+ */
107
113
  kind: "function";
114
+ /**
115
+ * The AST node of the function
116
+ */
108
117
  node: AST.TSESTreeFunction;
118
+ /**
119
+ * Flags describing the component's characteristics
120
+ */
109
121
  flag: ComponentFlag;
122
+ /**
123
+ * Hint for how the component was detected
124
+ */
110
125
  hint: ComponentDetectionHint;
126
+ /**
127
+ * The initialization path of the function
128
+ */
111
129
  initPath: unit | AST.FunctionInitPath;
130
+ /**
131
+ * List of hook calls within the component
132
+ */
112
133
  hookCalls: TSESTree.CallExpression[];
134
+ /**
135
+ * The display name of the component
136
+ */
113
137
  displayName: unit | TSESTree.Expression;
114
138
  }
139
+ /**
140
+ * Represents a React class component
141
+ */
115
142
  interface ClassComponent extends SemanticNode {
143
+ /**
144
+ * The identifier of the component
145
+ */
116
146
  id: unit | TSESTree.Identifier;
147
+ /**
148
+ * The kind of component
149
+ */
117
150
  kind: "class";
151
+ /**
152
+ * The AST node of the class
153
+ */
118
154
  node: AST.TSESTreeClass;
155
+ /**
156
+ * Flags describing the component's characteristics
157
+ */
119
158
  flag: ComponentFlag;
159
+ /**
160
+ * Hint for how the component was detected
161
+ */
120
162
  hint: ComponentDetectionHint;
163
+ /**
164
+ * List of methods and properties in the class
165
+ */
121
166
  methods: AST.TSESTreeMethodOrProperty[];
167
+ /**
168
+ * The display name of the component
169
+ */
122
170
  displayName: unit | TSESTree.Expression;
123
171
  }
172
+ /**
173
+ * Union type representing either a class or function component
174
+ */
124
175
  type Component = ClassComponent | FunctionComponent;
125
176
  //#endregion
126
177
  //#region src/component/component-collector.d.ts
@@ -167,27 +218,32 @@ declare namespace useComponentCollectorLegacy {
167
218
  * @returns The context and listeners for the rule
168
219
  */
169
220
  declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.ReturnType;
170
- //#endregion
171
- //#region src/component/component-definition.d.ts
172
221
  /**
173
- * Check whether given node is a function of a render method of a class component
174
- * @example
175
- * ```tsx
176
- * class Component extends React.Component {
177
- * renderHeader = () => <div />;
178
- * renderFooter = () => <div />;
179
- * }
180
- * ```
181
- * @param node The AST node to check
182
- * @returns `true` if node is a render function, `false` if not
222
+ * Check whether the given node is a this.setState() call
223
+ * @param node The node to check
224
+ * @param node
225
+ * @internal
226
+ */
227
+ declare function isThisSetState(node: TSESTree$1.CallExpression): boolean;
228
+ /**
229
+ * Check whether the given node is an assignment to this.state
230
+ * @param node The node to check
231
+ * @param node
232
+ * @internal
183
233
  */
184
- declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
234
+ declare function isAssignmentToThisState(node: TSESTree$1.AssignmentExpression): boolean;
235
+ //#endregion
236
+ //#region src/component/component-definition.d.ts
185
237
  /**
186
238
  * Determines if a function node represents a valid React component definition
239
+ *
187
240
  * @param context The rule context
188
- * @param node The function node to check
189
- * @param hint Component detection hints as bit flags
190
- * @returns `true` if the node is a valid component definition, `false` otherwise
241
+ * @param node The function node to analyze
242
+ * @param hint Component detection hints (bit flags) to customize detection logic
243
+ * @param context
244
+ * @param node
245
+ * @param hint
246
+ * @returns `true` if the node is considered a component definition
191
247
  */
192
248
  declare function isComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
193
249
  //#endregion
@@ -239,9 +295,26 @@ declare function isFunctionOfComponentDidMount(node: TSESTree.Node): boolean;
239
295
  declare function isFunctionOfComponentWillUnmount(node: TSESTree.Node): boolean;
240
296
  //#endregion
241
297
  //#region src/component/component-name.d.ts
298
+ /**
299
+ * Check if a string matches the strict component name pattern
300
+ * @param name The name to check
301
+ */
242
302
  declare function isComponentName(name: string): boolean;
303
+ /**
304
+ * Check if a string matches the loose component name pattern
305
+ * @param name The name to check
306
+ */
243
307
  declare function isComponentNameLoose(name: string): boolean;
308
+ /**
309
+ * Get component name from an identifier or identifier sequence (e.g., MemberExpression)
310
+ * @param id The identifier or identifier sequence
311
+ */
244
312
  declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
313
+ /**
314
+ * Check if the function has no name or a loose component name
315
+ * @param context The rule context
316
+ * @param fn The function node
317
+ */
245
318
  declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
246
319
  //#endregion
247
320
  //#region src/component/component-phase-helpers.d.ts
@@ -317,11 +390,6 @@ declare function isDirectValueOfRenderPropertyLoose(node: TSESTree.Node): boolea
317
390
  */
318
391
  declare function isDeclaredInRenderPropLoose(node: TSESTree.Node): boolean;
319
392
  //#endregion
320
- //#region src/component/component-state.d.ts
321
- type ComponentStateKind = "actionState" | "state";
322
- declare function isThisSetState(node: TSESTree.CallExpression): boolean;
323
- declare function isAssignmentToThisState(node: TSESTree.AssignmentExpression): boolean;
324
- //#endregion
325
393
  //#region src/component/component-wrapper.d.ts
326
394
  /**
327
395
  * Check if the node is a call expression for a component wrapper
@@ -484,7 +552,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
484
552
  readonly toStatic: () => string | number | bigint | boolean | RegExp | null;
485
553
  } | {
486
554
  readonly kind: "expression";
487
- readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
555
+ readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
488
556
  readonly toStatic: () => unknown;
489
557
  } | {
490
558
  readonly kind: "element";
@@ -492,7 +560,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
492
560
  readonly toStatic: () => undefined;
493
561
  } | {
494
562
  readonly kind: "spreadChild";
495
- readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
563
+ readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
496
564
  readonly toStatic: () => undefined;
497
565
  } | {
498
566
  readonly kind: "spreadProps";
@@ -582,8 +650,8 @@ declare function isJsxLike(code: {
582
650
  * Determines if a JSX element is a host element
583
651
  * Host elements in React start with lowercase letters (e.g., div, span)
584
652
  *
585
- * @param context - ESLint rule context
586
- * @param node - AST node to check
653
+ * @param context ESLint rule context
654
+ * @param node AST node to check
587
655
  * @returns boolean indicating if the element is a host element
588
656
  */
589
657
  declare function isJsxHostElement(context: RuleContext, node: TSESTree.Node): boolean;
@@ -591,8 +659,8 @@ declare function isJsxHostElement(context: RuleContext, node: TSESTree.Node): bo
591
659
  * Determines if a JSX element is a React Fragment
592
660
  * Fragments can be imported from React and used like <Fragment> or <React.Fragment>
593
661
  *
594
- * @param context - ESLint rule context
595
- * @param node - AST node to check
662
+ * @param context ESLint rule context
663
+ * @param node AST node to check
596
664
  * @returns boolean indicating if the element is a Fragment with type narrowing
597
665
  */
598
666
  declare function isJsxFragmentElement(context: RuleContext, node: TSESTree.Node): node is TSESTree.JSXElement;
@@ -603,8 +671,8 @@ declare function isJsxFragmentElement(context: RuleContext, node: TSESTree.Node)
603
671
  * For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
604
672
  * For JSX fragments, returns an empty string
605
673
  *
606
- * @param context - ESLint rule context
607
- * @param node - JSX element or fragment node
674
+ * @param context ESLint rule context
675
+ * @param node JSX element or fragment node
608
676
  * @returns String representation of the element type
609
677
  */
610
678
  declare function getJsxElementType(context: RuleContext, node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
@@ -613,8 +681,8 @@ declare function getJsxElementType(context: RuleContext, node: TSESTree.JSXEleme
613
681
  /**
614
682
  * Traverses up the AST to find a parent JSX attribute node that matches a given test
615
683
  *
616
- * @param node - The starting AST node
617
- * @param test - Optional predicate function to test if the attribute meets criteria
684
+ * @param node The starting AST node
685
+ * @param test Optional predicate function to test if the attribute meets criteria
618
686
  * Defaults to always returning true (matches any attribute)
619
687
  * @returns The first matching JSX attribute node found when traversing upwards, or undefined
620
688
  */
@@ -624,7 +692,7 @@ declare function findParentJsxAttribute(node: TSESTree.Node, test?: (node: TSEST
624
692
  /**
625
693
  * Incomplete but sufficient stringification of JSX nodes for common use cases
626
694
  *
627
- * @param node - JSX node from TypeScript ESTree
695
+ * @param node JSX node from TypeScript ESTree
628
696
  * @returns String representation of the JSX node
629
697
  */
630
698
  declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXNamespacedName | TSESTree$1.JSXMemberExpression | TSESTree$1.JSXOpeningElement | TSESTree$1.JSXClosingElement | TSESTree$1.JSXOpeningFragment | TSESTree$1.JSXClosingFragment | TSESTree$1.JSXText): string;
@@ -637,7 +705,7 @@ declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXNam
637
705
  * @param prev The previous AST node in the traversal (used for context)
638
706
  * @internal
639
707
  */
640
- declare function getInstanceId(node: TSESTree.Node, prev?: TSESTree.Node): TSESTree.JSXElement | 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.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 | undefined;
708
+ declare function getInstanceId(node: TSESTree.Node, prev?: TSESTree.Node): 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.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.UnaryExpressionBitwiseNot | TSESTree.UnaryExpressionDelete | TSESTree.UnaryExpressionMinus | TSESTree.UnaryExpressionNot | TSESTree.UnaryExpressionPlus | TSESTree.UnaryExpressionTypeof | TSESTree.UnaryExpressionVoid | TSESTree.UpdateExpression | TSESTree.YieldExpression | undefined;
641
709
  //#endregion
642
710
  //#region src/utils/is-from-react.d.ts
643
711
  /**
@@ -671,6 +739,11 @@ declare namespace isReactAPI {
671
739
  (context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.MemberExpression | TSESTree.Identifier;
672
740
  };
673
741
  }
742
+ /**
743
+ * Checks if the node is a React API identifier or member expression
744
+ * @param api The React API name to check against (e.g., "useState", "React.memo")
745
+ * @returns A predicate function to check if a node matches the API
746
+ */
674
747
  declare function isReactAPI(api: string): isReactAPI.ReturnType;
675
748
  declare namespace isReactAPICall {
676
749
  type ReturnType = {
@@ -678,6 +751,11 @@ declare namespace isReactAPICall {
678
751
  (context: RuleContext): (node: unit | null | TSESTree.Node) => node is TSESTree.CallExpression;
679
752
  };
680
753
  }
754
+ /**
755
+ * Checks if the node is a call expression to a specific React API
756
+ * @param api The React API name to check against
757
+ * @returns A predicate function to check if a node is a call to the API
758
+ */
681
759
  declare function isReactAPICall(api: string): isReactAPICall.ReturnType;
682
760
  declare const isCaptureOwnerStack: isReactAPI.ReturnType;
683
761
  declare const isChildrenCount: isReactAPI.ReturnType;
@@ -706,4 +784,4 @@ declare const isForwardRefCall: isReactAPICall.ReturnType;
706
784
  declare const isMemoCall: isReactAPICall.ReturnType;
707
785
  declare const isLazyCall: isReactAPICall.ReturnType;
708
786
  //#endregion
709
- export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, ComponentStateKind, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, FunctionComponent, Hook, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasNoneOrLooseComponentName, isAssignmentToThisState, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInitializedFromSource, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
787
+ export { ClassComponent, Component, ComponentDetectionHint, ComponentEffectPhaseKind, ComponentFlag, ComponentKind, ComponentLifecyclePhaseKind, ComponentPhaseKind, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, FunctionComponent, Hook, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, SemanticEntry, SemanticNode, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInitializedFromSource, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/dist/index.js CHANGED
@@ -1,75 +1,13 @@
1
- import { AST_NODE_TYPES } from "@typescript-eslint/types";
2
1
  import * as AST from "@eslint-react/ast";
3
2
  import { constFalse, constTrue, dual, flip, getOrElseUpdate, identity, unit } from "@eslint-react/eff";
4
3
  import { IdGenerator, RE_ANNOTATION_JSX, RE_ANNOTATION_JSX_FRAG, RE_ANNOTATION_JSX_IMPORT_SOURCE, RE_ANNOTATION_JSX_RUNTIME, RE_COMPONENT_NAME, RE_COMPONENT_NAME_LOOSE } from "@eslint-react/shared";
4
+ import { AST_NODE_TYPES } from "@typescript-eslint/types";
5
5
  import { findProperty, findVariable, getVariableDefinitionNode, isNodeValueEqual } from "@eslint-react/var";
6
6
  import { getStaticValue } from "@typescript-eslint/utils/ast-utils";
7
7
  import { P, isMatching, match } from "ts-pattern";
8
+ import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from "@typescript-eslint/utils";
8
9
  import birecord from "birecord";
9
10
 
10
- //#region src/utils/is-react-api.ts
11
- function isReactAPI(api) {
12
- const func = (context, node) => {
13
- if (node == null) return false;
14
- const getText = (n) => context.sourceCode.getText(n);
15
- const name = AST.toStringFormat(node, getText);
16
- if (name === api) return true;
17
- if (name.substring(name.indexOf(".") + 1) === api) return true;
18
- return false;
19
- };
20
- return dual(2, func);
21
- }
22
- function isReactAPICall(api) {
23
- const func = (context, node) => {
24
- if (node == null) return false;
25
- if (node.type !== AST_NODE_TYPES.CallExpression) return false;
26
- return isReactAPI(api)(context, node.callee);
27
- };
28
- return dual(2, func);
29
- }
30
- const isCaptureOwnerStack = isReactAPI("captureOwnerStack");
31
- const isChildrenCount = isReactAPI("Children.count");
32
- const isChildrenForEach = isReactAPI("Children.forEach");
33
- const isChildrenMap = isReactAPI("Children.map");
34
- const isChildrenOnly = isReactAPI("Children.only");
35
- const isChildrenToArray = isReactAPI("Children.toArray");
36
- const isCloneElement = isReactAPI("cloneElement");
37
- const isCreateContext = isReactAPI("createContext");
38
- const isCreateElement = isReactAPI("createElement");
39
- const isCreateRef = isReactAPI("createRef");
40
- const isForwardRef = isReactAPI("forwardRef");
41
- const isMemo = isReactAPI("memo");
42
- const isLazy = isReactAPI("lazy");
43
- const isCaptureOwnerStackCall = isReactAPICall("captureOwnerStack");
44
- const isChildrenCountCall = isReactAPICall("Children.count");
45
- const isChildrenForEachCall = isReactAPICall("Children.forEach");
46
- const isChildrenMapCall = isReactAPICall("Children.map");
47
- const isChildrenOnlyCall = isReactAPICall("Children.only");
48
- const isChildrenToArrayCall = isReactAPICall("Children.toArray");
49
- const isCloneElementCall = isReactAPICall("cloneElement");
50
- const isCreateContextCall = isReactAPICall("createContext");
51
- const isCreateElementCall = isReactAPICall("createElement");
52
- const isCreateRefCall = isReactAPICall("createRef");
53
- const isForwardRefCall = isReactAPICall("forwardRef");
54
- const isMemoCall = isReactAPICall("memo");
55
- const isLazyCall = isReactAPICall("lazy");
56
-
57
- //#endregion
58
- //#region src/component/component-children.ts
59
- /**
60
- * Determines whether inside `createElement`'s children.
61
- * @param context The rule context
62
- * @param node The AST node to check
63
- * @returns `true` if the node is inside createElement's children
64
- */
65
- function isChildrenOfCreateElement(context, node) {
66
- const parent = node.parent;
67
- if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
68
- if (!isCreateElementCall(context, parent)) return false;
69
- return parent.arguments.slice(2).some((arg) => arg === node);
70
- }
71
-
72
- //#endregion
73
11
  //#region src/hook/hook-name.ts
74
12
  const REACT_BUILTIN_HOOK_NAMES = [
75
13
  "use",
@@ -276,7 +214,7 @@ function isFunctionOfUseEffectCleanup(node) {
276
214
  /**
277
215
  * Incomplete but sufficient stringification of JSX nodes for common use cases
278
216
  *
279
- * @param node - JSX node from TypeScript ESTree
217
+ * @param node JSX node from TypeScript ESTree
280
218
  * @returns String representation of the JSX node
281
219
  */
282
220
  function stringifyJsx(node) {
@@ -554,8 +492,8 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
554
492
  * For JSX elements, returns the stringified name (e.g., "div", "Button", "React.Fragment")
555
493
  * For JSX fragments, returns an empty string
556
494
  *
557
- * @param context - ESLint rule context
558
- * @param node - JSX element or fragment node
495
+ * @param context ESLint rule context
496
+ * @param node JSX element or fragment node
559
497
  * @returns String representation of the element type
560
498
  */
561
499
  function getJsxElementType(context, node) {
@@ -569,8 +507,8 @@ function getJsxElementType(context, node) {
569
507
  * Determines if a JSX element is a host element
570
508
  * Host elements in React start with lowercase letters (e.g., div, span)
571
509
  *
572
- * @param context - ESLint rule context
573
- * @param node - AST node to check
510
+ * @param context ESLint rule context
511
+ * @param node AST node to check
574
512
  * @returns boolean indicating if the element is a host element
575
513
  */
576
514
  function isJsxHostElement(context, node) {
@@ -580,8 +518,8 @@ function isJsxHostElement(context, node) {
580
518
  * Determines if a JSX element is a React Fragment
581
519
  * Fragments can be imported from React and used like <Fragment> or <React.Fragment>
582
520
  *
583
- * @param context - ESLint rule context
584
- * @param node - AST node to check
521
+ * @param context ESLint rule context
522
+ * @param node AST node to check
585
523
  * @returns boolean indicating if the element is a Fragment with type narrowing
586
524
  */
587
525
  function isJsxFragmentElement(context, node) {
@@ -594,8 +532,8 @@ function isJsxFragmentElement(context, node) {
594
532
  /**
595
533
  * Traverses up the AST to find a parent JSX attribute node that matches a given test
596
534
  *
597
- * @param node - The starting AST node
598
- * @param test - Optional predicate function to test if the attribute meets criteria
535
+ * @param node The starting AST node
536
+ * @param test Optional predicate function to test if the attribute meets criteria
599
537
  * Defaults to always returning true (matches any attribute)
600
538
  * @returns The first matching JSX attribute node found when traversing upwards, or undefined
601
539
  */
@@ -606,6 +544,147 @@ function findParentJsxAttribute(node, test = constTrue) {
606
544
  return AST.findParentNode(node, guard);
607
545
  }
608
546
 
547
+ //#endregion
548
+ //#region src/utils/get-instance-id.ts
549
+ /** eslint-disable jsdoc/require-param */
550
+ /**
551
+ * Gets the identifier node of an instance based on AST node relationships.
552
+ * Used for tracking where hooks or components are being assigned in the code.
553
+ * @param node The current AST node to evaluate
554
+ * @param prev The previous AST node in the traversal (used for context)
555
+ * @internal
556
+ */
557
+ function getInstanceId(node, prev) {
558
+ switch (true) {
559
+ case node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev: return node.id;
560
+ case node.type === AST_NODE_TYPES.AssignmentExpression && node.right === prev: return node.left;
561
+ case node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev: return node.key;
562
+ case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
563
+ default: return getInstanceId(node.parent, node);
564
+ }
565
+ }
566
+
567
+ //#endregion
568
+ //#region src/utils/is-from-source.ts
569
+ /**
570
+ * Get the arguments of a require expression
571
+ * @param node The node to match
572
+ * @returns The require expression arguments or undefined if the node is not a require expression
573
+ */
574
+ function getRequireExpressionArguments(node) {
575
+ return match(node).with({
576
+ type: AST_NODE_TYPES.CallExpression,
577
+ arguments: P.select(),
578
+ callee: {
579
+ type: AST_NODE_TYPES.Identifier,
580
+ name: "require"
581
+ }
582
+ }, identity).with({
583
+ type: AST_NODE_TYPES.MemberExpression,
584
+ object: P.select()
585
+ }, getRequireExpressionArguments).otherwise(() => null);
586
+ }
587
+ /**
588
+ * Check if an identifier name is initialized from source
589
+ * @param name The top-level identifier's name
590
+ * @param source The import source to check against
591
+ * @param initialScope Initial scope to search for the identifier
592
+ * @returns Whether the identifier name is initialized from source
593
+ * @internal
594
+ */
595
+ function isInitializedFromSource(name, source, initialScope) {
596
+ const latestDef = findVariable(name, initialScope)?.defs.at(-1);
597
+ if (latestDef == null) return false;
598
+ const { node, parent } = latestDef;
599
+ if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
600
+ const { init } = node;
601
+ if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) return isInitializedFromSource(init.object.name, source, initialScope);
602
+ if (init.type === AST_NODE_TYPES.Identifier) return isInitializedFromSource(init.name, source, initialScope);
603
+ const arg0 = getRequireExpressionArguments(init)?.[0];
604
+ if (arg0 == null || !AST.isLiteral(arg0, "string")) return false;
605
+ return arg0.value === source || arg0.value.startsWith(`${source}/`);
606
+ }
607
+ return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === source;
608
+ }
609
+
610
+ //#endregion
611
+ //#region src/utils/is-from-react.ts
612
+ /**
613
+ * Check if an identifier name is initialized from react
614
+ * @param name The top-level identifier's name
615
+ * @param importSource The import source to check against
616
+ * @param initialScope Initial scope to search for the identifier
617
+ * @returns Whether the identifier name is initialized from react
618
+ */
619
+ function isInitializedFromReact(name, importSource, initialScope) {
620
+ return name.toLowerCase() === "react" || isInitializedFromSource(name, importSource, initialScope);
621
+ }
622
+
623
+ //#endregion
624
+ //#region src/utils/is-instance-id-equal.ts
625
+ /** @internal */
626
+ function isInstanceIdEqual(context, a, b) {
627
+ return AST.isNodeEqual(a, b) || isNodeValueEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
628
+ }
629
+
630
+ //#endregion
631
+ //#region src/utils/is-react-api.ts
632
+ /**
633
+ * Checks if the node is a React API identifier or member expression
634
+ * @param api The React API name to check against (e.g., "useState", "React.memo")
635
+ * @returns A predicate function to check if a node matches the API
636
+ */
637
+ function isReactAPI(api) {
638
+ const func = (context, node) => {
639
+ if (node == null) return false;
640
+ const getText = (n) => context.sourceCode.getText(n);
641
+ const name = AST.toStringFormat(node, getText);
642
+ if (name === api) return true;
643
+ if (name.substring(name.indexOf(".") + 1) === api) return true;
644
+ return false;
645
+ };
646
+ return dual(2, func);
647
+ }
648
+ /**
649
+ * Checks if the node is a call expression to a specific React API
650
+ * @param api The React API name to check against
651
+ * @returns A predicate function to check if a node is a call to the API
652
+ */
653
+ function isReactAPICall(api) {
654
+ const func = (context, node) => {
655
+ if (node == null) return false;
656
+ if (node.type !== AST_NODE_TYPES.CallExpression) return false;
657
+ return isReactAPI(api)(context, node.callee);
658
+ };
659
+ return dual(2, func);
660
+ }
661
+ const isCaptureOwnerStack = isReactAPI("captureOwnerStack");
662
+ const isChildrenCount = isReactAPI("Children.count");
663
+ const isChildrenForEach = isReactAPI("Children.forEach");
664
+ const isChildrenMap = isReactAPI("Children.map");
665
+ const isChildrenOnly = isReactAPI("Children.only");
666
+ const isChildrenToArray = isReactAPI("Children.toArray");
667
+ const isCloneElement = isReactAPI("cloneElement");
668
+ const isCreateContext = isReactAPI("createContext");
669
+ const isCreateElement = isReactAPI("createElement");
670
+ const isCreateRef = isReactAPI("createRef");
671
+ const isForwardRef = isReactAPI("forwardRef");
672
+ const isMemo = isReactAPI("memo");
673
+ const isLazy = isReactAPI("lazy");
674
+ const isCaptureOwnerStackCall = isReactAPICall("captureOwnerStack");
675
+ const isChildrenCountCall = isReactAPICall("Children.count");
676
+ const isChildrenForEachCall = isReactAPICall("Children.forEach");
677
+ const isChildrenMapCall = isReactAPICall("Children.map");
678
+ const isChildrenOnlyCall = isReactAPICall("Children.only");
679
+ const isChildrenToArrayCall = isReactAPICall("Children.toArray");
680
+ const isCloneElementCall = isReactAPICall("cloneElement");
681
+ const isCreateContextCall = isReactAPICall("createContext");
682
+ const isCreateElementCall = isReactAPICall("createElement");
683
+ const isCreateRefCall = isReactAPICall("createRef");
684
+ const isForwardRefCall = isReactAPICall("forwardRef");
685
+ const isMemoCall = isReactAPICall("memo");
686
+ const isLazyCall = isReactAPICall("lazy");
687
+
609
688
  //#endregion
610
689
  //#region src/component/component-detection-hint.ts
611
690
  /**
@@ -679,18 +758,19 @@ function isRenderMethodLike(node) {
679
758
  //#endregion
680
759
  //#region src/component/component-definition.ts
681
760
  /**
682
- * Function pattern matchers for different contexts
761
+ * Function patterns for matching specific AST structures
762
+ * Used to identify where a function is defined (e.g., method, property)
683
763
  */
684
- const functionPatterns = {
685
- classMethod: {
764
+ const FUNCTION_PATTERNS = {
765
+ CLASS_METHOD: {
686
766
  type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
687
767
  parent: AST_NODE_TYPES.MethodDefinition
688
768
  },
689
- classProperty: {
769
+ CLASS_PROPERTY: {
690
770
  type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
691
771
  parent: AST_NODE_TYPES.Property
692
772
  },
693
- objectMethod: {
773
+ OBJECT_METHOD: {
694
774
  type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
695
775
  parent: {
696
776
  type: AST_NODE_TYPES.Property,
@@ -699,39 +779,65 @@ const functionPatterns = {
699
779
  }
700
780
  };
701
781
  /**
702
- * Check whether given node is a function of a render method of a class component
782
+ * Checks if the given node is a function within a render method of a class component.
783
+ *
784
+ * @param node The AST node to check
785
+ * @param node
786
+ * @returns `true` if the node is a render function inside a class component
787
+ *
703
788
  * @example
704
789
  * ```tsx
705
790
  * class Component extends React.Component {
706
- * renderHeader = () => <div />;
707
- * renderFooter = () => <div />;
791
+ * renderHeader = () => <div />; // Returns true
708
792
  * }
709
793
  * ```
710
- * @param node The AST node to check
711
- * @returns `true` if node is a render function, `false` if not
712
794
  */
713
795
  function isFunctionOfRenderMethod(node) {
714
- return isRenderMethodLike(node.parent) && isClassComponent(node.parent.parent.parent);
796
+ const parent = node.parent;
797
+ const greatGrandparent = parent.parent?.parent;
798
+ return greatGrandparent != null && isRenderMethodLike(parent) && isClassComponent(greatGrandparent);
715
799
  }
716
800
  /**
717
- * Checks if a function node should be excluded based on detection hints
801
+ * Checks if a function node should be excluded based on provided detection hints
802
+ *
718
803
  * @param node The function node to check
719
804
  * @param hint Component detection hints as bit flags
720
- * @returns `true` if the function should be excluded, `false` otherwise
805
+ * @param node
806
+ * @param hint
807
+ * @returns `true` if the function matches an exclusion hint
721
808
  */
722
809
  function shouldExcludeBasedOnHint(node, hint) {
723
- if (hint & ComponentDetectionHint.SkipObjectMethod && isMatching(functionPatterns.objectMethod)(node)) return true;
724
- if (hint & ComponentDetectionHint.SkipClassMethod && isMatching(functionPatterns.classMethod)(node)) return true;
725
- if (hint & ComponentDetectionHint.SkipClassProperty && isMatching(functionPatterns.classProperty)(node)) return true;
810
+ if (hint & ComponentDetectionHint.SkipObjectMethod && isMatching(FUNCTION_PATTERNS.OBJECT_METHOD)(node)) return true;
811
+ if (hint & ComponentDetectionHint.SkipClassMethod && isMatching(FUNCTION_PATTERNS.CLASS_METHOD)(node)) return true;
812
+ if (hint & ComponentDetectionHint.SkipClassProperty && isMatching(FUNCTION_PATTERNS.CLASS_PROPERTY)(node)) return true;
726
813
  if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return true;
727
814
  return false;
728
815
  }
729
816
  /**
817
+ * Determines if the node is an argument within `createElement`'s children list (3rd argument onwards)
818
+ *
819
+ * @param context The rule context
820
+ * @param node The AST node to check
821
+ * @param context
822
+ * @param node
823
+ * @returns `true` if the node is passed as a child to `createElement`
824
+ */
825
+ function isChildrenOfCreateElement(context, node) {
826
+ const parent = node.parent;
827
+ if (parent?.type !== AST_NODE_TYPES.CallExpression) return false;
828
+ if (!isCreateElementCall(context, parent)) return false;
829
+ return parent.arguments.slice(2).some((arg) => arg === node);
830
+ }
831
+ /**
730
832
  * Determines if a function node represents a valid React component definition
833
+ *
731
834
  * @param context The rule context
732
- * @param node The function node to check
733
- * @param hint Component detection hints as bit flags
734
- * @returns `true` if the node is a valid component definition, `false` otherwise
835
+ * @param node The function node to analyze
836
+ * @param hint Component detection hints (bit flags) to customize detection logic
837
+ * @param context
838
+ * @param node
839
+ * @param hint
840
+ * @returns `true` if the node is considered a component definition
735
841
  */
736
842
  function isComponentDefinition(context, node, hint) {
737
843
  if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) return false;
@@ -746,89 +852,6 @@ function isComponentDefinition(context, node, hint) {
746
852
  return significantParent == null || significantParent.type !== AST_NODE_TYPES.JSXExpressionContainer;
747
853
  }
748
854
 
749
- //#endregion
750
- //#region src/utils/get-instance-id.ts
751
- /** eslint-disable jsdoc/require-param */
752
- /**
753
- * Gets the identifier node of an instance based on AST node relationships.
754
- * Used for tracking where hooks or components are being assigned in the code.
755
- * @param node The current AST node to evaluate
756
- * @param prev The previous AST node in the traversal (used for context)
757
- * @internal
758
- */
759
- function getInstanceId(node, prev) {
760
- switch (true) {
761
- case node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev: return node.id;
762
- case node.type === AST_NODE_TYPES.AssignmentExpression && node.right === prev: return node.left;
763
- case node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev: return node.key;
764
- case node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node: return unit;
765
- default: return getInstanceId(node.parent, node);
766
- }
767
- }
768
-
769
- //#endregion
770
- //#region src/utils/is-from-source.ts
771
- /**
772
- * Get the arguments of a require expression
773
- * @param node The node to match
774
- * @returns The require expression arguments or undefined if the node is not a require expression
775
- */
776
- function getRequireExpressionArguments(node) {
777
- return match(node).with({
778
- type: AST_NODE_TYPES.CallExpression,
779
- arguments: P.select(),
780
- callee: {
781
- type: AST_NODE_TYPES.Identifier,
782
- name: "require"
783
- }
784
- }, identity).with({
785
- type: AST_NODE_TYPES.MemberExpression,
786
- object: P.select()
787
- }, getRequireExpressionArguments).otherwise(() => null);
788
- }
789
- /**
790
- * Check if an identifier name is initialized from source
791
- * @param name The top-level identifier's name
792
- * @param source The import source to check against
793
- * @param initialScope Initial scope to search for the identifier
794
- * @returns Whether the identifier name is initialized from source
795
- * @internal
796
- */
797
- function isInitializedFromSource(name, source, initialScope) {
798
- const latestDef = findVariable(name, initialScope)?.defs.at(-1);
799
- if (latestDef == null) return false;
800
- const { node, parent } = latestDef;
801
- if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
802
- const { init } = node;
803
- if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) return isInitializedFromSource(init.object.name, source, initialScope);
804
- if (init.type === AST_NODE_TYPES.Identifier) return isInitializedFromSource(init.name, source, initialScope);
805
- const arg0 = getRequireExpressionArguments(init)?.[0];
806
- if (arg0 == null || !AST.isLiteral(arg0, "string")) return false;
807
- return arg0.value === source || arg0.value.startsWith(`${source}/`);
808
- }
809
- return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === source;
810
- }
811
-
812
- //#endregion
813
- //#region src/utils/is-from-react.ts
814
- /**
815
- * Check if an identifier name is initialized from react
816
- * @param name The top-level identifier's name
817
- * @param importSource The import source to check against
818
- * @param initialScope Initial scope to search for the identifier
819
- * @returns Whether the identifier name is initialized from react
820
- */
821
- function isInitializedFromReact(name, importSource, initialScope) {
822
- return name.toLowerCase() === "react" || isInitializedFromSource(name, importSource, initialScope);
823
- }
824
-
825
- //#endregion
826
- //#region src/utils/is-instance-id-equal.ts
827
- /** @internal */
828
- function isInstanceIdEqual(context, a, b) {
829
- return AST.isNodeEqual(a, b) || isNodeValueEqual(a, b, [context.sourceCode.getScope(a), context.sourceCode.getScope(b)]);
830
- }
831
-
832
855
  //#endregion
833
856
  //#region src/component/component-wrapper.ts
834
857
  /**
@@ -885,16 +908,33 @@ function getComponentFlagFromInitPath(initPath) {
885
908
 
886
909
  //#endregion
887
910
  //#region src/component/component-name.ts
911
+ /**
912
+ * Check if a string matches the strict component name pattern
913
+ * @param name The name to check
914
+ */
888
915
  function isComponentName(name) {
889
916
  return RE_COMPONENT_NAME.test(name);
890
917
  }
918
+ /**
919
+ * Check if a string matches the loose component name pattern
920
+ * @param name The name to check
921
+ */
891
922
  function isComponentNameLoose(name) {
892
923
  return RE_COMPONENT_NAME_LOOSE.test(name);
893
924
  }
925
+ /**
926
+ * Get component name from an identifier or identifier sequence (e.g., MemberExpression)
927
+ * @param id The identifier or identifier sequence
928
+ */
894
929
  function getComponentNameFromId(id) {
895
930
  if (id == null) return unit;
896
931
  return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
897
932
  }
933
+ /**
934
+ * Check if the function has no name or a loose component name
935
+ * @param context The rule context
936
+ * @param fn The function node
937
+ */
898
938
  function hasNoneOrLooseComponentName(context, fn) {
899
939
  const id = getFunctionComponentId(context, fn);
900
940
  if (id == null) return true;
@@ -1040,6 +1080,26 @@ function useComponentCollectorLegacy() {
1040
1080
  }
1041
1081
  };
1042
1082
  }
1083
+ /**
1084
+ * Check whether the given node is a this.setState() call
1085
+ * @param node The node to check
1086
+ * @param node
1087
+ * @internal
1088
+ */
1089
+ function isThisSetState(node) {
1090
+ const { callee } = node;
1091
+ return callee.type === AST_NODE_TYPES$1.MemberExpression && AST.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES$1.Identifier && callee.property.name === "setState";
1092
+ }
1093
+ /**
1094
+ * Check whether the given node is an assignment to this.state
1095
+ * @param node The node to check
1096
+ * @param node
1097
+ * @internal
1098
+ */
1099
+ function isAssignmentToThisState(node) {
1100
+ const { left } = node;
1101
+ return left.type === AST_NODE_TYPES$1.MemberExpression && AST.isThisExpression(left.object) && AST.getPropertyName(left.property) === "state";
1102
+ }
1043
1103
 
1044
1104
  //#endregion
1045
1105
  //#region src/component/component-method.ts
@@ -1165,15 +1225,4 @@ function isDeclaredInRenderPropLoose(node) {
1165
1225
  }
1166
1226
 
1167
1227
  //#endregion
1168
- //#region src/component/component-state.ts
1169
- function isThisSetState(node) {
1170
- const { callee } = node;
1171
- return callee.type === AST_NODE_TYPES.MemberExpression && AST.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
1172
- }
1173
- function isAssignmentToThisState(node) {
1174
- const { left } = node;
1175
- return left.type === AST_NODE_TYPES.MemberExpression && AST.isThisExpression(left.object) && AST.getPropertyName(left.property) === "state";
1176
- }
1177
-
1178
- //#endregion
1179
- export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasNoneOrLooseComponentName, isAssignmentToThisState, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInitializedFromSource, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
1228
+ export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, REACT_BUILTIN_HOOK_NAMES, findParentJsxAttribute, getComponentFlagFromInitPath, getComponentNameFromId, getFunctionComponentId, getInstanceId, getJsxAttribute, getJsxAttributeName, getJsxConfigFromAnnotation, getJsxConfigFromContext, getJsxElementType, getPhaseKindOfFunction, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, 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, isForwardRef, isForwardRefCall, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isInitializedFromReact, isInitializedFromSource, isInstanceIdEqual, isInversePhase, isJsxFragmentElement, isJsxHostElement, isJsxLike, isJsxText, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookId, isReactHookName, isRender, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectLikeCall, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, resolveJsxAttributeValue, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "2.3.13-next.0",
3
+ "version": "2.3.13-next.2",
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,10 +35,10 @@
35
35
  "@typescript-eslint/utils": "^8.48.1",
36
36
  "birecord": "^0.1.1",
37
37
  "ts-pattern": "^5.9.0",
38
- "@eslint-react/ast": "2.3.13-next.0",
39
- "@eslint-react/shared": "2.3.13-next.0",
40
- "@eslint-react/eff": "2.3.13-next.0",
41
- "@eslint-react/var": "2.3.13-next.0"
38
+ "@eslint-react/ast": "2.3.13-next.2",
39
+ "@eslint-react/shared": "2.3.13-next.2",
40
+ "@eslint-react/var": "2.3.13-next.2",
41
+ "@eslint-react/eff": "2.3.13-next.2"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "eslint": "^8.57.0 || ^9.0.0",