@eslint-react/core 1.23.1 → 1.23.2-beta.6

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
@@ -5,7 +5,6 @@ import * as _eslint_react_types from '@eslint-react/types';
5
5
  import { RuleContext } from '@eslint-react/types';
6
6
  import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
7
7
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
8
- import { ESLintReactSettings } from '@eslint-react/shared';
9
8
  import { Scope } from '@typescript-eslint/scope-manager';
10
9
  import { SyntaxKind } from 'typescript';
11
10
 
@@ -80,14 +79,31 @@ type ERComponent = ERClassComponent | ERFunctionComponent;
80
79
  declare function useComponentCollector(context: RuleContext, hint?: bigint): {
81
80
  readonly ctx: {
82
81
  readonly getAllComponents: (_: TSESTree.Program) => Map<string, ERFunctionComponent>;
83
- readonly getCurrentFunction: () => O.Option<[key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]]>;
84
- readonly getCurrentFunctionStack: () => [key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]][];
82
+ readonly getCurrentFunction: () => O.Option<{
83
+ key: string;
84
+ node: AST.TSESTreeFunction;
85
+ hookCalls: TSESTree.CallExpression[];
86
+ isComponent: boolean;
87
+ }>;
88
+ readonly getCurrentFunctionStack: () => {
89
+ key: string;
90
+ node: AST.TSESTreeFunction;
91
+ hookCalls: TSESTree.CallExpression[];
92
+ isComponent: boolean;
93
+ }[];
85
94
  };
86
95
  readonly listeners: {
87
96
  readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
88
- readonly ":function[type]:exit": () => [key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]] | undefined;
97
+ readonly ":function[type]:exit": () => {
98
+ key: string;
99
+ node: AST.TSESTreeFunction;
100
+ hookCalls: TSESTree.CallExpression[];
101
+ isComponent: boolean;
102
+ } | undefined;
89
103
  readonly "ArrowFunctionExpression[type][body.type!='BlockStatement']": () => void;
90
- readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']": (node: TSESTree.Node) => void;
104
+ readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']": (node: TSESTree.AssignmentExpression & {
105
+ left: TSESTree.MemberExpression;
106
+ }) => void;
91
107
  readonly "CallExpression[type]:exit": (node: TSESTree.CallExpression) => void;
92
108
  readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
93
109
  };
@@ -299,6 +315,8 @@ declare function isThisSetState(node: TSESTree.CallExpression): boolean;
299
315
 
300
316
  type ERStateKind = "actionState" | "state";
301
317
 
318
+ declare const getId: () => string;
319
+
302
320
  /**
303
321
  * Checks if the given node is a call expression to the given function or method of the pragma
304
322
  * @param name The name of the function or method to check
@@ -327,14 +345,7 @@ type IsCallFromReactMember = {
327
345
  };
328
346
  declare function isCallFromReactMember(pragmaMemberName: string, name: string): IsCallFromReactMember;
329
347
 
330
- /**
331
- * Check if an identifier is initialized from React
332
- * @param name The top-level identifier's name
333
- * @param initialScope Initial scope to search for the identifier
334
- * @param settings ESLint React settings
335
- * @returns Whether the identifier is initialized from React
336
- */
337
- declare function isInitializedFromReact(name: string, initialScope: Scope, settings: ESLintReactSettings): boolean;
348
+ declare function isInitializedFromReact(name: string, initialScope: Scope, importSource?: string): boolean;
338
349
 
339
350
  /**********************************************
340
351
  * DO NOT MODIFY THIS FILE MANUALLY *
@@ -2558,11 +2569,4 @@ declare const isMemoCall: {
2558
2569
  (node: Node, context: _eslint_react_types.RuleContext): node is CallExpression;
2559
2570
  };
2560
2571
 
2561
- declare function next(): bigint;
2562
-
2563
- declare const uid_next: typeof next;
2564
- declare namespace uid {
2565
- export { uid_next as next };
2566
- }
2567
-
2568
- export { 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, getElementRepresentName, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, uid, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
2572
+ export { 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, getElementRepresentName, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, 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
@@ -5,7 +5,6 @@ import * as _eslint_react_types from '@eslint-react/types';
5
5
  import { RuleContext } from '@eslint-react/types';
6
6
  import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
7
7
  import * as _typescript_eslint_utils_ts_eslint from '@typescript-eslint/utils/ts-eslint';
8
- import { ESLintReactSettings } from '@eslint-react/shared';
9
8
  import { Scope } from '@typescript-eslint/scope-manager';
10
9
  import { SyntaxKind } from 'typescript';
11
10
 
@@ -80,14 +79,31 @@ type ERComponent = ERClassComponent | ERFunctionComponent;
80
79
  declare function useComponentCollector(context: RuleContext, hint?: bigint): {
81
80
  readonly ctx: {
82
81
  readonly getAllComponents: (_: TSESTree.Program) => Map<string, ERFunctionComponent>;
83
- readonly getCurrentFunction: () => O.Option<[key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]]>;
84
- readonly getCurrentFunctionStack: () => [key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]][];
82
+ readonly getCurrentFunction: () => O.Option<{
83
+ key: string;
84
+ node: AST.TSESTreeFunction;
85
+ hookCalls: TSESTree.CallExpression[];
86
+ isComponent: boolean;
87
+ }>;
88
+ readonly getCurrentFunctionStack: () => {
89
+ key: string;
90
+ node: AST.TSESTreeFunction;
91
+ hookCalls: TSESTree.CallExpression[];
92
+ isComponent: boolean;
93
+ }[];
85
94
  };
86
95
  readonly listeners: {
87
96
  readonly ":function[type]": (node: AST.TSESTreeFunction) => void;
88
- readonly ":function[type]:exit": () => [key: string, node: AST.TSESTreeFunction, isComponent: boolean, hookCalls: TSESTree.CallExpression[]] | undefined;
97
+ readonly ":function[type]:exit": () => {
98
+ key: string;
99
+ node: AST.TSESTreeFunction;
100
+ hookCalls: TSESTree.CallExpression[];
101
+ isComponent: boolean;
102
+ } | undefined;
89
103
  readonly "ArrowFunctionExpression[type][body.type!='BlockStatement']": () => void;
90
- readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']": (node: TSESTree.Node) => void;
104
+ readonly "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']": (node: TSESTree.AssignmentExpression & {
105
+ left: TSESTree.MemberExpression;
106
+ }) => void;
91
107
  readonly "CallExpression[type]:exit": (node: TSESTree.CallExpression) => void;
92
108
  readonly "ReturnStatement[type]": (node: TSESTree.ReturnStatement) => void;
93
109
  };
@@ -299,6 +315,8 @@ declare function isThisSetState(node: TSESTree.CallExpression): boolean;
299
315
 
300
316
  type ERStateKind = "actionState" | "state";
301
317
 
318
+ declare const getId: () => string;
319
+
302
320
  /**
303
321
  * Checks if the given node is a call expression to the given function or method of the pragma
304
322
  * @param name The name of the function or method to check
@@ -327,14 +345,7 @@ type IsCallFromReactMember = {
327
345
  };
328
346
  declare function isCallFromReactMember(pragmaMemberName: string, name: string): IsCallFromReactMember;
329
347
 
330
- /**
331
- * Check if an identifier is initialized from React
332
- * @param name The top-level identifier's name
333
- * @param initialScope Initial scope to search for the identifier
334
- * @param settings ESLint React settings
335
- * @returns Whether the identifier is initialized from React
336
- */
337
- declare function isInitializedFromReact(name: string, initialScope: Scope, settings: ESLintReactSettings): boolean;
348
+ declare function isInitializedFromReact(name: string, initialScope: Scope, importSource?: string): boolean;
338
349
 
