@eslint-react/core 1.24.0-next.9 → 1.24.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.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as AST from '@eslint-react/ast';
2
2
  import * as _eslint_react_shared from '@eslint-react/shared';
3
- import { RuleContext, CustomComponentNormalized } from '@eslint-react/shared';
3
+ import { RuleContext } from '@eslint-react/shared';
4
4
  import { TSESTree } from '@typescript-eslint/types';
5
5
  import { _ } from '@eslint-react/eff';
6
6
  import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
@@ -82,6 +82,13 @@ interface ComponentCollectorOptions {
82
82
  collectDisplayName?: boolean;
83
83
  collectHookCalls?: boolean;
84
84
  }
85
+ /**
86
+ * Get a ctx and listeners for the rule to collect function components
87
+ * @param context The ESLint rule context
88
+ * @param hint The hint to use
89
+ * @param options The options to use
90
+ * @returns The component collector
91
+ */
85
92
  declare function useComponentCollector(context: RuleContext, hint?: bigint, options?: ComponentCollectorOptions): {
86
93
  readonly ctx: {
87
94
  readonly getAllComponents: (node: TSESTree.Program) => Map<string, ERFunctionComponent>;
@@ -101,9 +108,6 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
101
108
  readonly listeners: {
102
109
  readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
103
110
  readonly "CallExpression[type]:exit"?: (node: TSESTree.CallExpression) => void;
104
- readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"?: (node: TSESTree.AssignmentExpression & {
105
- left: TSESTree.MemberExpression;
106
- }) => void;
107
111
  readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
108
112
  readonly ":function[type]:exit": () => {
109
113
  key: string;
@@ -115,6 +119,10 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
115
119
  };
116
120
  };
117
121
 
