@eslint-react/core 2.3.13-beta.1 → 2.3.13-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +37 -100
- package/dist/index.js +181 -210
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
import { TSESTree } from "@typescript-eslint/types";
|
|
1
2
|
import * as AST from "@eslint-react/ast";
|
|
2
3
|
import { unit } from "@eslint-react/eff";
|
|
3
4
|
import { RuleContext } from "@eslint-react/shared";
|
|
4
|
-
import { TSESTree } from "@typescript-eslint/types";
|
|
5
|
-
import { ESLintUtils, TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
|
|
6
5
|
import * as birecord0 from "birecord";
|
|
6
|
+
import { ESLintUtils, TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
|
|
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
|
|
10
19
|
//#region src/component/component-detection-hint.d.ts
|
|
11
20
|
type ComponentDetectionHint = bigint;
|
|
12
21
|
/**
|
|
@@ -84,94 +93,34 @@ interface SemanticNode {
|
|
|
84
93
|
//#region src/component/component-flag.d.ts
|
|
85
94
|
type ComponentFlag = bigint;
|
|
86
95
|
declare const ComponentFlag: {
|
|
87
|
-
/** No flags set */
|
|
88
96
|
None: bigint;
|
|
89
|
-
/** Indicates the component is a pure component (e.g. extends PureComponent) */
|
|
90
97
|
PureComponent: bigint;
|
|
91
|
-
/** Indicates the component creates elements using `createElement` instead of JSX */
|
|
92
98
|
CreateElement: bigint;
|
|
93
|
-
/** Indicates the component is memoized (e.g. React.memo) */
|
|
94
99
|
Memo: bigint;
|
|
95
|
-
/** Indicates the component forwards a ref (e.g. React.forwardRef) */
|
|
96
100
|
ForwardRef: bigint;
|
|
97
|
-
/** Indicates the component is asynchronous */
|
|
98
101
|
Async: bigint;
|
|
99
102
|
};
|
|
100
103
|
//#endregion
|
|
101
104
|
//#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
|
-
*/
|
|
109
106
|
id: unit | TSESTree.Identifier | TSESTree.Identifier[];
|
|
110
|
-
/**
|
|
111
|
-
* The kind of component
|
|
112
|
-
*/
|
|
113
107
|
kind: "function";
|
|
114
|
-
/**
|
|
115
|
-
* The AST node of the function
|
|
116
|
-
*/
|
|
117
108
|
node: AST.TSESTreeFunction;
|
|
118
|
-
/**
|
|
119
|
-
* Flags describing the component's characteristics
|
|
120
|
-
*/
|
|
121
109
|
flag: ComponentFlag;
|
|
122
|
-
/**
|
|
123
|
-
* Hint for how the component was detected
|
|
124
|
-
*/
|
|
125
110
|
hint: ComponentDetectionHint;
|
|
126
|
-
/**
|
|
127
|
-
* The initialization path of the function
|
|
128
|
-
*/
|
|
129
111
|
initPath: unit | AST.FunctionInitPath;
|
|
130
|
-
/**
|
|
131
|
-
* List of hook calls within the component
|
|
132
|
-
*/
|
|
133
112
|
hookCalls: TSESTree.CallExpression[];
|
|
134
|
-
/**
|
|
135
|
-
* The display name of the component
|
|
136
|
-
*/
|
|
137
113
|
displayName: unit | TSESTree.Expression;
|
|
138
114
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Represents a React class component
|
|
141
|
-
*/
|
|
142
115
|
interface ClassComponent extends SemanticNode {
|
|
143
|
-
/**
|
|
144
|
-
* The identifier of the component
|
|
145
|
-
*/
|
|
146
116
|
id: unit | TSESTree.Identifier;
|
|
147
|
-
/**
|
|
148
|
-
* The kind of component
|
|
149
|
-
*/
|
|
150
117
|
kind: "class";
|
|
151
|
-
/**
|
|
152
|
-
* The AST node of the class
|
|
153
|
-
*/
|
|
154
118
|
node: AST.TSESTreeClass;
|
|
155
|
-
/**
|
|
156
|
-
* Flags describing the component's characteristics
|
|
157
|
-
*/
|
|
158
119
|
flag: ComponentFlag;
|
|
159
|
-
/**
|
|
160
|
-
* Hint for how the component was detected
|
|
161
|
-
*/
|
|
162
120
|
hint: ComponentDetectionHint;
|
|
163
|
-
/**
|
|
164
|
-
* List of methods and properties in the class
|
|
165
|
-
*/
|
|
166
121
|
methods: AST.TSESTreeMethodOrProperty[];
|
|
167
|
-
/**
|
|
168
|
-
* The display name of the component
|
|
169
|
-
*/
|
|
170
122
|
displayName: unit | TSESTree.Expression;
|
|
171
123
|
}
|
|
172
|
-
/**
|
|
173
|
-
* Union type representing either a class or function component
|
|
174
|
-
*/
|
|
175
124
|
type Component = ClassComponent | FunctionComponent;
|
|
176
125
|
//#endregion
|
|
177
126
|
//#region src/component/component-collector.d.ts
|
|
@@ -218,27 +167,27 @@ declare namespace useComponentCollectorLegacy {
|
|
|
218
167
|
* @returns The context and listeners for the rule
|
|
219
168
|
*/
|
|
220
169
|
declare function useComponentCollectorLegacy(): useComponentCollectorLegacy.ReturnType;
|
|
221
|
-
/**
|
|
222
|
-
* Check whether the given node is a this.setState() call
|
|
223
|
-
* @param node - The node to check
|
|
224
|
-
* @internal
|
|
225
|
-
*/
|
|
226
|
-
declare function isThisSetState(node: TSESTree$1.CallExpression): boolean;
|
|
227
|
-
/**
|
|
228
|
-
* Check whether the given node is an assignment to this.state
|
|
229
|
-
* @param node - The node to check
|
|
230
|
-
* @internal
|
|
231
|
-
*/
|
|
232
|
-
declare function isAssignmentToThisState(node: TSESTree$1.AssignmentExpression): boolean;
|
|
233
170
|
//#endregion
|
|
234
171
|
//#region src/component/component-definition.d.ts
|
|
172
|
+
/**
|
|
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
|
|
183
|
+
*/
|
|
184
|
+
declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
|
|
235
185
|
/**
|
|
236
186
|
* Determines if a function node represents a valid React component definition
|
|
237
|
-
*
|
|
238
|
-
* @param
|
|
239
|
-
* @param
|
|
240
|
-
* @
|
|
241
|
-
* @returns `true` if the node is considered a component definition
|
|
187
|
+
* @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
|
|
242
191
|
*/
|
|
243
192
|
declare function isComponentDefinition(context: RuleContext, node: AST.TSESTreeFunction, hint: bigint): boolean;
|
|
244
193
|
//#endregion
|
|
@@ -290,26 +239,9 @@ declare function isFunctionOfComponentDidMount(node: TSESTree.Node): boolean;
|
|
|
290
239
|
declare function isFunctionOfComponentWillUnmount(node: TSESTree.Node): boolean;
|
|
291
240
|
//#endregion
|
|
292
241
|
//#region src/component/component-name.d.ts
|
|
293
|
-
/**
|
|
294
|
-
* Check if a string matches the strict component name pattern
|
|
295
|
-
* @param name - The name to check
|
|
296
|
-
*/
|
|
297
242
|
declare function isComponentName(name: string): boolean;
|
|
298
|
-
/**
|
|
299
|
-
* Check if a string matches the loose component name pattern
|
|
300
|
-
* @param name - The name to check
|
|
301
|
-
*/
|
|
302
243
|
declare function isComponentNameLoose(name: string): boolean;
|
|
303
|
-
/**
|
|
304
|
-
* Get component name from an identifier or identifier sequence (e.g., MemberExpression)
|
|
305
|
-
* @param id - The identifier or identifier sequence
|
|
306
|
-
*/
|
|
307
244
|
declare function getComponentNameFromId(id: TSESTree.Identifier | TSESTree.Identifier[] | unit): string | undefined;
|
|
308
|
-
/**
|
|
309
|
-
* Check if the function has no name or a loose component name
|
|
310
|
-
* @param context - The rule context
|
|
311
|
-
* @param fn - The function node
|
|
312
|
-
*/
|
|
313
245
|
declare function hasNoneOrLooseComponentName(context: RuleContext, fn: AST.TSESTreeFunction): boolean;
|
|
314
246
|
//#endregion
|
|
315
247
|
//#region src/component/component-phase-helpers.d.ts
|
|
@@ -385,6 +317,11 @@ declare function isDirectValueOfRenderPropertyLoose(node: TSESTree.Node): boolea
|
|
|
385
317
|
*/
|
|
386
318
|
declare function isDeclaredInRenderPropLoose(node: TSESTree.Node): boolean;
|
|
387
319
|
//#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
|
|
388
325
|
//#region src/component/component-wrapper.d.ts
|
|
389
326
|
/**
|
|
390
327
|
* Check if the node is a call expression for a component wrapper
|
|
@@ -547,7 +484,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
|
|
|
547
484
|
readonly toStatic: () => string | number | bigint | boolean | RegExp | null;
|
|
548
485
|
} | {
|
|
549
486
|
readonly kind: "expression";
|
|
550
|
-
readonly node: TSESTree.
|
|
487
|
+
readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
|
|
551
488
|
readonly toStatic: () => unknown;
|
|
552
489
|
} | {
|
|
553
490
|
readonly kind: "element";
|
|
@@ -555,7 +492,7 @@ declare function resolveJsxAttributeValue(context: RuleContext, attribute: AST.T
|
|
|
555
492
|
readonly toStatic: () => undefined;
|
|
556
493
|
} | {
|
|
557
494
|
readonly kind: "spreadChild";
|
|
558
|
-
readonly node: TSESTree.
|
|
495
|
+
readonly node: TSESTree.Expression | TSESTree.JSXEmptyExpression;
|
|
559
496
|
readonly toStatic: () => undefined;
|
|
560
497
|
} | {
|
|
561
498
|
readonly kind: "spreadProps";
|
|
@@ -700,7 +637,7 @@ declare function stringifyJsx(node: TSESTree$1.JSXIdentifier | TSESTree$1.JSXNam
|
|
|
700
637
|
* @param prev The previous AST node in the traversal (used for context)
|
|
701
638
|
* @internal
|
|
702
639
|
*/
|
|
703
|
-
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.
|
|
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;
|
|
704
641
|
//#endregion
|
|
705
642
|
//#region src/utils/is-from-react.d.ts
|
|
706
643
|
/**
|
|
@@ -769,4 +706,4 @@ declare const isForwardRefCall: isReactAPICall.ReturnType;
|
|
|
769
706
|
declare const isMemoCall: isReactAPICall.ReturnType;
|
|
770
707
|
declare const isLazyCall: isReactAPICall.ReturnType;
|
|
771
708
|
//#endregion
|
|
772
|
-
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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,75 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
1
2
|
import * as AST from "@eslint-react/ast";
|
|
2
3
|
import { constFalse, constTrue, dual, flip, getOrElseUpdate, identity, unit } from "@eslint-react/eff";
|
|
3
4
|
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";
|
|
9
8
|
import birecord from "birecord";
|
|
10
9
|
|
|
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
|
|
11
73
|
//#region src/hook/hook-name.ts
|
|
12
74
|
const REACT_BUILTIN_HOOK_NAMES = [
|
|
13
75
|
"use",
|
|
@@ -544,137 +606,6 @@ function findParentJsxAttribute(node, test = constTrue) {
|
|
|
544
606
|
return AST.findParentNode(node, guard);
|
|
545
607
|
}
|
|
546
608
|
|
|
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
|
-
function isReactAPI(api) {
|
|
633
|
-
const func = (context, node) => {
|
|
634
|
-
if (node == null) return false;
|
|
635
|
-
const getText = (n) => context.sourceCode.getText(n);
|
|
636
|
-
const name = AST.toStringFormat(node, getText);
|
|
637
|
-
if (name === api) return true;
|
|
638
|
-
if (name.substring(name.indexOf(".") + 1) === api) return true;
|
|
639
|
-
return false;
|
|
640
|
-
};
|
|
641
|
-
return dual(2, func);
|
|
642
|
-
}
|
|
643
|
-
function isReactAPICall(api) {
|
|
644
|
-
const func = (context, node) => {
|
|
645
|
-
if (node == null) return false;
|
|
646
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
647
|
-
return isReactAPI(api)(context, node.callee);
|
|
648
|
-
};
|
|
649
|
-
return dual(2, func);
|
|
650
|
-
}
|
|
651
|
-
const isCaptureOwnerStack = isReactAPI("captureOwnerStack");
|
|
652
|
-
const isChildrenCount = isReactAPI("Children.count");
|
|
653
|
-
const isChildrenForEach = isReactAPI("Children.forEach");
|
|
654
|
-
const isChildrenMap = isReactAPI("Children.map");
|
|
655
|
-
const isChildrenOnly = isReactAPI("Children.only");
|
|
656
|
-
const isChildrenToArray = isReactAPI("Children.toArray");
|
|
657
|
-
const isCloneElement = isReactAPI("cloneElement");
|
|
658
|
-
const isCreateContext = isReactAPI("createContext");
|
|
659
|
-
const isCreateElement = isReactAPI("createElement");
|
|
660
|
-
const isCreateRef = isReactAPI("createRef");
|
|
661
|
-
const isForwardRef = isReactAPI("forwardRef");
|
|
662
|
-
const isMemo = isReactAPI("memo");
|
|
663
|
-
const isLazy = isReactAPI("lazy");
|
|
664
|
-
const isCaptureOwnerStackCall = isReactAPICall("captureOwnerStack");
|
|
665
|
-
const isChildrenCountCall = isReactAPICall("Children.count");
|
|
666
|
-
const isChildrenForEachCall = isReactAPICall("Children.forEach");
|
|
667
|
-
const isChildrenMapCall = isReactAPICall("Children.map");
|
|
668
|
-
const isChildrenOnlyCall = isReactAPICall("Children.only");
|
|
669
|
-
const isChildrenToArrayCall = isReactAPICall("Children.toArray");
|
|
670
|
-
const isCloneElementCall = isReactAPICall("cloneElement");
|
|
671
|
-
const isCreateContextCall = isReactAPICall("createContext");
|
|
672
|
-
const isCreateElementCall = isReactAPICall("createElement");
|
|
673
|
-
const isCreateRefCall = isReactAPICall("createRef");
|
|
674
|
-
const isForwardRefCall = isReactAPICall("forwardRef");
|
|
675
|
-
const isMemoCall = isReactAPICall("memo");
|
|
676
|
-
const isLazyCall = isReactAPICall("lazy");
|
|
677
|
-
|
|
678
609
|
//#endregion
|
|
679
610
|
//#region src/component/component-detection-hint.ts
|
|
680
611
|
/**
|
|
@@ -748,19 +679,18 @@ function isRenderMethodLike(node) {
|
|
|
748
679
|
//#endregion
|
|
749
680
|
//#region src/component/component-definition.ts
|
|
750
681
|
/**
|
|
751
|
-
* Function
|
|
752
|
-
* Used to identify where a function is defined (e.g., method, property)
|
|
682
|
+
* Function pattern matchers for different contexts
|
|
753
683
|
*/
|
|
754
|
-
const
|
|
755
|
-
|
|
684
|
+
const functionPatterns = {
|
|
685
|
+
classMethod: {
|
|
756
686
|
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
757
687
|
parent: AST_NODE_TYPES.MethodDefinition
|
|
758
688
|
},
|
|
759
|
-
|
|
689
|
+
classProperty: {
|
|
760
690
|
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
761
691
|
parent: AST_NODE_TYPES.Property
|
|
762
692
|
},
|
|
763
|
-
|
|
693
|
+
objectMethod: {
|
|
764
694
|
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
765
695
|
parent: {
|
|
766
696
|
type: AST_NODE_TYPES.Property,
|
|
@@ -769,57 +699,39 @@ const FUNCTION_PATTERNS = {
|
|
|
769
699
|
}
|
|
770
700
|
};
|
|
771
701
|
/**
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
* @param node - The AST node to check
|
|
775
|
-
* @returns `true` if the node is a render function inside a class component
|
|
776
|
-
*
|
|
702
|
+
* Check whether given node is a function of a render method of a class component
|
|
777
703
|
* @example
|
|
778
704
|
* ```tsx
|
|
779
705
|
* class Component extends React.Component {
|
|
780
|
-
* renderHeader = () => <div />;
|
|
706
|
+
* renderHeader = () => <div />;
|
|
707
|
+
* renderFooter = () => <div />;
|
|
781
708
|
* }
|
|
782
709
|
* ```
|
|
710
|
+
* @param node The AST node to check
|
|
711
|
+
* @returns `true` if node is a render function, `false` if not
|
|
783
712
|
*/
|
|
784
713
|
function isFunctionOfRenderMethod(node) {
|
|
785
|
-
|
|
786
|
-
const greatGrandparent = parent.parent?.parent;
|
|
787
|
-
return greatGrandparent != null && isRenderMethodLike(parent) && isClassComponent(greatGrandparent);
|
|
714
|
+
return isRenderMethodLike(node.parent) && isClassComponent(node.parent.parent.parent);
|
|
788
715
|
}
|
|
789
716
|
/**
|
|
790
|
-
* Checks if a function node should be excluded based on
|
|
791
|
-
*
|
|
792
|
-
* @param
|
|
793
|
-
* @
|
|
794
|
-
* @returns `true` if the function matches an exclusion hint
|
|
717
|
+
* Checks if a function node should be excluded based on detection hints
|
|
718
|
+
* @param node The function node to check
|
|
719
|
+
* @param hint Component detection hints as bit flags
|
|
720
|
+
* @returns `true` if the function should be excluded, `false` otherwise
|
|
795
721
|
*/
|
|
796
722
|
function shouldExcludeBasedOnHint(node, hint) {
|
|
797
|
-
if (hint & ComponentDetectionHint.SkipObjectMethod && isMatching(
|
|
798
|
-
if (hint & ComponentDetectionHint.SkipClassMethod && isMatching(
|
|
799
|
-
if (hint & ComponentDetectionHint.SkipClassProperty && isMatching(
|
|
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;
|
|
800
726
|
if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST.isArrayMapCall(node.parent)) return true;
|
|
801
727
|
return false;
|
|
802
728
|
}
|
|
803
729
|
/**
|
|
804
|
-
* Determines if the node is an argument within `createElement`'s children list (3rd argument onwards)
|
|
805
|
-
*
|
|
806
|
-
* @param context - The rule context
|
|
807
|
-
* @param node - The AST node to check
|
|
808
|
-
* @returns `true` if the node is passed as a child to `createElement`
|
|
809
|
-
*/
|
|
810
|
-
function isChildrenOfCreateElement(context, node) {
|
|
811
|
-
const parent = node.parent;
|
|
812
|
-
if (parent?.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
813
|
-
if (!isCreateElementCall(context, parent)) return false;
|
|
814
|
-
return parent.arguments.slice(2).some((arg) => arg === node);
|
|
815
|
-
}
|
|
816
|
-
/**
|
|
817
730
|
* Determines if a function node represents a valid React component definition
|
|
818
|
-
*
|
|
819
|
-
* @param
|
|
820
|
-
* @param
|
|
821
|
-
* @
|
|
822
|
-
* @returns `true` if the node is considered a component definition
|
|
731
|
+
* @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
|
|
823
735
|
*/
|
|
824
736
|
function isComponentDefinition(context, node, hint) {
|
|
825
737
|
if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) return false;
|
|
@@ -834,6 +746,89 @@ function isComponentDefinition(context, node, hint) {
|
|
|
834
746
|
return significantParent == null || significantParent.type !== AST_NODE_TYPES.JSXExpressionContainer;
|
|
835
747
|
}
|
|
836
748
|
|
|
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
|
+
|
|
837
832
|
//#endregion
|
|
838
833
|
//#region src/component/component-wrapper.ts
|
|
839
834
|
/**
|
|
@@ -890,33 +885,16 @@ function getComponentFlagFromInitPath(initPath) {
|
|
|
890
885
|
|
|
891
886
|
//#endregion
|
|
892
887
|
//#region src/component/component-name.ts
|
|
893
|
-
/**
|
|
894
|
-
* Check if a string matches the strict component name pattern
|
|
895
|
-
* @param name - The name to check
|
|
896
|
-
*/
|
|
897
888
|
function isComponentName(name) {
|
|
898
889
|
return RE_COMPONENT_NAME.test(name);
|
|
899
890
|
}
|
|
900
|
-
/**
|
|
901
|
-
* Check if a string matches the loose component name pattern
|
|
902
|
-
* @param name - The name to check
|
|
903
|
-
*/
|
|
904
891
|
function isComponentNameLoose(name) {
|
|
905
892
|
return RE_COMPONENT_NAME_LOOSE.test(name);
|
|
906
893
|
}
|
|
907
|
-
/**
|
|
908
|
-
* Get component name from an identifier or identifier sequence (e.g., MemberExpression)
|
|
909
|
-
* @param id - The identifier or identifier sequence
|
|
910
|
-
*/
|
|
911
894
|
function getComponentNameFromId(id) {
|
|
912
895
|
if (id == null) return unit;
|
|
913
896
|
return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
|
|
914
897
|
}
|
|
915
|
-
/**
|
|
916
|
-
* Check if the function has no name or a loose component name
|
|
917
|
-
* @param context - The rule context
|
|
918
|
-
* @param fn - The function node
|
|
919
|
-
*/
|
|
920
898
|
function hasNoneOrLooseComponentName(context, fn) {
|
|
921
899
|
const id = getFunctionComponentId(context, fn);
|
|
922
900
|
if (id == null) return true;
|
|
@@ -1062,24 +1040,6 @@ function useComponentCollectorLegacy() {
|
|
|
1062
1040
|
}
|
|
1063
1041
|
};
|
|
1064
1042
|
}
|
|
1065
|
-
/**
|
|
1066
|
-
* Check whether the given node is a this.setState() call
|
|
1067
|
-
* @param node - The node to check
|
|
1068
|
-
* @internal
|
|
1069
|
-
*/
|
|
1070
|
-
function isThisSetState(node) {
|
|
1071
|
-
const { callee } = node;
|
|
1072
|
-
return callee.type === AST_NODE_TYPES$1.MemberExpression && AST.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES$1.Identifier && callee.property.name === "setState";
|
|
1073
|
-
}
|
|
1074
|
-
/**
|
|
1075
|
-
* Check whether the given node is an assignment to this.state
|
|
1076
|
-
* @param node - The node to check
|
|
1077
|
-
* @internal
|
|
1078
|
-
*/
|
|
1079
|
-
function isAssignmentToThisState(node) {
|
|
1080
|
-
const { left } = node;
|
|
1081
|
-
return left.type === AST_NODE_TYPES$1.MemberExpression && AST.isThisExpression(left.object) && AST.getPropertyName(left.property) === "state";
|
|
1082
|
-
}
|
|
1083
1043
|
|
|
1084
1044
|
//#endregion
|
|
1085
1045
|
//#region src/component/component-method.ts
|
|
@@ -1205,4 +1165,15 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
1205
1165
|
}
|
|
1206
1166
|
|
|
1207
1167
|
//#endregion
|
|
1208
|
-
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "2.3.13-
|
|
3
|
+
"version": "2.3.13-next.0",
|
|
4
4
|
"description": "ESLint React's ESLint utility module for static analysis of React core APIs and patterns.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -35,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-
|
|
39
|
-
"@eslint-react/
|
|
40
|
-
"@eslint-react/
|
|
41
|
-
"@eslint-react/
|
|
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"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"eslint": "^8.57.0 || ^9.0.0",
|