@eslint-react/core 1.24.0-next.12 → 1.24.0-next.14
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.mts +13 -10
- package/dist/index.d.ts +13 -10
- package/dist/index.js +37 -29
- package/dist/index.mjs +32 -25
- package/package.json +6 -6
package/dist/index.d.mts
CHANGED
|
@@ -108,9 +108,6 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
|
|
|
108
108
|
readonly listeners: {
|
|
109
109
|
readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
|
|
110
110
|
readonly "CallExpression[type]:exit"?: (node: TSESTree.CallExpression) => void;
|
|
111
|
-
readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"?: (node: TSESTree.AssignmentExpression & {
|
|
112
|
-
left: TSESTree.MemberExpression;
|
|
113
|
-
}) => void;
|
|
114
111
|
readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
|
|
115
112
|
readonly ":function[type]:exit": () => {
|
|
116
113
|
key: string;
|
|
@@ -136,6 +133,17 @@ declare function useComponentCollectorLegacy(): {
|
|
|
136
133
|
};
|
|
137
134
|
};
|
|
138
135
|
|
|
136
|
+
/**
|
|
137
|
+
* The ESQuery selector for a component display name assignment expression
|
|
138
|
+
*/
|
|
139
|
+
declare const COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR: string;
|
|
140
|
+
/**
|
|
141
|
+
* Check if the node is a component display name assignment expression
|
|
142
|
+
* @param node The AST node
|
|
143
|
+
* @returns `true` if the node is a component display name assignment
|
|
144
|
+
*/
|
|
145
|
+
declare function isComponentDisplayNameAssignment(node: TSESTree.Node | _): node is TSESTree.AssignmentExpression;
|
|
146
|
+
|
|
139
147
|
declare function getFunctionComponentIdentifier(node: AST.TSESTreeFunction, context: RuleContext): TSESTree.Identifier | TSESTree.Identifier[] | _;
|
|
140
148
|
|
|
141
149
|
type ERComponentKind = "classComponent" | "functionComponent";
|
|
@@ -166,9 +174,6 @@ declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
|
|
|
166
174
|
*/
|
|
167
175
|
declare function isInsideRenderMethod(node: TSESTree.Node): boolean;
|
|
168
176
|
|
|
169
|
-
type EREffectMethodKind = "useEffect" | "useInsertionEffect" | "useLayoutEffect";
|
|
170
|
-
type ERLifecycleMethodKind = "componentDidMount" | "componentWillUnmount";
|
|
171
|
-
|
|
172
177
|
declare const RE_COMPONENT_NAME: RegExp;
|
|
173
178
|
declare function getComponentNameFromIdentifier(node: TSESTree.Identifier | TSESTree.Identifier[] | _): string | undefined;
|
|
174
179
|
declare function isComponentName(name: string): boolean;
|
|
@@ -252,7 +257,7 @@ declare function isClassComponent(node: TSESTree.Node): node is AST.TSESTreeClas
|
|
|
252
257
|
*/
|
|
253
258
|
declare function isPureComponent(node: TSESTree.Node): boolean;
|
|
254
259
|
|
|
255
|
-
type EREffectKind = "
|
|
260
|
+
type EREffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
|
|
256
261
|
|
|
257
262
|
declare function isFunctionOfUseEffectSetup(node: TSESTree.Node | _): boolean | undefined;
|
|
258
263
|
declare function isFunctionOfUseEffectCleanup(node: TSESTree.Node): boolean | undefined;
|
|
@@ -330,8 +335,6 @@ interface ERSemanticEntry {
|
|
|
330
335
|
phase: ERPhaseKind;
|
|
331
336
|
}
|
|
332
337
|
|
|
333
|
-
declare const getId: () => string;
|
|
334
|
-
|
|
335
338
|
/**
|
|
336
339
|
* Checks if the given node is a call expression to the given function or method of the pragma
|
|
337
340
|
* @param name The name of the function or method to check
|
|
@@ -2584,4 +2587,4 @@ declare const isMemoCall: {
|
|
|
2584
2587
|
(node: Node, context: _eslint_react_shared.RuleContext): node is CallExpression;
|
|
2585
2588
|
};
|
|
2586
2589
|
|
|
2587
|
-
export { type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type
|
|
2590
|
+
export { COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR, type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type EREffectPhaseKind, type ERFunctionComponent, ERFunctionComponentFlag, type ERHook, type ERHookKind, type ERLifecyclePhaseKind, type ERPhaseKind, ERPhaseRelevance, type ERSemanticEntry, type ERSemanticNode, type ERStateKind, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDisplayNameAssignment, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/dist/index.d.ts
CHANGED
|
@@ -108,9 +108,6 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
|
|
|
108
108
|
readonly listeners: {
|
|
109
109
|
readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
|
|
110
110
|
readonly "CallExpression[type]:exit"?: (node: TSESTree.CallExpression) => void;
|
|
111
|
-
readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"?: (node: TSESTree.AssignmentExpression & {
|
|
112
|
-
left: TSESTree.MemberExpression;
|
|
113
|
-
}) => void;
|
|
114
111
|
readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
|
|
115
112
|
readonly ":function[type]:exit": () => {
|
|
116
113
|
key: string;
|
|
@@ -136,6 +133,17 @@ declare function useComponentCollectorLegacy(): {
|
|
|
136
133
|
};
|
|
137
134
|
};
|
|
138
135
|
|
|
136
|
+
/**
|
|
137
|
+
* The ESQuery selector for a component display name assignment expression
|
|
138
|
+
*/
|
|
139
|
+
declare const COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR: string;
|
|
140
|
+
/**
|
|
141
|
+
* Check if the node is a component display name assignment expression
|
|
142
|
+
* @param node The AST node
|
|
143
|
+
* @returns `true` if the node is a component display name assignment
|
|
144
|
+
*/
|
|
145
|
+
declare function isComponentDisplayNameAssignment(node: TSESTree.Node | _): node is TSESTree.AssignmentExpression;
|
|
146
|
+
|
|
139
147
|
declare function getFunctionComponentIdentifier(node: AST.TSESTreeFunction, context: RuleContext): TSESTree.Identifier | TSESTree.Identifier[] | _;
|
|
140
148
|
|
|
141
149
|
type ERComponentKind = "classComponent" | "functionComponent";
|
|
@@ -166,9 +174,6 @@ declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
|
|
|
166
174
|
*/
|
|
167
175
|
declare function isInsideRenderMethod(node: TSESTree.Node): boolean;
|
|
168
176
|
|
|
169
|
-
type EREffectMethodKind = "useEffect" | "useInsertionEffect" | "useLayoutEffect";
|
|
170
|
-
type ERLifecycleMethodKind = "componentDidMount" | "componentWillUnmount";
|
|
171
|
-
|
|
172
177
|
declare const RE_COMPONENT_NAME: RegExp;
|
|
173
178
|
declare function getComponentNameFromIdentifier(node: TSESTree.Identifier | TSESTree.Identifier[] | _): string | undefined;
|
|
174
179
|
declare function isComponentName(name: string): boolean;
|
|
@@ -252,7 +257,7 @@ declare function isClassComponent(node: TSESTree.Node): node is AST.TSESTreeClas
|
|
|
252
257
|
*/
|
|
253
258
|
declare function isPureComponent(node: TSESTree.Node): boolean;
|
|
254
259
|
|
|
255
|
-
type EREffectKind = "
|
|
260
|
+
type EREffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
|
|
256
261
|
|
|
257
262
|
declare function isFunctionOfUseEffectSetup(node: TSESTree.Node | _): boolean | undefined;
|
|
258
263
|
declare function isFunctionOfUseEffectCleanup(node: TSESTree.Node): boolean | undefined;
|
|
@@ -330,8 +335,6 @@ interface ERSemanticEntry {
|
|
|
330
335
|
phase: ERPhaseKind;
|
|
331
336
|
}
|
|
332
337
|
|
|
333
|
-
declare const getId: () => string;
|
|
334
|
-
|
|
335
338
|
/**
|
|
336
339
|
* Checks if the given node is a call expression to the given function or method of the pragma
|
|
337
340
|
* @param name The name of the function or method to check
|
|
@@ -2584,4 +2587,4 @@ declare const isMemoCall: {
|
|
|
2584
2587
|
(node: Node, context: _eslint_react_shared.RuleContext): node is CallExpression;
|
|
2585
2588
|
};
|
|
2586
2589
|
|
|
2587
|
-
export { type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type
|
|
2590
|
+
export { COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR, type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type EREffectPhaseKind, type ERFunctionComponent, ERFunctionComponentFlag, type ERHook, type ERHookKind, type ERLifecyclePhaseKind, type ERPhaseKind, ERPhaseRelevance, type ERSemanticEntry, type ERSemanticNode, type ERStateKind, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDisplayNameAssignment, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var AST8 = require('@eslint-react/ast');
|
|
4
4
|
var eff = require('@eslint-react/eff');
|
|
5
5
|
var JSX3 = require('@eslint-react/jsx');
|
|
6
|
-
var types = require('@typescript-eslint/types');
|
|
7
6
|
var shared = require('@eslint-react/shared');
|
|
7
|
+
var types = require('@typescript-eslint/types');
|
|
8
8
|
var VAR = require('@eslint-react/var');
|
|
9
9
|
var birecord = require('birecord');
|
|
10
10
|
|
|
@@ -34,10 +34,6 @@ var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
|
|
|
34
34
|
var birecord__default = /*#__PURE__*/_interopDefault(birecord);
|
|
35
35
|
|
|
36
36
|
// src/component/component-collector.ts
|
|
37
|
-
|
|
38
|
-
// src/utils/get-id.ts
|
|
39
|
-
var id = 0n;
|
|
40
|
-
var getId = () => (id++).toString();
|
|
41
37
|
function isInitializedFromReact(name, initialScope, importSource = "react") {
|
|
42
38
|
return name.toLowerCase() === "react" || VAR__namespace.isInitializedFromSource(
|
|
43
39
|
name,
|
|
@@ -171,8 +167,8 @@ function isReactHookName(name) {
|
|
|
171
167
|
// src/hook/is.ts
|
|
172
168
|
function isReactHook(node) {
|
|
173
169
|
if (node == null) return eff._;
|
|
174
|
-
const
|
|
175
|
-
return
|
|
170
|
+
const id = AST8__namespace.getFunctionIdentifier(node);
|
|
171
|
+
return id?.name != null && isReactHookName(id.name);
|
|
176
172
|
}
|
|
177
173
|
function isReactHookCall(node) {
|
|
178
174
|
if (node == null) return false;
|
|
@@ -267,13 +263,13 @@ function useHookCollector() {
|
|
|
267
263
|
const hooks = /* @__PURE__ */ new Map();
|
|
268
264
|
const fEntries = [];
|
|
269
265
|
const onFunctionEnter = (node) => {
|
|
270
|
-
const
|
|
271
|
-
const name =
|
|
266
|
+
const id = AST8__namespace.getFunctionIdentifier(node);
|
|
267
|
+
const name = id?.name;
|
|
272
268
|
if (name != null && isReactHookName(name)) {
|
|
273
|
-
const key = getId();
|
|
269
|
+
const key = shared.getId();
|
|
274
270
|
fEntries.push({ key, node });
|
|
275
271
|
hooks.set(key, {
|
|
276
|
-
id
|
|
272
|
+
id,
|
|
277
273
|
key,
|
|
278
274
|
kind: "function",
|
|
279
275
|
name,
|
|
@@ -335,6 +331,17 @@ var ERComponentHint = {
|
|
|
335
331
|
SkipClassProperty: 1n << 69n
|
|
336
332
|
};
|
|
337
333
|
var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
|
|
334
|
+
var COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
|
|
335
|
+
"AssignmentExpression",
|
|
336
|
+
"[type]",
|
|
337
|
+
"[operator='=']",
|
|
338
|
+
"[left.type='MemberExpression']",
|
|
339
|
+
"[left.property.name='displayName']"
|
|
340
|
+
].join("");
|
|
341
|
+
function isComponentDisplayNameAssignment(node) {
|
|
342
|
+
if (node == null) return false;
|
|
343
|
+
return node.type === types.AST_NODE_TYPES.AssignmentExpression && node.operator === "=" && node.left.type === types.AST_NODE_TYPES.MemberExpression && node.left.property.type === types.AST_NODE_TYPES.Identifier && node.left.property.name === "displayName";
|
|
344
|
+
}
|
|
338
345
|
|
|
339
346
|
// src/component/component-flag.ts
|
|
340
347
|
var ERClassComponentFlag = {
|
|
@@ -442,9 +449,9 @@ function isComponentName(name) {
|
|
|
442
449
|
return RE_COMPONENT_NAME.test(name);
|
|
443
450
|
}
|
|
444
451
|
function hasNoneOrValidComponentName(node, context) {
|
|
445
|
-
const
|
|
446
|
-
if (
|
|
447
|
-
const name = Array.isArray(
|
|
452
|
+
const id = getFunctionComponentIdentifier(node, context);
|
|
453
|
+
if (id == null) return true;
|
|
454
|
+
const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
|
|
448
455
|
return name != null && isComponentName(name);
|
|
449
456
|
}
|
|
450
457
|
|
|
@@ -487,7 +494,6 @@ function getComponentFlag(initPath) {
|
|
|
487
494
|
}
|
|
488
495
|
return flag;
|
|
489
496
|
}
|
|
490
|
-
var displayNameAssignmentSelector = "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']";
|
|
491
497
|
function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
|
|
492
498
|
const { collectDisplayName = false, collectHookCalls = false } = options;
|
|
493
499
|
const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
|
|
@@ -495,7 +501,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
495
501
|
const functionEntries = [];
|
|
496
502
|
const getCurrentEntry = () => functionEntries.at(-1);
|
|
497
503
|
const onFunctionEnter = (node) => {
|
|
498
|
-
const key = getId();
|
|
504
|
+
const key = shared.getId();
|
|
499
505
|
functionEntries.push({ key, node, hookCalls: [], isComponent: false });
|
|
500
506
|
};
|
|
501
507
|
const onFunctionExit = () => {
|
|
@@ -536,11 +542,11 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
536
542
|
return;
|
|
537
543
|
}
|
|
538
544
|
const initPath = AST8__namespace.getFunctionInitPath(entry.node);
|
|
539
|
-
const
|
|
540
|
-
const name = getComponentNameFromIdentifier(
|
|
541
|
-
const key = getId();
|
|
545
|
+
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
546
|
+
const name = getComponentNameFromIdentifier(id);
|
|
547
|
+
const key = shared.getId();
|
|
542
548
|
components.set(key, {
|
|
543
|
-
id
|
|
549
|
+
id,
|
|
544
550
|
key,
|
|
545
551
|
kind: "function",
|
|
546
552
|
name,
|
|
@@ -553,8 +559,9 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
553
559
|
});
|
|
554
560
|
},
|
|
555
561
|
...collectDisplayName ? {
|
|
556
|
-
[
|
|
562
|
+
[COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR](node) {
|
|
557
563
|
const { left, right } = node;
|
|
564
|
+
if (left.type !== types.AST_NODE_TYPES.MemberExpression) return;
|
|
558
565
|
const componentName = left.object.type === types.AST_NODE_TYPES.Identifier ? left.object.name : eff._;
|
|
559
566
|
const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
|
|
560
567
|
if (component == null) {
|
|
@@ -587,10 +594,10 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
587
594
|
functionEntries.pop();
|
|
588
595
|
functionEntries.push({ ...entry, isComponent });
|
|
589
596
|
const initPath = AST8__namespace.getFunctionInitPath(entry.node);
|
|
590
|
-
const
|
|
591
|
-
const name = getComponentNameFromIdentifier(
|
|
597
|
+
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
598
|
+
const name = getComponentNameFromIdentifier(id);
|
|
592
599
|
components.set(entry.key, {
|
|
593
|
-
id
|
|
600
|
+
id,
|
|
594
601
|
key: entry.key,
|
|
595
602
|
kind: "function",
|
|
596
603
|
name,
|
|
@@ -617,16 +624,16 @@ function useComponentCollectorLegacy() {
|
|
|
617
624
|
if (!isClassComponent(node)) {
|
|
618
625
|
return;
|
|
619
626
|
}
|
|
620
|
-
const
|
|
621
|
-
const key = getId();
|
|
627
|
+
const id = AST8__namespace.getClassIdentifier(node);
|
|
628
|
+
const key = shared.getId();
|
|
622
629
|
const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
|
|
623
630
|
components.set(
|
|
624
631
|
key,
|
|
625
632
|
{
|
|
626
|
-
id
|
|
633
|
+
id,
|
|
627
634
|
key,
|
|
628
635
|
kind: "class",
|
|
629
|
-
name:
|
|
636
|
+
name: id?.name,
|
|
630
637
|
node,
|
|
631
638
|
// TODO: Get displayName of class component
|
|
632
639
|
displayName: eff._,
|
|
@@ -698,6 +705,7 @@ function isFunctionOfUseEffectCleanup(node) {
|
|
|
698
705
|
return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
|
|
699
706
|
}
|
|
700
707
|
|
|
708
|
+
exports.COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR;
|
|
701
709
|
exports.DEFAULT_COMPONENT_HINT = DEFAULT_COMPONENT_HINT;
|
|
702
710
|
exports.ERClassComponentFlag = ERClassComponentFlag;
|
|
703
711
|
exports.ERComponentHint = ERComponentHint;
|
|
@@ -707,7 +715,6 @@ exports.RE_COMPONENT_NAME = RE_COMPONENT_NAME;
|
|
|
707
715
|
exports.RE_HOOK_NAME = RE_HOOK_NAME;
|
|
708
716
|
exports.getComponentNameFromIdentifier = getComponentNameFromIdentifier;
|
|
709
717
|
exports.getFunctionComponentIdentifier = getFunctionComponentIdentifier;
|
|
710
|
-
exports.getId = getId;
|
|
711
718
|
exports.hasNoneOrValidComponentName = hasNoneOrValidComponentName;
|
|
712
719
|
exports.isCallFromReact = isCallFromReact;
|
|
713
720
|
exports.isCallFromReactMember = isCallFromReactMember;
|
|
@@ -727,6 +734,7 @@ exports.isCloneElement = isCloneElement;
|
|
|
727
734
|
exports.isCloneElementCall = isCloneElementCall;
|
|
728
735
|
exports.isComponentDidCatch = isComponentDidCatch;
|
|
729
736
|
exports.isComponentDidMount = isComponentDidMount;
|
|
737
|
+
exports.isComponentDisplayNameAssignment = isComponentDisplayNameAssignment;
|
|
730
738
|
exports.isComponentName = isComponentName;
|
|
731
739
|
exports.isComponentWillUnmount = isComponentWillUnmount;
|
|
732
740
|
exports.isCreateContext = isCreateContext;
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import * as AST8 from '@eslint-react/ast';
|
|
2
2
|
import { flip, dual, _, returnFalse } from '@eslint-react/eff';
|
|
3
3
|
import * as JSX3 from '@eslint-react/jsx';
|
|
4
|
+
import { unsafeDecodeSettings, getId } from '@eslint-react/shared';
|
|
4
5
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
5
|
-
import { unsafeDecodeSettings } from '@eslint-react/shared';
|
|
6
6
|
import * as VAR from '@eslint-react/var';
|
|
7
7
|
import birecord from 'birecord';
|
|
8
8
|
|
|
9
9
|
// src/component/component-collector.ts
|
|
10
|
-
|
|
11
|
-
// src/utils/get-id.ts
|
|
12
|
-
var id = 0n;
|
|
13
|
-
var getId = () => (id++).toString();
|
|
14
10
|
function isInitializedFromReact(name, initialScope, importSource = "react") {
|
|
15
11
|
return name.toLowerCase() === "react" || VAR.isInitializedFromSource(
|
|
16
12
|
name,
|
|
@@ -144,8 +140,8 @@ function isReactHookName(name) {
|
|
|
144
140
|
// src/hook/is.ts
|
|
145
141
|
function isReactHook(node) {
|
|
146
142
|
if (node == null) return _;
|
|
147
|
-
const
|
|
148
|
-
return
|
|
143
|
+
const id = AST8.getFunctionIdentifier(node);
|
|
144
|
+
return id?.name != null && isReactHookName(id.name);
|
|
149
145
|
}
|
|
150
146
|
function isReactHookCall(node) {
|
|
151
147
|
if (node == null) return false;
|
|
@@ -240,13 +236,13 @@ function useHookCollector() {
|
|
|
240
236
|
const hooks = /* @__PURE__ */ new Map();
|
|
241
237
|
const fEntries = [];
|
|
242
238
|
const onFunctionEnter = (node) => {
|
|
243
|
-
const
|
|
244
|
-
const name =
|
|
239
|
+
const id = AST8.getFunctionIdentifier(node);
|
|
240
|
+
const name = id?.name;
|
|
245
241
|
if (name != null && isReactHookName(name)) {
|
|
246
242
|
const key = getId();
|
|
247
243
|
fEntries.push({ key, node });
|
|
248
244
|
hooks.set(key, {
|
|
249
|
-
id
|
|
245
|
+
id,
|
|
250
246
|
key,
|
|
251
247
|
kind: "function",
|
|
252
248
|
name,
|
|
@@ -308,6 +304,17 @@ var ERComponentHint = {
|
|
|
308
304
|
SkipClassProperty: 1n << 69n
|
|
309
305
|
};
|
|
310
306
|
var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
|
|
307
|
+
var COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
|
|
308
|
+
"AssignmentExpression",
|
|
309
|
+
"[type]",
|
|
310
|
+
"[operator='=']",
|
|
311
|
+
"[left.type='MemberExpression']",
|
|
312
|
+
"[left.property.name='displayName']"
|
|
313
|
+
].join("");
|
|
314
|
+
function isComponentDisplayNameAssignment(node) {
|
|
315
|
+
if (node == null) return false;
|
|
316
|
+
return node.type === AST_NODE_TYPES.AssignmentExpression && node.operator === "=" && node.left.type === AST_NODE_TYPES.MemberExpression && node.left.property.type === AST_NODE_TYPES.Identifier && node.left.property.name === "displayName";
|
|
317
|
+
}
|
|
311
318
|
|
|
312
319
|
// src/component/component-flag.ts
|
|
313
320
|
var ERClassComponentFlag = {
|
|
@@ -415,9 +422,9 @@ function isComponentName(name) {
|
|
|
415
422
|
return RE_COMPONENT_NAME.test(name);
|
|
416
423
|
}
|
|
417
424
|
function hasNoneOrValidComponentName(node, context) {
|
|
418
|
-
const
|
|
419
|
-
if (
|
|
420
|
-
const name = Array.isArray(
|
|
425
|
+
const id = getFunctionComponentIdentifier(node, context);
|
|
426
|
+
if (id == null) return true;
|
|
427
|
+
const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
|
|
421
428
|
return name != null && isComponentName(name);
|
|
422
429
|
}
|
|
423
430
|
|
|
@@ -460,7 +467,6 @@ function getComponentFlag(initPath) {
|
|
|
460
467
|
}
|
|
461
468
|
return flag;
|
|
462
469
|
}
|
|
463
|
-
var displayNameAssignmentSelector = "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']";
|
|
464
470
|
function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
|
|
465
471
|
const { collectDisplayName = false, collectHookCalls = false } = options;
|
|
466
472
|
const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
|
|
@@ -509,11 +515,11 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
509
515
|
return;
|
|
510
516
|
}
|
|
511
517
|
const initPath = AST8.getFunctionInitPath(entry.node);
|
|
512
|
-
const
|
|
513
|
-
const name = getComponentNameFromIdentifier(
|
|
518
|
+
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
519
|
+
const name = getComponentNameFromIdentifier(id);
|
|
514
520
|
const key = getId();
|
|
515
521
|
components.set(key, {
|
|
516
|
-
id
|
|
522
|
+
id,
|
|
517
523
|
key,
|
|
518
524
|
kind: "function",
|
|
519
525
|
name,
|
|
@@ -526,8 +532,9 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
526
532
|
});
|
|
527
533
|
},
|
|
528
534
|
...collectDisplayName ? {
|
|
529
|
-
[
|
|
535
|
+
[COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR](node) {
|
|
530
536
|
const { left, right } = node;
|
|
537
|
+
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
531
538
|
const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
|
|
532
539
|
const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
|
|
533
540
|
if (component == null) {
|
|
@@ -560,10 +567,10 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
560
567
|
functionEntries.pop();
|
|
561
568
|
functionEntries.push({ ...entry, isComponent });
|
|
562
569
|
const initPath = AST8.getFunctionInitPath(entry.node);
|
|
563
|
-
const
|
|
564
|
-
const name = getComponentNameFromIdentifier(
|
|
570
|
+
const id = getFunctionComponentIdentifier(entry.node, context);
|
|
571
|
+
const name = getComponentNameFromIdentifier(id);
|
|
565
572
|
components.set(entry.key, {
|
|
566
|
-
id
|
|
573
|
+
id,
|
|
567
574
|
key: entry.key,
|
|
568
575
|
kind: "function",
|
|
569
576
|
name,
|
|
@@ -590,16 +597,16 @@ function useComponentCollectorLegacy() {
|
|
|
590
597
|
if (!isClassComponent(node)) {
|
|
591
598
|
return;
|
|
592
599
|
}
|
|
593
|
-
const
|
|
600
|
+
const id = AST8.getClassIdentifier(node);
|
|
594
601
|
const key = getId();
|
|
595
602
|
const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
|
|
596
603
|
components.set(
|
|
597
604
|
key,
|
|
598
605
|
{
|
|
599
|
-
id
|
|
606
|
+
id,
|
|
600
607
|
key,
|
|
601
608
|
kind: "class",
|
|
602
|
-
name:
|
|
609
|
+
name: id?.name,
|
|
603
610
|
node,
|
|
604
611
|
// TODO: Get displayName of class component
|
|
605
612
|
displayName: _,
|
|
@@ -671,4 +678,4 @@ function isFunctionOfUseEffectCleanup(node) {
|
|
|
671
678
|
return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
|
|
672
679
|
}
|
|
673
680
|
|
|
674
|
-
export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier,
|
|
681
|
+
export { COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR, DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDisplayNameAssignment, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/core",
|
|
3
|
-
"version": "1.24.0-next.
|
|
3
|
+
"version": "1.24.0-next.14",
|
|
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": {
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"@typescript-eslint/utils": "^8.20.0",
|
|
40
40
|
"birecord": "^0.1.1",
|
|
41
41
|
"ts-pattern": "^5.6.0",
|
|
42
|
-
"@eslint-react/ast": "1.24.0-next.
|
|
43
|
-
"@eslint-react/eff": "1.24.0-next.
|
|
44
|
-
"@eslint-react/
|
|
45
|
-
"@eslint-react/
|
|
46
|
-
"@eslint-react/
|
|
42
|
+
"@eslint-react/ast": "1.24.0-next.14",
|
|
43
|
+
"@eslint-react/eff": "1.24.0-next.14",
|
|
44
|
+
"@eslint-react/shared": "1.24.0-next.14",
|
|
45
|
+
"@eslint-react/var": "1.24.0-next.14",
|
|
46
|
+
"@eslint-react/jsx": "1.24.0-next.14"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"tsup": "^8.3.5",
|