122
+ /**
123
+ * Get a ctx and listeners for the rule to collect class components
124
+ * @returns The context and listeners for the rule
125
+ */
118
126
  declare function useComponentCollectorLegacy(): {
119
127
  readonly ctx: {
120
128
  readonly getAllComponents: (node: TSESTree$1.Program) => Map<string, ERClassComponent>;
@@ -125,6 +133,17 @@ declare function useComponentCollectorLegacy(): {
125
133
  };
126
134
  };
127
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
+
128
147
  declare function getFunctionComponentIdentifier(node: AST.TSESTreeFunction, context: RuleContext): TSESTree.Identifier | TSESTree.Identifier[] | _;
129
148
 
130
149
  type ERComponentKind = "classComponent" | "functionComponent";
@@ -155,9 +174,6 @@ declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
155
174
  */
156
175
  declare function isInsideRenderMethod(node: TSESTree.Node): boolean;
157
176
 
158
- type EREffectMethodKind = "useEffect" | "useInsertionEffect" | "useLayoutEffect";
159
- type ERLifecycleMethodKind = "componentDidMount" | "componentWillUnmount";
160
-
161
177
  declare const RE_COMPONENT_NAME: RegExp;
162
178
  declare function getComponentNameFromIdentifier(node: TSESTree.Identifier | TSESTree.Identifier[] | _): string | undefined;
163
179
  declare function isComponentName(name: string): boolean;
@@ -241,13 +257,11 @@ declare function isClassComponent(node: TSESTree.Node): node is AST.TSESTreeClas
241
257
  */
242
258
  declare function isPureComponent(node: TSESTree.Node): boolean;
243
259
 
244
- type EREffectKind = "effect" | "insertionEffect" | "layoutEffect";
260
+ type EREffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
245
261
 
246
262
  declare function isFunctionOfUseEffectSetup(node: TSESTree.Node | _): boolean | undefined;
247
263
  declare function isFunctionOfUseEffectCleanup(node: TSESTree.Node): boolean | undefined;
248
264
 
249
- declare function getElementNameOnJsxAndHtml(node: TSESTree.JSXOpeningElement, context: RuleContext, polymorphicPropName?: string, additionalComponents?: CustomComponentNormalized[]): [string, string];
250
-
251
265
  /**
252
266
  * Determines whether inside `createElement`'s props.
253
267
  * @param node The AST node to check
@@ -321,8 +335,6 @@ interface ERSemanticEntry {
321
335
  phase: ERPhaseKind;
322
336
  }
323
337
 
324
- declare const getId: () => string;
325
-
326
338
  /**
327
339
  * Checks if the given node is a call expression to the given function or method of the pragma
328
340
  * @param name The name of the function or method to check
@@ -351,7 +363,7 @@ type IsCallFromReactMember = {
351
363
  };
352
364
  declare function isCallFromReactMember(pragmaMemberName: string, name: string): IsCallFromReactMember;
353
365
 
354
- declare function isInitializedFromReact(name: string, initialScope: Scope, importSource?: string): boolean;
366
+ declare function isInitializedFromReact(name: string, importSource: string, initialScope: Scope): boolean;
355
367
 
356
368
  /**********************************************
357
369
  * DO NOT MODIFY THIS FILE MANUALLY *
@@ -2575,4 +2587,4 @@ declare const isMemoCall: {
2575
2587
  (node: Node, context: _eslint_react_shared.RuleContext): node is CallExpression;
2576
2588
  };
2577
2589
 
2578
- export { type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type EREffectMethodKind, type EREffectPhaseKind, type ERFunctionComponent, ERFunctionComponentFlag, type ERHook, type ERHookKind, type ERLifecycleMethodKind, type ERLifecyclePhaseKind, type ERPhaseKind, ERPhaseRelevance, type ERSemanticEntry, type ERSemanticNode, type ERStateKind, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementNameOnJsxAndHtml, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, 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 };
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
@@ -1,6 +1,6 @@
1
1
  import * as AST from '@eslint-react/ast';
2
2
  import * as _eslint_react_shared from '@eslint-react/shared';
3
- import { RuleContext, CustomComponentNormalized } from '@eslint-react/shared';
3
+ import { RuleContext } from '@eslint-react/shared';
4
4
  import { TSESTree } from '@typescript-eslint/types';
5
5
  import { _ } from '@eslint-react/eff';
6
6
  import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
@@ -82,6 +82,13 @@ interface ComponentCollectorOptions {
82
82
  collectDisplayName?: boolean;
83
83
  collectHookCalls?: boolean;
84
84
  }
85
+ /**
86
+ * Get a ctx and listeners for the rule to collect function components
87
+ * @param context The ESLint rule context
88
+ * @param hint The hint to use
89
+ * @param options The options to use
90
+ * @returns The component collector
91
+ */
85
92
  declare function useComponentCollector(context: RuleContext, hint?: bigint, options?: ComponentCollectorOptions): {
86
93
  readonly ctx: {
87
94
  readonly getAllComponents: (node: TSESTree.Program) => Map<string, ERFunctionComponent>;
@@ -101,9 +108,6 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
101
108
  readonly listeners: {
102
109
  readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
103
110
  readonly "CallExpression[type]:exit"?: (node: TSESTree.CallExpression) => void;
104
- readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"?: (node: TSESTree.AssignmentExpression & {
105
- left: TSESTree.MemberExpression;
106
- }) => void;
107
111
  readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
108
112
  readonly ":function[type]:exit": () => {
109
113
  key: string;
@@ -115,6 +119,10 @@ declare function useComponentCollector(context: RuleContext, hint?: bigint, opti
115
119
  };
116
120
  };
117
121
 
122
+ /**
123
+ * Get a ctx and listeners for the rule to collect class components
124
+ * @returns The context and listeners for the rule
125
+ */
118
126
  declare function useComponentCollectorLegacy(): {
119
127
  readonly ctx: {
120
128
  readonly getAllComponents: (node: TSESTree$1.Program) => Map<string, ERClassComponent>;
@@ -125,6 +133,17 @@ declare function useComponentCollectorLegacy(): {
125
133
  };
126
134
  };
127
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
+
128
147
  declare function getFunctionComponentIdentifier(node: AST.TSESTreeFunction, context: RuleContext): TSESTree.Identifier | TSESTree.Identifier[] | _;
129
148
 
130
149
  type ERComponentKind = "classComponent" | "functionComponent";
@@ -155,9 +174,6 @@ declare function isFunctionOfRenderMethod(node: AST.TSESTreeFunction): boolean;
155
174
  */
156
175
  declare function isInsideRenderMethod(node: TSESTree.Node): boolean;
157
176
 
158
- type EREffectMethodKind = "useEffect" | "useInsertionEffect" | "useLayoutEffect";
159
- type ERLifecycleMethodKind = "componentDidMount" | "componentWillUnmount";
160
-
161
177
  declare const RE_COMPONENT_NAME: RegExp;
162
178
  declare function getComponentNameFromIdentifier(node: TSESTree.Identifier | TSESTree.Identifier[] | _): string | undefined;
163
179
  declare function isComponentName(name: string): boolean;
@@ -241,13 +257,11 @@ declare function isClassComponent(node: TSESTree.Node): node is AST.TSESTreeClas
241
257
  */
242
258
  declare function isPureComponent(node: TSESTree.Node): boolean;
243
259
 
244
- type EREffectKind = "effect" | "insertionEffect" | "layoutEffect";
260
+ type EREffectKind = "useEffect" | "useLayoutEffect" | "useInsertionEffect";
245
261
 
246
262
  declare function isFunctionOfUseEffectSetup(node: TSESTree.Node | _): boolean | undefined;
247
263
  declare function isFunctionOfUseEffectCleanup(node: TSESTree.Node): boolean | undefined;
248
264
 
249
- declare function getElementNameOnJsxAndHtml(node: TSESTree.JSXOpeningElement, context: RuleContext, polymorphicPropName?: string, additionalComponents?: CustomComponentNormalized[]): [string, string];
250
-
251
265
  /**
252
266
  * Determines whether inside `createElement`'s props.
253
267
  * @param node The AST node to check
@@ -321,8 +335,6 @@ interface ERSemanticEntry {
321
335
  phase: ERPhaseKind;
322
336
  }
323
337
 
324
- declare const getId: () => string;
325
-
326
338
  /**
327
339
  * Checks if the given node is a call expression to the given function or method of the pragma
328
340
  * @param name The name of the function or method to check
@@ -351,7 +363,7 @@ type IsCallFromReactMember = {
351
363
  };
352
364
  declare function isCallFromReactMember(pragmaMemberName: string, name: string): IsCallFromReactMember;
353
365
 
354
- declare function isInitializedFromReact(name: string, initialScope: Scope, importSource?: string): boolean;
366
+ declare function isInitializedFromReact(name: string, importSource: string, initialScope: Scope): boolean;
355
367
 
356
368
  /**********************************************
357
369
  * DO NOT MODIFY THIS FILE MANUALLY *
@@ -2575,4 +2587,4 @@ declare const isMemoCall: {
2575
2587
  (node: Node, context: _eslint_react_shared.RuleContext): node is CallExpression;
2576
2588
  };
2577
2589
 
2578
- export { type ComponentCollectorOptions, DEFAULT_COMPONENT_HINT, type ERClassComponent, ERClassComponentFlag, type ERComponent, ERComponentHint, type ERComponentKind, type EREffectKind, type EREffectMethodKind, type EREffectPhaseKind, type ERFunctionComponent, ERFunctionComponentFlag, type ERHook, type ERHookKind, type ERLifecycleMethodKind, type ERLifecyclePhaseKind, type ERPhaseKind, ERPhaseRelevance, type ERSemanticEntry, type ERSemanticNode, type ERStateKind, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementNameOnJsxAndHtml, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, 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 };
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
@@ -2,11 +2,10 @@
2
2
 
3
3
  var AST8 = require('@eslint-react/ast');
4
4
  var eff = require('@eslint-react/eff');
5
- var JSX4 = require('@eslint-react/jsx');
5
+ var JSX3 = require('@eslint-react/jsx');
6
+ var shared = require('@eslint-react/shared');
6
7
  var types = require('@typescript-eslint/types');
7
8
  var VAR = require('@eslint-react/var');
8
- var shared = require('@eslint-react/shared');
9
- require('ts-pattern');
10
9
  var birecord = require('birecord');
11
10
 
12
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -30,35 +29,12 @@ function _interopNamespace(e) {
30
29
  }
31
30
 
32
31
  var AST8__namespace = /*#__PURE__*/_interopNamespace(AST8);
33
- var JSX4__namespace = /*#__PURE__*/_interopNamespace(JSX4);
32
+ var JSX3__namespace = /*#__PURE__*/_interopNamespace(JSX3);
34
33
  var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
35
34
  var birecord__default = /*#__PURE__*/_interopDefault(birecord);
36
35
 
37
36
  // src/component/component-collector.ts
38
- function getElementNameOnJsxAndHtml(node, context, polymorphicPropName, additionalComponents = []) {
39
- const name = JSX4__namespace.getElementName(node);
40
- if (name === name.toLowerCase()) return [name, name];
41
- const component = additionalComponents.findLast((c) => c.name === name || c.re.test(name));
42
- if (component != null) return [name, component.as];
43
- if (polymorphicPropName == null) return [name, name];
44
- const initialScope = context.sourceCode.getScope(node);
45
- const attributeNode = JSX4__namespace.getAttributeNode(
46
- polymorphicPropName,
47
- initialScope,
48
- node.attributes
49
- );
50
- if (attributeNode == null) return [name, name];
51
- const polymorphicPropValue = VAR__namespace.toResolved(JSX4__namespace.getAttributeStaticValue(attributeNode, initialScope)).value;
52
- if (typeof polymorphicPropValue === "string") {
53
- return [name, polymorphicPropValue];
54
- }
55
- return [name, name];
56
- }
57
-
58
- // src/utils/get-id.ts
59
- var id = 0n;
60
- var getId = () => (id++).toString();
61
- function isInitializedFromReact(name, initialScope, importSource = "react") {
37
+ function isInitializedFromReact(name, importSource, initialScope) {
62
38
  return name.toLowerCase() === "react" || VAR__namespace.isInitializedFromSource(
63
39
  name,
64
40
  importSource,
@@ -76,12 +52,13 @@ function isFromReact(name) {
76
52
  }
77
53
  return node.name === name;
78
54
  }
55
+ const importSource = settings.importSource ?? shared.DEFAULT_ESLINT_REACT_SETTINGS.importSource;
79
56
  const initialScope = context.sourceCode.getScope(node);
80
57
  if (node.type === types.AST_NODE_TYPES.MemberExpression) {
81
- return node.object.type === types.AST_NODE_TYPES.Identifier && node.property.type === types.AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, initialScope, settings.importSource);
58
+ return node.object.type === types.AST_NODE_TYPES.Identifier && node.property.type === types.AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, importSource, initialScope);
82
59
  }
83
60
  if (node.name === name) {
84
- return isInitializedFromReact(name, initialScope, settings.importSource);
61
+ return isInitializedFromReact(name, importSource, initialScope);
85
62
  }
86
63
  return false;
87
64
  };
@@ -101,14 +78,15 @@ function isFromReactMember(memberName, name) {
101
78
  }
102
79
  return false;
103
80
  }
81
+ const importSource = settings.importSource ?? shared.DEFAULT_ESLINT_REACT_SETTINGS.importSource;
104
82
  const initialScope = context.sourceCode.getScope(node);
105
83
  if (node.property.type !== types.AST_NODE_TYPES.Identifier || node.property.name !== name) {
106
84
  return false;
107
85
  }
108
86
  if (node.object.type === types.AST_NODE_TYPES.Identifier && node.object.name === memberName) {
109
- return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
87
+ return isInitializedFromReact(node.object.name, importSource, initialScope);
110
88
  }
111
- if (node.object.type === types.AST_NODE_TYPES.MemberExpression && node.object.object.type === types.AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, initialScope, settings.importSource) && node.object.property.type === types.AST_NODE_TYPES.Identifier) {
89
+ if (node.object.type === types.AST_NODE_TYPES.MemberExpression && node.object.object.type === types.AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, importSource, initialScope) && node.object.property.type === types.AST_NODE_TYPES.Identifier) {
112
90
  return node.object.property.name === memberName;
113
91
  }