339
350
  /**********************************************
340
351
  * DO NOT MODIFY THIS FILE MANUALLY *
@@ -2558,11 +2569,4 @@ declare const isMemoCall: {
2558
2569
  (node: Node, context: _eslint_react_types.RuleContext): node is CallExpression;
2559
2570
  };
2560
2571
 
2561
- declare function next(): bigint;
2562
-
2563
- declare const uid_next: typeof next;
2564
- declare namespace uid {
2565
- export { uid_next as next };
2566
- }
2567
-
2568
- export { 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, getElementRepresentName, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, uid, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
2572
+ export { 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, getElementRepresentName, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, 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
@@ -31,15 +31,11 @@ var AST9__namespace = /*#__PURE__*/_interopNamespace(AST9);
31
31
  var JSX4__namespace = /*#__PURE__*/_interopNamespace(JSX4);
32
32
  var VAR__namespace = /*#__PURE__*/_interopNamespace(VAR);
33
33
 
34
- var __defProp = Object.defineProperty;
35
- var __export = (target, all) => {
36
- for (var name in all)
37
- __defProp(target, name, { get: all[name], enumerable: true });
38
- };
34
+ // src/component/component-collector.ts
39
35
  function getElementRepresentName(node, context) {
40
36
  const rawElementName = JSX4__namespace.getElementName(node);
41
37
  if (rawElementName === rawElementName.toLowerCase()) return rawElementName;
42
- const { components, polymorphicPropName } = shared.normalizeSettings(shared.decodeSettings(context.settings));
38
+ const { components, polymorphicPropName } = shared.getSettingsFromContext(context);
43
39
  const asElementName = components.get(rawElementName);
44
40
  if (eff.isString(asElementName)) return asElementName;
45
41
  return eff.F.pipe(
@@ -50,34 +46,55 @@ function getElementRepresentName(node, context) {
50
46
  eff.O.getOrElse(() => rawElementName)
51
47
  );
52
48
  }
53
- function isInitializedFromReact(name, initialScope, settings) {
54
- if (!settings.strictImportCheck) return true;
55
- if (name.toLowerCase() === "react") return true;
56
- const { importSource = "react" } = settings;
57
- return VAR__namespace.isInitializedFromSource(name, importSource, initialScope);
49
+
50
+ // src/utils/get-id.ts
51
+ var id = 0n;
52
+ var getId = () => (id++).toString();
53
+ function isInitializedFromReact(name, initialScope, importSource = "react") {
54
+ return name.toLowerCase() === "react" || VAR__namespace.isInitializedFromSource(
55
+ name,
56
+ importSource,
57
+ initialScope
58
+ );
58
59
  }
59
60
 
60
61
  // src/utils/is-from-react.ts
61
62
  function isFromReact(name) {
62
63
  return (node, context) => {
63
- const settings = shared.unsafeReadSettings(context.settings);
64
+ const settings = shared.unsafeDecodeSettings(context.settings);
65
+ if (!settings.strictImportCheck) {
66
+ if (node.type === types.AST_NODE_TYPES.MemberExpression) {
67
+ return node.object.type === types.AST_NODE_TYPES.Identifier && node.property.type === types.AST_NODE_TYPES.Identifier && node.property.name === name;
68
+ }
69
+ return node.name === name;
70
+ }
64
71
  const initialScope = context.sourceCode.getScope(node);
65
72
  if (node.type === types.AST_NODE_TYPES.MemberExpression) {
66
- 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);
73
+ 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);
74
+ }
75
+ if (node.name === name) {
76
+ return isInitializedFromReact(name, initialScope, settings.importSource);
67
77
  }
68
- if (node.name === name) return isInitializedFromReact(name, initialScope, settings);
69
78
  return false;
70
79
  };
71
80
  }
72
81
  function isFromReactMember(memberName, name) {
73
82
  return (node, context) => {
74
- const settings = shared.unsafeReadSettings(context.settings);
83
+ const settings = shared.unsafeDecodeSettings(context.settings);
84
+ if (!settings.strictImportCheck) {
85
+ if (node.property.type !== types.AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
86
+ if (node.object.type === types.AST_NODE_TYPES.Identifier && node.object.name === memberName) return true;
87
+ if (node.object.type === types.AST_NODE_TYPES.MemberExpression && node.object.object.type === types.AST_NODE_TYPES.Identifier && node.object.property.type === types.AST_NODE_TYPES.Identifier) {
88
+ return node.object.property.name === memberName;
89
+ }
90
+ return false;
91
+ }
75
92
  const initialScope = context.sourceCode.getScope(node);
76
93
  if (node.property.type !== types.AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
77
94
  if (node.object.type === types.AST_NODE_TYPES.Identifier && node.object.name === memberName) {
78
- return isInitializedFromReact(node.object.name, initialScope, settings);
95
+ return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
79
96
  }
80
- 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) && node.object.property.type === types.AST_NODE_TYPES.Identifier) {
97
+ 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) {
81
98
  return node.object.property.name === memberName;
82
99
  }
83
100
  return false;
@@ -128,22 +145,12 @@ var isCreateRefCall = isReactAPICallWithName("createRef");
128
145
  var isForwardRefCall = isReactAPICallWithName("forwardRef");
129
146
  var isMemoCall = isReactAPICallWithName("memo");
130
147
 
131
- // src/utils/uid.ts
132
- var uid_exports = {};
133
- __export(uid_exports, {
134
- next: () => next
135
- });
136
- var id = 0n;
137
- function next() {
138
- return id++;
139
- }
140
-
141
148
  // src/element/hierarchy.ts
142
149
  function isInsideCreateElementProps(node, context) {
143
150
  return eff.F.pipe(
144
151
  eff.O.Do,
145
- eff.O.bind("call", () => AST9__namespace.traverseUpGuard(node, isCreateElementCall(context))),
146
- eff.O.bind("prop", () => AST9__namespace.traverseUpGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.ObjectExpression))),
152
+ eff.O.bind("call", () => AST9__namespace.findParentNodeGuard(node, isCreateElementCall(context))),
153
+ eff.O.bind("prop", () => AST9__namespace.findParentNodeGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.ObjectExpression))),
147
154
  eff.O.bind("arg1", ({ call }) => eff.O.fromNullable(call.arguments[1])),