114
92
  return false;
@@ -191,8 +169,8 @@ function isReactHookName(name) {
191
169
  // src/hook/is.ts
192
170
  function isReactHook(node) {
193
171
  if (node == null) return eff._;
194
- const id2 = AST8__namespace.getFunctionIdentifier(node);
195
- return id2?.name != null && isReactHookName(id2.name);
172
+ const id = AST8__namespace.getFunctionIdentifier(node);
173
+ return id?.name != null && isReactHookName(id.name);
196
174
  }
197
175
  function isReactHookCall(node) {
198
176
  if (node == null) return false;
@@ -210,13 +188,14 @@ function isReactHookCall(node) {
210
188
  function isReactHookCallWithName(node, context) {
211
189
  if (node == null) return eff.returnFalse;
212
190
  const settings = shared.unsafeDecodeSettings(context.settings);
191
+ const importSource = settings.importSource ?? "react";
192
+ const initialScope = context.sourceCode.getScope(node);
213
193
  return (name) => {
214
- const initialScope = context.sourceCode.getScope(node);
215
194
  switch (true) {
216
195
  case (node.callee.type === types.AST_NODE_TYPES.Identifier && node.callee.name === name):
217
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
196
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
218
197
  case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
219
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
198
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
220
199
  default:
221
200
  return false;
222
201
  }
@@ -237,13 +216,14 @@ function isReactHookCallWithNameLoose(node) {
237
216
  }
238
217
  function isReactHookCallWithNameAlias(name, context, alias) {
239
218
  const settings = shared.unsafeDecodeSettings(context);
219
+ const importSource = settings.importSource ?? "react";
240
220
  return (node) => {
241
221
  const initialScope = context.sourceCode.getScope(node);
242
222
  switch (true) {
243
223
  case (node.callee.type === types.AST_NODE_TYPES.Identifier && node.callee.name === name):
244
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
224
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
245
225
  case (node.callee.type === types.AST_NODE_TYPES.MemberExpression && node.callee.property.type === types.AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
246
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
226
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
247
227
  default:
248
228
  return alias.some(isReactHookCallWithNameLoose(node));
249
229
  }
@@ -287,13 +267,13 @@ function useHookCollector() {
287
267
  const hooks = /* @__PURE__ */ new Map();
288
268
  const fEntries = [];
289
269
  const onFunctionEnter = (node) => {
290
- const id2 = AST8__namespace.getFunctionIdentifier(node);
291
- const name = id2?.name;
270
+ const id = AST8__namespace.getFunctionIdentifier(node);
271
+ const name = id?.name;
292
272
  if (name != null && isReactHookName(name)) {
293
- const key = getId();
273
+ const key = shared.getId();
294
274
  fEntries.push({ key, node });
295
275
  hooks.set(key, {
296
- id: id2,
276
+ id,
297
277
  key,
298
278
  kind: "function",
299
279
  name,
@@ -339,7 +319,7 @@ function useHookCollector() {
339
319
  return { ctx, listeners };
340
320
  }
341
321
  var ERComponentHint = {
342
- ...JSX4__namespace.JSXValueHint,
322
+ ...JSX3__namespace.JSXValueHint,
343
323
  // 1n << 0n - 1n << 63n are reserved for JSXValueHint
344
324
  // Skip function component created by React.memo
345
325
  SkipMemo: 1n << 64n,
@@ -355,6 +335,17 @@ var ERComponentHint = {
355
335
  SkipClassProperty: 1n << 69n
356
336
  };
357
337
  var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
338
+ var COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
339
+ "AssignmentExpression",
340
+ "[type]",
341
+ "[operator='=']",
342
+ "[left.type='MemberExpression']",
343
+ "[left.property.name='displayName']"
344
+ ].join("");
345
+ function isComponentDisplayNameAssignment(node) {
346
+ if (node == null) return false;
347
+ 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";
348
+ }
358
349
 
359
350
  // src/component/component-flag.ts
360
351
  var ERClassComponentFlag = {
@@ -418,6 +409,8 @@ function isPureComponent(node) {
418
409
  }
419
410
  return false;
420
411
  }
412
+
413
+ // src/component/component-lifecycle.ts
421
414
  function isComponentDidMount(node) {
422
415
  return AST8__namespace.isMethodOrProperty(node) && node.key.type === types.AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
423
416
  }
@@ -460,9 +453,9 @@ function isComponentName(name) {
460
453
  return RE_COMPONENT_NAME.test(name);
461
454
  }
462
455
  function hasNoneOrValidComponentName(node, context) {
463
- const id2 = getFunctionComponentIdentifier(node, context);
464
- if (id2 == null) return true;
465
- const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
456
+ const id = getFunctionComponentIdentifier(node, context);
457
+ if (id == null) return true;
458
+ const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
466
459
  return name != null && isComponentName(name);
467
460
  }
468
461
 
@@ -505,7 +498,6 @@ function getComponentFlag(initPath) {
505
498
  }
506
499
  return flag;
507
500
  }
508
- var displayNameAssignmentSelector = "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']";
509
501
  function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
510
502
  const { collectDisplayName = false, collectHookCalls = false } = options;
511
503
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
@@ -513,7 +505,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
513
505
  const functionEntries = [];
514
506
  const getCurrentEntry = () => functionEntries.at(-1);
515
507
  const onFunctionEnter = (node) => {
516
- const key = getId();
508
+ const key = shared.getId();
517
509
  functionEntries.push({ key, node, hookCalls: [], isComponent: false });
518
510
  };
519
511
  const onFunctionExit = () => {
@@ -523,7 +515,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
523
515
  return functionEntries.pop();
524
516
  }
525
517
  const shouldDrop = AST8__namespace.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
526
- return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX4__namespace.isJSXValue(r.argument, jsxCtx, hint);
518
+ return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3__namespace.isJSXValue(r.argument, jsxCtx, hint);
527
519
  });
528
520
  if (shouldDrop) {
529
521
  components.delete(entry.key);
@@ -549,16 +541,16 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
549
541
  return;
550
542
  }
551
543
  const { body } = entry.node;
552
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4__namespace.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
544
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3__namespace.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
553
545
  if (!isComponent) {
554
546
  return;
555
547
  }
556
548
  const initPath = AST8__namespace.getFunctionInitPath(entry.node);
557
- const id2 = getFunctionComponentIdentifier(entry.node, context);
558
- const name = getComponentNameFromIdentifier(id2);
559
- const key = getId();
549
+ const id = getFunctionComponentIdentifier(entry.node, context);
550
+ const name = getComponentNameFromIdentifier(id);
551
+ const key = shared.getId();
560
552
  components.set(key, {
561
- id: id2,
553
+ id,
562
554
  key,
563
555
  kind: "function",
564
556
  name,
@@ -571,8 +563,9 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
571
563
  });
572
564
  },
573
565
  ...collectDisplayName ? {
574
- [displayNameAssignmentSelector](node) {
566
+ [COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR](node) {
575
567
  const { left, right } = node;
568
+ if (left.type !== types.AST_NODE_TYPES.MemberExpression) return;
576
569
  const componentName = left.object.type === types.AST_NODE_TYPES.Identifier ? left.object.name : eff._;
577
570
  const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
578
571
  if (component == null) {
@@ -598,17 +591,17 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
598
591
  if (entry == null) {
599
592
  return;
600
593
  }
601
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4__namespace.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
594
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3__namespace.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
602
595
  if (!isComponent) {
603
596
  return;
604
597
  }
605
598
  functionEntries.pop();
606
599
  functionEntries.push({ ...entry, isComponent });
607
600
  const initPath = AST8__namespace.getFunctionInitPath(entry.node);
608
- const id2 = getFunctionComponentIdentifier(entry.node, context);
609
- const name = getComponentNameFromIdentifier(id2);
601
+ const id = getFunctionComponentIdentifier(entry.node, context);
602
+ const name = getComponentNameFromIdentifier(id);
610
603
  components.set(entry.key, {
611
- id: id2,
604
+ id,
612
605
  key: entry.key,
613
606
  kind: "function",
614
607
  name,
@@ -635,16 +628,16 @@ function useComponentCollectorLegacy() {
635
628
  if (!isClassComponent(node)) {
636
629
  return;
637
630
  }
638
- const id2 = AST8__namespace.getClassIdentifier(node);
639
- const key = getId();
631
+ const id = AST8__namespace.getClassIdentifier(node);
632
+ const key = shared.getId();
640
633
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
641
634
  components.set(
642
635
  key,
643
636
  {
644
- id: id2,
637
+ id,
645
638
  key,
646
639
  kind: "class",
647
- name: id2?.name,
640
+ name: id?.name,
648
641
  node,
649
642
  // TODO: Get displayName of class component
650
643
  displayName: eff._,
@@ -671,12 +664,12 @@ function isRenderFunctionLoose(node, context) {
671
664
  if (AST8__namespace.getFunctionIdentifier(node)?.name.startsWith("render")) {
672
665
  return parent.type === types.AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === types.AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === types.AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
673
666
  }
674
- return JSX4__namespace.isJSXValue(
667
+ return JSX3__namespace.isJSXValue(
675
668
  body,
676
669
  {
677
670
  getScope: (node2) => context.sourceCode.getScope(node2)
678
671
  },
679
- JSX4__namespace.JSXValueHint.SkipNullLiteral | JSX4__namespace.JSXValueHint.SkipUndefined | JSX4__namespace.JSXValueHint.StrictLogical | JSX4__namespace.JSXValueHint.StrictConditional
672
+ JSX3__namespace.JSXValueHint.SkipNullLiteral | JSX3__namespace.JSXValueHint.SkipUndefined | JSX3__namespace.JSXValueHint.StrictLogical | JSX3__namespace.JSXValueHint.StrictConditional
680
673
  );
681
674
  }
682
675
  function isRenderPropLoose(node, context) {
@@ -716,6 +709,7 @@ function isFunctionOfUseEffectCleanup(node) {
716
709
  return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
717
710
  }
718
711
 
712
+ exports.COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR;
719
713
  exports.DEFAULT_COMPONENT_HINT = DEFAULT_COMPONENT_HINT;
720
714
  exports.ERClassComponentFlag = ERClassComponentFlag;
721
715
  exports.ERComponentHint = ERComponentHint;
@@ -724,9 +718,7 @@ exports.ERPhaseRelevance = ERPhaseRelevance;
724
718
  exports.RE_COMPONENT_NAME = RE_COMPONENT_NAME;
725
719
  exports.RE_HOOK_NAME = RE_HOOK_NAME;
726
720
  exports.getComponentNameFromIdentifier = getComponentNameFromIdentifier;
727
- exports.getElementNameOnJsxAndHtml = getElementNameOnJsxAndHtml;
728
721
  exports.getFunctionComponentIdentifier = getFunctionComponentIdentifier;
729
- exports.getId = getId;
730
722
  exports.hasNoneOrValidComponentName = hasNoneOrValidComponentName;
731
723
  exports.isCallFromReact = isCallFromReact;
732
724
  exports.isCallFromReactMember = isCallFromReactMember;
@@ -746,6 +738,7 @@ exports.isCloneElement = isCloneElement;
746
738
  exports.isCloneElementCall = isCloneElementCall;
747
739
  exports.isComponentDidCatch = isComponentDidCatch;
748
740
  exports.isComponentDidMount = isComponentDidMount;
741
+ exports.isComponentDisplayNameAssignment = isComponentDisplayNameAssignment;
749
742
  exports.isComponentName = isComponentName;
750
743
  exports.isComponentWillUnmount = isComponentWillUnmount;
751
744
  exports.isCreateContext = isCreateContext;
package/dist/index.mjs CHANGED
@@ -1,37 +1,13 @@
1
1
  import * as AST8 from '@eslint-react/ast';
2
2
  import { flip, dual, _, returnFalse } from '@eslint-react/eff';
3
- import * as JSX4 from '@eslint-react/jsx';
3
+ import * as JSX3 from '@eslint-react/jsx';
4
+ import { unsafeDecodeSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
4
5
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
5
6
  import * as VAR from '@eslint-react/var';
6
- import { unsafeDecodeSettings } from '@eslint-react/shared';
7
- import 'ts-pattern';
8
7
  import birecord from 'birecord';
9
8
 
10
9
  // src/component/component-collector.ts
11
- function getElementNameOnJsxAndHtml(node, context, polymorphicPropName, additionalComponents = []) {
12
- const name = JSX4.getElementName(node);
13
- if (name === name.toLowerCase()) return [name, name];
14
- const component = additionalComponents.findLast((c) => c.name === name || c.re.test(name));
15
- if (component != null) return [name, component.as];
16
- if (polymorphicPropName == null) return [name, name];
17
- const initialScope = context.sourceCode.getScope(node);
18
- const attributeNode = JSX4.getAttributeNode(
19
- polymorphicPropName,
20
- initialScope,
21
- node.attributes
22
- );
23
- if (attributeNode == null) return [name, name];
24
- const polymorphicPropValue = VAR.toResolved(JSX4.getAttributeStaticValue(attributeNode, initialScope)).value;
25
- if (typeof polymorphicPropValue === "string") {
26
- return [name, polymorphicPropValue];
27
- }
28
- return [name, name];
29
- }
30
-
31
- // src/utils/get-id.ts
32
- var id = 0n;
33
- var getId = () => (id++).toString();
34
- function isInitializedFromReact(name, initialScope, importSource = "react") {
10
+ function isInitializedFromReact(name, importSource, initialScope) {
35
11
  return name.toLowerCase() === "react" || VAR.isInitializedFromSource(
36
12
  name,
37
13
  importSource,
@@ -49,12 +25,13 @@ function isFromReact(name) {
49
25
  }
50
26
  return node.name === name;
51
27
  }
28
+ const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
52
29
  const initialScope = context.sourceCode.getScope(node);
53
30
  if (node.type === AST_NODE_TYPES.MemberExpression) {
54
- return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, initialScope, settings.importSource);
31
+ return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, importSource, initialScope);
55
32
  }
56
33
  if (node.name === name) {
57
- return isInitializedFromReact(name, initialScope, settings.importSource);
34
+ return isInitializedFromReact(name, importSource, initialScope);
58
35
  }
59
36
  return false;
60
37
  };
@@ -74,14 +51,15 @@ function isFromReactMember(memberName, name) {
74
51
  }
75
52
  return false;
76
53
  }
54
+ const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
77
55
  const initialScope = context.sourceCode.getScope(node);
78
56
  if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
79
57
  return false;
80
58
  }
81
59
  if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
82
- return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
60
+ return isInitializedFromReact(node.object.name, importSource, initialScope);
83
61
  }
84
- if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, initialScope, settings.importSource) && node.object.property.type === AST_NODE_TYPES.Identifier) {
62
+ if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, importSource, initialScope) && node.object.property.type === AST_NODE_TYPES.Identifier) {
85
63
  return node.object.property.name === memberName;
86
64
  }
87
65
  return false;
@@ -164,8 +142,8 @@ function isReactHookName(name) {
164
142
  // src/hook/is.ts
165
143
  function isReactHook(node) {
166
144
  if (node == null) return _;
167
- const id2 = AST8.getFunctionIdentifier(node);
168
- return id2?.name != null && isReactHookName(id2.name);
145
+ const id = AST8.getFunctionIdentifier(node);
146
+ return id?.name != null && isReactHookName(id.name);
169
147
  }
170
148
  function isReactHookCall(node) {
171
149
  if (node == null) return false;
@@ -183,13 +161,14 @@ function isReactHookCall(node) {
183
161
  function isReactHookCallWithName(node, context) {
184
162
  if (node == null) return returnFalse;
185
163
  const settings = unsafeDecodeSettings(context.settings);
164
+ const importSource = settings.importSource ?? "react";
165
+ const initialScope = context.sourceCode.getScope(node);
186
166
  return (name) => {
187
- const initialScope = context.sourceCode.getScope(node);
188
167
  switch (true) {
189
168
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
190
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
169
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
191
170
  case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
192
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
171
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
193
172
  default:
194
173
  return false;
195
174
  }
@@ -210,13 +189,14 @@ function isReactHookCallWithNameLoose(node) {
210
189
  }
211
190
  function isReactHookCallWithNameAlias(name, context, alias) {
212
191
  const settings = unsafeDecodeSettings(context);
192
+ const importSource = settings.importSource ?? "react";
213
193
  return (node) => {
214
194
  const initialScope = context.sourceCode.getScope(node);
215
195
  switch (true) {
216
196
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
217
- return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
197
+ return !settings.strictImportCheck || isInitializedFromReact(name, importSource, initialScope);
218
198
  case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
219
- return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
199
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
220
200
  default:
221
201
  return alias.some(isReactHookCallWithNameLoose(node));
222
202
  }
@@ -260,13 +240,13 @@ function useHookCollector() {
260
240
  const hooks = /* @__PURE__ */ new Map();
261
241
  const fEntries = [];
262
242
  const onFunctionEnter = (node) => {
263
- const id2 = AST8.getFunctionIdentifier(node);
264
- const name = id2?.name;
243
+ const id = AST8.getFunctionIdentifier(node);
244
+ const name = id?.name;
265
245
  if (name != null && isReactHookName(name)) {
266
246
  const key = getId();
267
247
  fEntries.push({ key, node });
268
248
  hooks.set(key, {
269
- id: id2,
249
+ id,
270
250
  key,
271
251
  kind: "function",
272
252
  name,
@@ -312,7 +292,7 @@ function useHookCollector() {
312
292
  return { ctx, listeners };
313
293
  }
314
294
  var ERComponentHint = {
315
- ...JSX4.JSXValueHint,
295
+ ...JSX3.JSXValueHint,
316
296
  // 1n << 0n - 1n << 63n are reserved for JSXValueHint
317
297
  // Skip function component created by React.memo
318
298
  SkipMemo: 1n << 64n,
@@ -328,6 +308,17 @@ var ERComponentHint = {
328
308
  SkipClassProperty: 1n << 69n
329
309
  };
330
310
  var DEFAULT_COMPONENT_HINT = 0n | ERComponentHint.SkipBooleanLiteral | ERComponentHint.SkipMapCallback | ERComponentHint.SkipNumberLiteral | ERComponentHint.SkipStringLiteral | ERComponentHint.SkipUndefined | ERComponentHint.SkipEmptyArray | ERComponentHint.StrictArray | ERComponentHint.StrictConditional | ERComponentHint.StrictLogical;
311
+ var COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
312
+ "AssignmentExpression",
313
+ "[type]",
314
+ "[operator='=']",
315
+ "[left.type='MemberExpression']",
316
+ "[left.property.name='displayName']"
317
+ ].join("");
318
+ function isComponentDisplayNameAssignment(node) {
319
+ if (node == null) return false;
320
+ 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";
321
+ }
331
322
 
332
323
  // src/component/component-flag.ts
333
324
  var ERClassComponentFlag = {
@@ -391,6 +382,8 @@ function isPureComponent(node) {
391
382
  }
392
383
  return false;
393
384
  }
385
+
386
+ // src/component/component-lifecycle.ts
394
387
  function isComponentDidMount(node) {
395
388
  return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
396
389
  }
@@ -433,9 +426,9 @@ function isComponentName(name) {
433
426
  return RE_COMPONENT_NAME.test(name);
434
427
  }
435
428
  function hasNoneOrValidComponentName(node, context) {
436
- const id2 = getFunctionComponentIdentifier(node, context);
437
- if (id2 == null) return true;
438
- const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
429
+ const id = getFunctionComponentIdentifier(node, context);
430
+ if (id == null) return true;
431
+ const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
439
432
  return name != null && isComponentName(name);
440
433
  }
441
434
 
@@ -478,7 +471,6 @@ function getComponentFlag(initPath) {
478
471
  }
479
472
  return flag;
480
473
  }
481
- var displayNameAssignmentSelector = "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']";
482
474
  function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options = {}) {
483
475
  const { collectDisplayName = false, collectHookCalls = false } = options;
484
476
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
@@ -496,7 +488,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
496
488
  return functionEntries.pop();
497
489
  }
498
490
  const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
499
- return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
491
+ return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
500
492
  });
501
493
  if (shouldDrop) {
502
494
  components.delete(entry.key);
@@ -522,16 +514,16 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
522
514
  return;
523
515
  }
524
516
  const { body } = entry.node;
525
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
517
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
526
518
  if (!isComponent) {
527
519
  return;
528
520
  }
529
521
  const initPath = AST8.getFunctionInitPath(entry.node);
530
- const id2 = getFunctionComponentIdentifier(entry.node, context);
531
- const name = getComponentNameFromIdentifier(id2);
522
+ const id = getFunctionComponentIdentifier(entry.node, context);
523
+ const name = getComponentNameFromIdentifier(id);
532
524
  const key = getId();
533
525
  components.set(key, {
534
- id: id2,
526
+ id,
535
527
  key,
536
528
  kind: "function",
537
529
  name,
@@ -544,8 +536,9 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
544
536
  });
545
537
  },
546
538
  ...collectDisplayName ? {
547
- [displayNameAssignmentSelector](node) {
539
+ [COMPONENT_DISPLAY_NAME_ASSIGNMENT_SELECTOR](node) {
548
540
  const { left, right } = node;
541
+ if (left.type !== AST_NODE_TYPES.MemberExpression) return;
549
542
  const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
550
543
  const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
551
544
  if (component == null) {
@@ -571,17 +564,17 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
571
564
  if (entry == null) {
572
565
  return;
573
566
  }
574
- const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
567
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
575
568
  if (!isComponent) {
576
569
  return;
577
570
  }
578
571
  functionEntries.pop();
579
572
  functionEntries.push({ ...entry, isComponent });
580
573
  const initPath = AST8.getFunctionInitPath(entry.node);
581
- const id2 = getFunctionComponentIdentifier(entry.node, context);
582
- const name = getComponentNameFromIdentifier(id2);
574
+ const id = getFunctionComponentIdentifier(entry.node, context);
575
+ const name = getComponentNameFromIdentifier(id);
583
576
  components.set(entry.key, {
584
- id: id2,
577
+ id,
585
578
  key: entry.key,
586
579
  kind: "function",
587
580
  name,
@@ -608,16 +601,16 @@ function useComponentCollectorLegacy() {
608
601
  if (!isClassComponent(node)) {
609
602
  return;
610
603
  }
611
- const id2 = AST8.getClassIdentifier(node);
604
+ const id = AST8.getClassIdentifier(node);
612
605
  const key = getId();
613
606
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
614
607
  components.set(
615
608
  key,
616
609
  {
617
- id: id2,
610
+ id,
618
611
  key,
619
612
  kind: "class",
620
- name: id2?.name,
613
+ name: id?.name,
621
614
  node,
622
615
  // TODO: Get displayName of class component
623
616
  displayName: _,
@@ -644,12 +637,12 @@ function isRenderFunctionLoose(node, context) {
644
637
  if (AST8.getFunctionIdentifier(node)?.name.startsWith("render")) {
645
638
  return parent.type === AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
646
639
  }
647
- return JSX4.isJSXValue(
640
+ return JSX3.isJSXValue(
648
641
  body,
649
642
  {
650
643
  getScope: (node2) => context.sourceCode.getScope(node2)
651
644
  },
652
- JSX4.JSXValueHint.SkipNullLiteral | JSX4.JSXValueHint.SkipUndefined | JSX4.JSXValueHint.StrictLogical | JSX4.JSXValueHint.StrictConditional
645
+ JSX3.JSXValueHint.SkipNullLiteral | JSX3.JSXValueHint.SkipUndefined | JSX3.JSXValueHint.StrictLogical | JSX3.JSXValueHint.StrictConditional
653
646
  );
654
647
  }
655
648
  function isRenderPropLoose(node, context) {
@@ -689,4 +682,4 @@ function isFunctionOfUseEffectCleanup(node) {
689
682
  return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
690
683
  }
691
684
 
692
- export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementNameOnJsxAndHtml, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, 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 };
685
+ 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.9",
3
+ "version": "1.24.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": {
@@ -38,12 +38,12 @@
38
38
  "@typescript-eslint/types": "^8.20.0",
39
39
  "@typescript-eslint/utils": "^8.20.0",
40
40
  "birecord": "^0.1.1",
41
- "ts-pattern": "^5.6.0",
42
- "@eslint-react/ast": "1.24.0-next.9",
43
- "@eslint-react/eff": "1.24.0-next.9",
44
- "@eslint-react/jsx": "1.24.0-next.9",
45
- "@eslint-react/var": "1.24.0-next.9",
46
- "@eslint-react/shared": "1.24.0-next.9"
41
+ "ts-pattern": "^5.6.1",
42
+ "@eslint-react/ast": "1.24.0",
43
+ "@eslint-react/var": "1.24.0",
44
+ "@eslint-react/jsx": "1.24.0",
45
+ "@eslint-react/shared": "1.24.0",
46
+ "@eslint-react/eff": "1.24.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.3.5",