148
155
  eff.O.exists(({ arg1, prop }) => prop === arg1)
149
156
  );
@@ -182,14 +189,14 @@ function isReactHookCall(node) {
182
189
  return false;
183
190
  }
184
191
  function isReactHookCallWithName(node, context) {
185
- const settings = shared.unsafeReadSettings(context.settings);
192
+ const settings = shared.unsafeDecodeSettings(context.settings);
186
193
  return (name) => {
187
194
  const initialScope = context.sourceCode.getScope(node);
188
195
  switch (true) {
189
196
  case (node.callee.type === types.AST_NODE_TYPES.Identifier && node.callee.name === name):
190
- return isInitializedFromReact(name, initialScope, settings);
197
+ return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
191
198
  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):
192
- return isInitializedFromReact(node.callee.object.name, initialScope, settings);
199
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
193
200
  default:
194
201
  return false;
195
202
  }
@@ -208,14 +215,14 @@ function isReactHookCallWithNameLoose(node) {
208
215
  };
209
216
  }
210
217
  function isReactHookCallWithNameAlias(name, context, alias) {
211
- const settings = shared.unsafeReadSettings(context.settings);
218
+ const settings = shared.unsafeDecodeSettings(context);
212
219
  return (node) => {
213
220
  const initialScope = context.sourceCode.getScope(node);
214
221
  switch (true) {
215
222
  case (node.callee.type === types.AST_NODE_TYPES.Identifier && node.callee.name === name):
216
- return isInitializedFromReact(name, initialScope, settings);
223
+ return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
217
224
  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):
218
- return isInitializedFromReact(node.callee.object.name, initialScope, settings);
225
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
219
226
  default:
220
227
  return alias.some(isReactHookCallWithNameLoose(node));
221
228
  }
@@ -250,7 +257,7 @@ var isUseTransitionCall = eff.F.flip(isReactHookCallWithName)("useTransition");
250
257
 
251
258
  // src/hook/hierarchy.ts
252
259
  function isInsideReactHook(node) {
253
- return eff.O.exists(AST9__namespace.traverseUpGuard(node, AST9__namespace.isFunction), isReactHook);
260
+ return eff.O.exists(AST9__namespace.findParentNodeGuard(node, AST9__namespace.isFunction), isReactHook);
254
261
  }
255
262
  function useHookCollector() {
256
263
  const hooks = /* @__PURE__ */ new Map();
@@ -259,7 +266,7 @@ function useHookCollector() {
259
266
  const id2 = AST9__namespace.getFunctionIdentifier(node);
260
267
  const name = eff.O.flatMapNullable(id2, (id3) => id3.name);
261
268
  if (eff.O.isSome(id2) && eff.O.isSome(name) && isReactHookName(name.value)) {
262
- const key = uid_exports.next().toString();
269
+ const key = getId();
263
270
  fStack.push([node, eff.O.some(key)]);
264
271
  hooks.set(key, {
265
272
  _: key,
@@ -417,7 +424,7 @@ function useComponentCollectorLegacy() {
417
424
  const collect = (node) => {
418
425
  if (!isClassComponent(node)) return;
419
426
  const id2 = AST9__namespace.getClassIdentifier(node);
420
- const key = uid_exports.next().toString();
427
+ const key = getId();
421
428
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
422
429
  components.set(
423
430
  key,
@@ -462,21 +469,18 @@ function isFunctionOfRenderMethod(node) {
462
469
  return isClassComponent(node.parent.parent.parent);
463
470
  }
464
471
  function isInsideRenderMethod(node) {
465
- return eff.O.isSome(AST9__namespace.traverseUp(node, (node2) => {
472
+ return eff.O.isSome(AST9__namespace.findParentNode(node, (node2) => {
466
473
  return isRenderMethodLike(node2) && isClassComponent(node2.parent.parent);
467
474
  }));
468
475
  }
469
476
  function hasNoneOrValidComponentName(node, context) {
470
- return eff.O.match(
471
- getFunctionComponentIdentifier(node, context),
472
- {
473
- onNone: eff.F.constTrue,
474
- onSome: (id2) => {
475
- const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
476
- return !!name && isComponentName(name);
477
- }
478
- }
479
- );
477
+ const mbIdentifier = getFunctionComponentIdentifier(node, context);
478
+ if (eff.O.isNone(mbIdentifier)) {
479
+ return true;
480
+ }
481
+ const id2 = mbIdentifier.value;
482
+ const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
483
+ return !!name && isComponentName(name);
480
484
  }
481
485
 
482
486
  // src/component/component-collector.ts
@@ -497,7 +501,7 @@ function hasValidHierarchy(node, context, hint) {
497
501
  return false;
498
502
  }
499
503
  return !eff.O.exists(
500
- AST9__namespace.traverseUp(
504
+ AST9__namespace.findParentNode(
501
505
  node,
502
506
  AST9__namespace.isOneOf([
503
507
  types.AST_NODE_TYPES.JSXExpressionContainer,
@@ -523,20 +527,20 @@ function getComponentFlag(initPath) {
523
527
  function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
524
528
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
525
529
  const components = /* @__PURE__ */ new Map();
526
- const functionStack = [];
527
- const getCurrentFunction = () => eff.O.fromNullable(functionStack.at(-1));
530
+ const functionEntries = [];
531
+ const getCurrentFunction = () => eff.O.fromNullable(functionEntries.at(-1));
528
532
  const onFunctionEnter = (node) => {
529
- const key = uid_exports.next().toString();
530
- functionStack.push([key, node, false, []]);
533
+ const key = getId();
534
+ functionEntries.push({ key, node, hookCalls: [], isComponent: false });
531
535
  };
532
536
  const onFunctionExit = () => {
533
- const [key, fn, isComponent] = functionStack.at(-1) ?? [];
534
- if (!key || !fn || !isComponent) return functionStack.pop();
535
- const shouldDrop = AST9__namespace.getNestedReturnStatements(fn.body).slice().reverse().some((r) => {
536
- return context.sourceCode.getScope(r).block === fn && r.argument !== null && !JSX4__namespace.isJSXValue(r.argument, jsxCtx, hint);
537
+ const { key, node, isComponent } = functionEntries.at(-1) ?? {};
538
+ if (!key || !node || !isComponent) return functionEntries.pop();
539
+ const shouldDrop = AST9__namespace.getNestedReturnStatements(node.body).slice().reverse().some((r) => {
540
+ return context.sourceCode.getScope(r).block === node && r.argument !== null && !JSX4__namespace.isJSXValue(r.argument, jsxCtx, hint);
537
541
  });
538
542
  if (shouldDrop) components.delete(key);
539
- return functionStack.pop();
543
+ return functionEntries.pop();
540
544
  };
541
545
  const ctx = {
542
546
  getAllComponents(_) {
@@ -544,43 +548,42 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
544
548
  },
545
549
  getCurrentFunction,
546
550
  getCurrentFunctionStack() {
547
- return [...functionStack];
551
+ return [...functionEntries];
548
552
  }
549
553
  };
550
554
  const listeners = {
551
555
  ":function[type]": onFunctionEnter,
552
556
  ":function[type]:exit": onFunctionExit,
553
557
  "ArrowFunctionExpression[type][body.type!='BlockStatement']"() {
554
- const maybeCurrentFn = getCurrentFunction();
555
- if (eff.O.isNone(maybeCurrentFn)) return;
556
- const [_key, currentFn, _isComponent, hookCalls] = maybeCurrentFn.value;
557
- const { body } = currentFn;
558
- const isComponent = hasNoneOrValidComponentName(currentFn, context) && JSX4__namespace.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(currentFn, context, hint);
558
+ const mbEntry = getCurrentFunction();
559
+ if (eff.O.isNone(mbEntry)) return;
560
+ const entry = mbEntry.value;
561
+ const { body } = entry.node;
562
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4__namespace.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
559
563
  if (!isComponent) return;
560
- const initPath = AST9__namespace.getFunctionInitPath(currentFn);
561
- const id2 = getFunctionComponentIdentifier(currentFn, context);
564
+ const initPath = AST9__namespace.getFunctionInitPath(entry.node);
565
+ const id2 = getFunctionComponentIdentifier(entry.node, context);
562
566
  const name = eff.O.flatMapNullable(id2, getComponentNameFromIdentifier);
563
- const key = uid_exports.next().toString();
567
+ const key = getId();
564
568
  components.set(key, {
565
569
  _: key,
566
570
  id: id2,
567
571
  kind: "function",
568
572
  name,
569
- node: currentFn,
573
+ node: entry.node,
570
574
  displayName: eff.O.none(),
571
575
  flag: getComponentFlag(initPath),
572
576
  hint,
573
- hookCalls,
577
+ hookCalls: entry.hookCalls,
574
578
  initPath
575
579
  });
576
580
  },
577
581
  "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(node) {
578
- if (node.type !== types.AST_NODE_TYPES.AssignmentExpression) return;
579
582
  const { left, right } = node;
580
- if (left.type !== types.AST_NODE_TYPES.MemberExpression) return;
581
- const maybeComponentName = tsPattern.match(left.object).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => eff.O.some(n.name)).otherwise(eff.O.none);
582
- if (eff.O.isNone(maybeComponentName)) return;
583
- const component = Array.from(components.values()).findLast(({ name }) => eff.O.exists(name, (n) => n === maybeComponentName.value));
583
+ const mbComponentName = tsPattern.match(left.object).with({ type: types.AST_NODE_TYPES.Identifier }, (n) => eff.O.some(n.name)).otherwise(eff.O.none);
584
+ if (eff.O.isNone(mbComponentName)) return;
585
+ const componentName = mbComponentName.value;
586
+ const component = Array.from(components.values()).findLast(({ name }) => eff.O.exists(name, (n) => n === componentName));
584
587
  if (!component) return;
585
588
  components.set(component._, {
586
589
  ...component,
@@ -589,34 +592,33 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
589
592
  },
590
593
  "CallExpression[type]:exit"(node) {
591
594
  if (!isReactHookCall(node)) return;
592
- const maybeCurrentFn = getCurrentFunction();
593
- if (eff.O.isNone(maybeCurrentFn)) return;
594
- const [key, currentFn, isComponent, hookCalls] = maybeCurrentFn.value;
595
- functionStack.pop();
596
- functionStack.push([key, currentFn, isComponent, [...hookCalls, node]]);
595
+ const mbEntry = getCurrentFunction();
596
+ if (eff.O.isNone(mbEntry)) return;
597
+ const entry = mbEntry.value;
598
+ functionEntries.pop();
599
+ functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
597
600
  },
598
601
  "ReturnStatement[type]"(node) {
599
- const maybeCurrentFn = getCurrentFunction();
600
- if (eff.O.isNone(maybeCurrentFn)) return;
601
- const [key, currentFn, isKnown, hookCalls] = maybeCurrentFn.value;
602
- if (isKnown) return;
603
- const isComponent = hasNoneOrValidComponentName(currentFn, context) && JSX4__namespace.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(currentFn, context, hint);
602
+ const mbEntry = getCurrentFunction();
603
+ if (eff.O.isNone(mbEntry)) return;
604
+ const entry = mbEntry.value;
605
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4__namespace.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
604
606
  if (!isComponent) return;
605
- functionStack.pop();
606
- functionStack.push([key, currentFn, true, []]);
607
- const initPath = AST9__namespace.getFunctionInitPath(currentFn);
608
- const id2 = getFunctionComponentIdentifier(currentFn, context);
607
+ functionEntries.pop();
608
+ functionEntries.push({ ...entry, isComponent });
609
+ const initPath = AST9__namespace.getFunctionInitPath(entry.node);
610
+ const id2 = getFunctionComponentIdentifier(entry.node, context);
609
611
  const name = eff.O.flatMapNullable(id2, getComponentNameFromIdentifier);
610
- components.set(key, {
611
- _: key,
612
+ components.set(entry.key, {
613
+ _: entry.key,
612
614
  id: id2,
613
615
  kind: "function",
614
616
  name,
615
- node: currentFn,
617
+ node: entry.node,
616
618
  displayName: eff.O.none(),
617
619
  flag: getComponentFlag(initPath),
618
620
  hint,
619
- hookCalls,
621
+ hookCalls: entry.hookCalls,
620
622
  initPath
621
623
  });
622
624
  }
@@ -627,10 +629,10 @@ function isSetupFunction(node) {
627
629
  return node.parent?.type === types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && node.parent.callee.type === types.AST_NODE_TYPES.Identifier && node.parent.arguments.at(0) === node && isUseEffectCallLoose(node.parent);
628
630
  }
629
631
  function isCleanupFunction(node) {
630
- const nearestRet = eff.O.getOrNull(AST9__namespace.traverseUpGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.ReturnStatement)));
632
+ const nearestRet = eff.O.getOrNull(AST9__namespace.findParentNodeGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.ReturnStatement)));
631
633
  if (!nearestRet) return false;
632
- const nearestFunction = eff.O.getOrNull(AST9__namespace.traverseUpGuard(node, AST9__namespace.isFunction));
633
- const nearestFunctionOfRet = eff.O.getOrNull(AST9__namespace.traverseUpGuard(nearestRet, AST9__namespace.isFunction));
634
+ const nearestFunction = eff.O.getOrNull(AST9__namespace.findParentNodeGuard(node, AST9__namespace.isFunction));
635
+ const nearestFunctionOfRet = eff.O.getOrNull(AST9__namespace.findParentNodeGuard(nearestRet, AST9__namespace.isFunction));
634
636
  if (!nearestFunction || !nearestFunctionOfRet) return false;
635
637
  return nearestFunction === nearestFunctionOfRet && isSetupFunction(nearestFunction);
636
638
  }
@@ -654,7 +656,7 @@ function isDeclaredInRenderPropLoose(node) {
654
656
  return true;
655
657
  }
656
658
  return eff.F.pipe(
657
- AST9__namespace.traverseUpGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.JSXExpressionContainer)),
659
+ AST9__namespace.findParentNodeGuard(node, AST9__namespace.is(types.AST_NODE_TYPES.JSXExpressionContainer)),
658
660
  eff.O.flatMapNullable((c) => c.parent),
659
661
  eff.O.filter(AST9__namespace.is(types.AST_NODE_TYPES.JSXAttribute)),
660
662
  eff.O.flatMapNullable((a) => a.name),
@@ -696,6 +698,7 @@ exports.RE_HOOK_NAME = RE_HOOK_NAME;
696
698
  exports.getComponentNameFromIdentifier = getComponentNameFromIdentifier;
697
699
  exports.getElementRepresentName = getElementRepresentName;
698
700
  exports.getFunctionComponentIdentifier = getFunctionComponentIdentifier;
701
+ exports.getId = getId;
699
702
  exports.hasNoneOrValidComponentName = hasNoneOrValidComponentName;
700
703
  exports.isCallFromReact = isCallFromReact;
701
704
  exports.isCallFromReactMember = isCallFromReactMember;
@@ -768,7 +771,6 @@ exports.isUseRefCall = isUseRefCall;
768
771
  exports.isUseStateCall = isUseStateCall;
769
772
  exports.isUseSyncExternalStoreCall = isUseSyncExternalStoreCall;
770
773
  exports.isUseTransitionCall = isUseTransitionCall;
771
- exports.uid = uid_exports;
772
774
  exports.useComponentCollector = useComponentCollector;
773
775
  exports.useComponentCollectorLegacy = useComponentCollectorLegacy;
774
776
  exports.useHookCollector = useHookCollector;
package/dist/index.mjs CHANGED
@@ -3,19 +3,15 @@ import { F, isString, O } from '@eslint-react/eff';
3
3
  import * as JSX4 from '@eslint-react/jsx';
4
4
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
5
5
  import { isMatching, P, match } from 'ts-pattern';
6
- import { normalizeSettings, decodeSettings, unsafeReadSettings } from '@eslint-react/shared';
6
+ import { getSettingsFromContext, unsafeDecodeSettings } from '@eslint-react/shared';
7
7
  import * as VAR from '@eslint-react/var';
8
8
  import { birecord } from '@eslint-react/types';
9
9
 
10
- var __defProp = Object.defineProperty;
11
- var __export = (target, all) => {
12
- for (var name in all)
13
- __defProp(target, name, { get: all[name], enumerable: true });
14
- };
10
+ // src/component/component-collector.ts
15
11
  function getElementRepresentName(node, context) {
16
12
  const rawElementName = JSX4.getElementName(node);
17
13
  if (rawElementName === rawElementName.toLowerCase()) return rawElementName;
18
- const { components, polymorphicPropName } = normalizeSettings(decodeSettings(context.settings));
14
+ const { components, polymorphicPropName } = getSettingsFromContext(context);
19
15
  const asElementName = components.get(rawElementName);
20
16
  if (isString(asElementName)) return asElementName;
21
17
  return F.pipe(
@@ -26,34 +22,55 @@ function getElementRepresentName(node, context) {
26
22
  O.getOrElse(() => rawElementName)
27
23
  );
28
24
  }
29
- function isInitializedFromReact(name, initialScope, settings) {
30
- if (!settings.strictImportCheck) return true;
31
- if (name.toLowerCase() === "react") return true;
32
- const { importSource = "react" } = settings;
33
- return VAR.isInitializedFromSource(name, importSource, initialScope);
25
+
26
+ // src/utils/get-id.ts
27
+ var id = 0n;
28
+ var getId = () => (id++).toString();
29
+ function isInitializedFromReact(name, initialScope, importSource = "react") {
30
+ return name.toLowerCase() === "react" || VAR.isInitializedFromSource(
31
+ name,
32
+ importSource,
33
+ initialScope
34
+ );
34
35
  }
35
36
 
36
37
  // src/utils/is-from-react.ts
37
38
  function isFromReact(name) {
38
39
  return (node, context) => {
39
- const settings = unsafeReadSettings(context.settings);
40
+ const settings = unsafeDecodeSettings(context.settings);
41
+ if (!settings.strictImportCheck) {
42
+ if (node.type === AST_NODE_TYPES.MemberExpression) {
43
+ return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name;
44
+ }
45
+ return node.name === name;
46
+ }
40
47
  const initialScope = context.sourceCode.getScope(node);
41
48
  if (node.type === AST_NODE_TYPES.MemberExpression) {
42
- 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);
49
+ 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);
50
+ }
51
+ if (node.name === name) {
52
+ return isInitializedFromReact(name, initialScope, settings.importSource);
43
53
  }
44
- if (node.name === name) return isInitializedFromReact(name, initialScope, settings);
45
54
  return false;
46
55
  };
47
56
  }
48
57
  function isFromReactMember(memberName, name) {
49
58
  return (node, context) => {
50
- const settings = unsafeReadSettings(context.settings);
59
+ const settings = unsafeDecodeSettings(context.settings);
60
+ if (!settings.strictImportCheck) {
61
+ if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
62
+ if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) return true;
63
+ if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && node.object.property.type === AST_NODE_TYPES.Identifier) {
64
+ return node.object.property.name === memberName;
65
+ }
66
+ return false;
67
+ }
51
68
  const initialScope = context.sourceCode.getScope(node);
52
69
  if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) return false;
53
70
  if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
54
- return isInitializedFromReact(node.object.name, initialScope, settings);
71
+ return isInitializedFromReact(node.object.name, initialScope, settings.importSource);
55
72
  }
56
- if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, initialScope, settings) && node.object.property.type === AST_NODE_TYPES.Identifier) {
73
+ 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) {
57
74
  return node.object.property.name === memberName;
58
75
  }
59
76
  return false;
@@ -104,22 +121,12 @@ var isCreateRefCall = isReactAPICallWithName("createRef");
104
121
  var isForwardRefCall = isReactAPICallWithName("forwardRef");
105
122
  var isMemoCall = isReactAPICallWithName("memo");
106
123
 
107
- // src/utils/uid.ts
108
- var uid_exports = {};
109
- __export(uid_exports, {
110
- next: () => next
111
- });
112
- var id = 0n;
113
- function next() {
114
- return id++;
115
- }
116
-
117
124
  // src/element/hierarchy.ts
118
125
  function isInsideCreateElementProps(node, context) {
119
126
  return F.pipe(
120
127
  O.Do,
121
- O.bind("call", () => AST9.traverseUpGuard(node, isCreateElementCall(context))),
122
- O.bind("prop", () => AST9.traverseUpGuard(node, AST9.is(AST_NODE_TYPES.ObjectExpression))),
128
+ O.bind("call", () => AST9.findParentNodeGuard(node, isCreateElementCall(context))),
129
+ O.bind("prop", () => AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.ObjectExpression))),
123
130
  O.bind("arg1", ({ call }) => O.fromNullable(call.arguments[1])),
124
131
  O.exists(({ arg1, prop }) => prop === arg1)
125
132
  );
@@ -158,14 +165,14 @@ function isReactHookCall(node) {
158
165
  return false;
159
166
  }
160
167
  function isReactHookCallWithName(node, context) {
161
- const settings = unsafeReadSettings(context.settings);
168
+ const settings = unsafeDecodeSettings(context.settings);
162
169
  return (name) => {
163
170
  const initialScope = context.sourceCode.getScope(node);
164
171
  switch (true) {
165
172
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
166
- return isInitializedFromReact(name, initialScope, settings);
173
+ return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
167
174
  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):
168
- return isInitializedFromReact(node.callee.object.name, initialScope, settings);
175
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
169
176
  default:
170
177
  return false;
171
178
  }
@@ -184,14 +191,14 @@ function isReactHookCallWithNameLoose(node) {
184
191
  };
185
192
  }
186
193
  function isReactHookCallWithNameAlias(name, context, alias) {
187
- const settings = unsafeReadSettings(context.settings);
194
+ const settings = unsafeDecodeSettings(context);
188
195
  return (node) => {
189
196
  const initialScope = context.sourceCode.getScope(node);
190
197
  switch (true) {
191
198
  case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
192
- return isInitializedFromReact(name, initialScope, settings);
199
+ return !settings.strictImportCheck || isInitializedFromReact(name, initialScope, settings.importSource);
193
200
  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):
194
- return isInitializedFromReact(node.callee.object.name, initialScope, settings);
201
+ return !settings.strictImportCheck || isInitializedFromReact(node.callee.object.name, initialScope, settings.importSource);
195
202
  default:
196
203
  return alias.some(isReactHookCallWithNameLoose(node));
197
204
  }
@@ -226,7 +233,7 @@ var isUseTransitionCall = F.flip(isReactHookCallWithName)("useTransition");
226
233
 
227
234
  // src/hook/hierarchy.ts
228
235
  function isInsideReactHook(node) {
229
- return O.exists(AST9.traverseUpGuard(node, AST9.isFunction), isReactHook);
236
+ return O.exists(AST9.findParentNodeGuard(node, AST9.isFunction), isReactHook);
230
237
  }
231
238
  function useHookCollector() {
232
239
  const hooks = /* @__PURE__ */ new Map();
@@ -235,7 +242,7 @@ function useHookCollector() {
235
242
  const id2 = AST9.getFunctionIdentifier(node);
236
243
  const name = O.flatMapNullable(id2, (id3) => id3.name);
237
244
  if (O.isSome(id2) && O.isSome(name) && isReactHookName(name.value)) {
238
- const key = uid_exports.next().toString();
245
+ const key = getId();
239
246
  fStack.push([node, O.some(key)]);
240
247
  hooks.set(key, {
241
248
  _: key,
@@ -393,7 +400,7 @@ function useComponentCollectorLegacy() {
393
400
  const collect = (node) => {
394
401
  if (!isClassComponent(node)) return;
395
402
  const id2 = AST9.getClassIdentifier(node);
396
- const key = uid_exports.next().toString();
403
+ const key = getId();
397
404
  const flag = isPureComponent(node) ? ERClassComponentFlag.PureComponent : ERClassComponentFlag.None;
398
405
  components.set(
399
406
  key,
@@ -438,21 +445,18 @@ function isFunctionOfRenderMethod(node) {
438
445
  return isClassComponent(node.parent.parent.parent);
439
446
  }
440
447
  function isInsideRenderMethod(node) {
441
- return O.isSome(AST9.traverseUp(node, (node2) => {
448
+ return O.isSome(AST9.findParentNode(node, (node2) => {
442
449
  return isRenderMethodLike(node2) && isClassComponent(node2.parent.parent);
443
450
  }));
444
451
  }
445
452
  function hasNoneOrValidComponentName(node, context) {
446
- return O.match(
447
- getFunctionComponentIdentifier(node, context),
448
- {
449
- onNone: F.constTrue,
450
- onSome: (id2) => {
451
- const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
452
- return !!name && isComponentName(name);
453
- }
454
- }
455
- );
453
+ const mbIdentifier = getFunctionComponentIdentifier(node, context);
454
+ if (O.isNone(mbIdentifier)) {
455
+ return true;
456
+ }
457
+ const id2 = mbIdentifier.value;
458
+ const name = Array.isArray(id2) ? id2.at(-1)?.name : id2.name;
459
+ return !!name && isComponentName(name);
456
460
  }
457
461
 
458
462
  // src/component/component-collector.ts
@@ -473,7 +477,7 @@ function hasValidHierarchy(node, context, hint) {
473
477
  return false;
474
478
  }
475
479
  return !O.exists(
476
- AST9.traverseUp(
480
+ AST9.findParentNode(
477
481
  node,
478
482
  AST9.isOneOf([
479
483
  AST_NODE_TYPES.JSXExpressionContainer,
@@ -499,20 +503,20 @@ function getComponentFlag(initPath) {
499
503
  function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
500
504
  const jsxCtx = { getScope: (node) => context.sourceCode.getScope(node) };
501
505
  const components = /* @__PURE__ */ new Map();
502
- const functionStack = [];
503
- const getCurrentFunction = () => O.fromNullable(functionStack.at(-1));
506
+ const functionEntries = [];
507
+ const getCurrentFunction = () => O.fromNullable(functionEntries.at(-1));
504
508
  const onFunctionEnter = (node) => {
505
- const key = uid_exports.next().toString();
506
- functionStack.push([key, node, false, []]);
509
+ const key = getId();
510
+ functionEntries.push({ key, node, hookCalls: [], isComponent: false });
507
511
  };
508
512
  const onFunctionExit = () => {
509
- const [key, fn, isComponent] = functionStack.at(-1) ?? [];
510
- if (!key || !fn || !isComponent) return functionStack.pop();
511
- const shouldDrop = AST9.getNestedReturnStatements(fn.body).slice().reverse().some((r) => {
512
- return context.sourceCode.getScope(r).block === fn && r.argument !== null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
513
+ const { key, node, isComponent } = functionEntries.at(-1) ?? {};
514
+ if (!key || !node || !isComponent) return functionEntries.pop();
515
+ const shouldDrop = AST9.getNestedReturnStatements(node.body).slice().reverse().some((r) => {
516
+ return context.sourceCode.getScope(r).block === node && r.argument !== null && !JSX4.isJSXValue(r.argument, jsxCtx, hint);
513
517
  });
514
518
  if (shouldDrop) components.delete(key);
515
- return functionStack.pop();
519
+ return functionEntries.pop();
516
520
  };
517
521
  const ctx = {
518
522
  getAllComponents(_) {
@@ -520,43 +524,42 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
520
524
  },
521
525
  getCurrentFunction,
522
526
  getCurrentFunctionStack() {
523
- return [...functionStack];
527
+ return [...functionEntries];
524
528
  }
525
529
  };
526
530
  const listeners = {
527
531
  ":function[type]": onFunctionEnter,
528
532
  ":function[type]:exit": onFunctionExit,
529
533
  "ArrowFunctionExpression[type][body.type!='BlockStatement']"() {
530
- const maybeCurrentFn = getCurrentFunction();
531
- if (O.isNone(maybeCurrentFn)) return;
532
- const [_key, currentFn, _isComponent, hookCalls] = maybeCurrentFn.value;
533
- const { body } = currentFn;
534
- const isComponent = hasNoneOrValidComponentName(currentFn, context) && JSX4.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(currentFn, context, hint);
534
+ const mbEntry = getCurrentFunction();
535
+ if (O.isNone(mbEntry)) return;
536
+ const entry = mbEntry.value;
537
+ const { body } = entry.node;
538
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
535
539
  if (!isComponent) return;
536
- const initPath = AST9.getFunctionInitPath(currentFn);
537
- const id2 = getFunctionComponentIdentifier(currentFn, context);
540
+ const initPath = AST9.getFunctionInitPath(entry.node);
541
+ const id2 = getFunctionComponentIdentifier(entry.node, context);
538
542
  const name = O.flatMapNullable(id2, getComponentNameFromIdentifier);
539
- const key = uid_exports.next().toString();
543
+ const key = getId();
540
544
  components.set(key, {
541
545
  _: key,
542
546
  id: id2,
543
547
  kind: "function",
544
548
  name,
545
- node: currentFn,
549
+ node: entry.node,
546
550
  displayName: O.none(),
547
551
  flag: getComponentFlag(initPath),
548
552
  hint,
549
- hookCalls,
553
+ hookCalls: entry.hookCalls,
550
554
  initPath
551
555
  });
552
556
  },
553
557
  "AssignmentExpression[type][operator='='][left.type='MemberExpression'][left.property.name='displayName']"(node) {
554
- if (node.type !== AST_NODE_TYPES.AssignmentExpression) return;
555
558
  const { left, right } = node;
556
- if (left.type !== AST_NODE_TYPES.MemberExpression) return;
557
- const maybeComponentName = match(left.object).with({ type: AST_NODE_TYPES.Identifier }, (n) => O.some(n.name)).otherwise(O.none);
558
- if (O.isNone(maybeComponentName)) return;
559
- const component = Array.from(components.values()).findLast(({ name }) => O.exists(name, (n) => n === maybeComponentName.value));
559
+ const mbComponentName = match(left.object).with({ type: AST_NODE_TYPES.Identifier }, (n) => O.some(n.name)).otherwise(O.none);
560
+ if (O.isNone(mbComponentName)) return;
561
+ const componentName = mbComponentName.value;
562
+ const component = Array.from(components.values()).findLast(({ name }) => O.exists(name, (n) => n === componentName));
560
563
  if (!component) return;
561
564
  components.set(component._, {
562
565
  ...component,
@@ -565,34 +568,33 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT) {
565
568
  },
566
569
  "CallExpression[type]:exit"(node) {
567
570
  if (!isReactHookCall(node)) return;
568
- const maybeCurrentFn = getCurrentFunction();
569
- if (O.isNone(maybeCurrentFn)) return;
570
- const [key, currentFn, isComponent, hookCalls] = maybeCurrentFn.value;
571
- functionStack.pop();
572
- functionStack.push([key, currentFn, isComponent, [...hookCalls, node]]);
571
+ const mbEntry = getCurrentFunction();
572
+ if (O.isNone(mbEntry)) return;
573
+ const entry = mbEntry.value;
574
+ functionEntries.pop();
575
+ functionEntries.push({ ...entry, hookCalls: [...entry.hookCalls, node] });
573
576
  },
574
577
  "ReturnStatement[type]"(node) {
575
- const maybeCurrentFn = getCurrentFunction();
576
- if (O.isNone(maybeCurrentFn)) return;
577
- const [key, currentFn, isKnown, hookCalls] = maybeCurrentFn.value;
578
- if (isKnown) return;
579
- const isComponent = hasNoneOrValidComponentName(currentFn, context) && JSX4.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(currentFn, context, hint);
578
+ const mbEntry = getCurrentFunction();
579
+ if (O.isNone(mbEntry)) return;
580
+ const entry = mbEntry.value;
581
+ const isComponent = hasNoneOrValidComponentName(entry.node, context) && JSX4.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(entry.node, context, hint);
580
582
  if (!isComponent) return;
581
- functionStack.pop();
582
- functionStack.push([key, currentFn, true, []]);
583
- const initPath = AST9.getFunctionInitPath(currentFn);
584
- const id2 = getFunctionComponentIdentifier(currentFn, context);
583
+ functionEntries.pop();
584
+ functionEntries.push({ ...entry, isComponent });
585
+ const initPath = AST9.getFunctionInitPath(entry.node);
586
+ const id2 = getFunctionComponentIdentifier(entry.node, context);
585
587
  const name = O.flatMapNullable(id2, getComponentNameFromIdentifier);
586
- components.set(key, {
587
- _: key,
588
+ components.set(entry.key, {
589
+ _: entry.key,
588
590
  id: id2,
589
591
  kind: "function",
590
592
  name,
591
- node: currentFn,
593
+ node: entry.node,
592
594
  displayName: O.none(),
593
595
  flag: getComponentFlag(initPath),
594
596
  hint,
595
- hookCalls,
597
+ hookCalls: entry.hookCalls,
596
598
  initPath
597
599
  });
598
600
  }
@@ -603,10 +605,10 @@ function isSetupFunction(node) {
603
605
  return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && node.parent.callee.type === AST_NODE_TYPES.Identifier && node.parent.arguments.at(0) === node && isUseEffectCallLoose(node.parent);
604
606
  }
605
607
  function isCleanupFunction(node) {
606
- const nearestRet = O.getOrNull(AST9.traverseUpGuard(node, AST9.is(AST_NODE_TYPES.ReturnStatement)));
608
+ const nearestRet = O.getOrNull(AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.ReturnStatement)));
607
609
  if (!nearestRet) return false;
608
- const nearestFunction = O.getOrNull(AST9.traverseUpGuard(node, AST9.isFunction));
609
- const nearestFunctionOfRet = O.getOrNull(AST9.traverseUpGuard(nearestRet, AST9.isFunction));
610
+ const nearestFunction = O.getOrNull(AST9.findParentNodeGuard(node, AST9.isFunction));
611
+ const nearestFunctionOfRet = O.getOrNull(AST9.findParentNodeGuard(nearestRet, AST9.isFunction));
610
612
  if (!nearestFunction || !nearestFunctionOfRet) return false;
611
613
  return nearestFunction === nearestFunctionOfRet && isSetupFunction(nearestFunction);
612
614
  }
@@ -630,7 +632,7 @@ function isDeclaredInRenderPropLoose(node) {
630
632
  return true;
631
633
  }
632
634
  return F.pipe(
633
- AST9.traverseUpGuard(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer)),
635
+ AST9.findParentNodeGuard(node, AST9.is(AST_NODE_TYPES.JSXExpressionContainer)),
634
636
  O.flatMapNullable((c) => c.parent),
635
637
  O.filter(AST9.is(AST_NODE_TYPES.JSXAttribute)),
636
638
  O.flatMapNullable((a) => a.name),
@@ -662,4 +664,4 @@ function isThisSetState(node) {
662
664
  return callee.type === AST_NODE_TYPES.MemberExpression && AST9.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
663
665
  }
664
666
 
665
- export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementRepresentName, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, uid_exports as uid, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
667
+ export { DEFAULT_COMPONENT_HINT, ERClassComponentFlag, ERComponentHint, ERFunctionComponentFlag, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getElementRepresentName, getFunctionComponentIdentifier, getId, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCleanupFunction, isCloneElement, isCloneElementCall, isComponentDidMount, isComponentDidMountFunction, isComponentName, isComponentWillUnmount, isComponentWillUnmountFunction, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfRenderMethod, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderPropLoose, isSetupFunction, 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.23.1",
3
+ "version": "1.23.2-beta.6",
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": {
@@ -33,17 +33,17 @@
33
33
  "./package.json"
34
34
  ],
35
35
  "dependencies": {
36
- "@typescript-eslint/scope-manager": "^8.19.0",
37
- "@typescript-eslint/type-utils": "^8.19.0",
38
- "@typescript-eslint/types": "^8.19.0",
39
- "@typescript-eslint/utils": "^8.19.0",
36
+ "@typescript-eslint/scope-manager": "^8.19.1",
37
+ "@typescript-eslint/type-utils": "^8.19.1",
38
+ "@typescript-eslint/types": "^8.19.1",
39
+ "@typescript-eslint/utils": "^8.19.1",
40
40
  "ts-pattern": "^5.6.0",
41
- "@eslint-react/ast": "1.23.1",
42
- "@eslint-react/eff": "1.23.1",
43
- "@eslint-react/jsx": "1.23.1",
44
- "@eslint-react/types": "1.23.1",
45
- "@eslint-react/shared": "1.23.1",
46
- "@eslint-react/var": "1.23.1"
41
+ "@eslint-react/ast": "1.23.2-beta.6",
42
+ "@eslint-react/eff": "1.23.2-beta.6",
43
+ "@eslint-react/jsx": "1.23.2-beta.6",
44
+ "@eslint-react/shared": "1.23.2-beta.6",
45
+ "@eslint-react/types": "1.23.2-beta.6",
46
+ "@eslint-react/var": "1.23.2-beta.6"
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.3.5",