Socket
Book a DemoSign in
Socket

@eslint-react/core

Package Overview
Dependencies
Maintainers
1
Versions
2401
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eslint-react/core - npm Package Compare versions

Comparing version
3.0.0
to
4.0.0-beta.0
+25
-352
dist/index.d.ts
import * as ast from "@eslint-react/ast";
import { TSESTree } from "@typescript-eslint/types";
import { RegExpLike, RuleContext } from "@eslint-react/shared";
import { Scope } from "@typescript-eslint/scope-manager";
import { ESLintUtils, TSESTree as TSESTree$1 } from "@typescript-eslint/utils";
import { Scope } from "@typescript-eslint/scope-manager";
import * as typescript from "typescript";

@@ -40,4 +39,4 @@ //#region src/api/find-import-source.d.ts

type ReturnType = {
(context: RuleContext, node: null | TSESTree.Node): node is TSESTree.Identifier | TSESTree.MemberExpression;
(context: RuleContext): (node: null | TSESTree.Node) => node is TSESTree.MemberExpression | TSESTree.Identifier;
(context: RuleContext, node: null | TSESTree.Node): boolean;
(context: RuleContext): (node: null | TSESTree.Node) => boolean;
};

@@ -96,10 +95,10 @@ }

declare const ComponentDetectionHint: {
readonly DoNotIncludeFunctionDefinedAsClassMethod: bigint;
readonly DoNotIncludeFunctionDefinedAsClassProperty: bigint;
readonly DoNotIncludeFunctionDefinedAsObjectMethod: bigint;
readonly DoNotIncludeFunctionDefinedAsArrayExpressionElement: bigint;
readonly DoNotIncludeFunctionDefinedAsArrayPatternElement: bigint;
readonly DoNotIncludeFunctionDefinedAsArbitraryCallExpressionCallback: bigint;
readonly DoNotIncludeFunctionDefinedAsArrayFlatMapCallback: bigint;
readonly DoNotIncludeFunctionDefinedAsArrayMapCallback: bigint;
readonly DoNotIncludeFunctionDefinedInArrayExpression: bigint;
readonly DoNotIncludeFunctionDefinedInArrayPattern: bigint;
readonly DoNotIncludeFunctionDefinedOnClassMethod: bigint;
readonly DoNotIncludeFunctionDefinedOnClassProperty: bigint;
readonly DoNotIncludeFunctionDefinedOnObjectMethod: bigint;
readonly None: 0n;

@@ -190,3 +189,3 @@ readonly DoNotIncludeJsxWithNullValue: bigint;

*/
kind: "function-component";
kind: "component";
/**

@@ -272,6 +271,3 @@ * The AST node of the function

//#region src/component/component-collector.d.ts
interface FunctionEntry$1 extends FunctionComponentSemanticNode {
isComponentDefinition: boolean;
}
declare namespace useComponentCollector {
declare namespace getComponentCollector {
type Options = {

@@ -282,6 +278,4 @@ collectDisplayName?: boolean;

type ReturnType = {
ctx: {
api: {
getAllComponents: (node: TSESTree.Program) => FunctionComponentSemanticNode[];
getCurrentEntries: () => FunctionEntry$1[];
getCurrentEntry: () => FunctionEntry$1 | null;
};

@@ -292,13 +286,13 @@ visitor: ESLintUtils.RuleListener;

/**
* Get a ctx and visitor object for the rule to collect function components
* Get a api and visitor object for the rule to collect function components
* @param context The ESLint rule context
* @param options The options to use
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
declare function useComponentCollector(context: RuleContext, options?: useComponentCollector.Options): useComponentCollector.ReturnType;
declare function getComponentCollector(context: RuleContext, options?: getComponentCollector.Options): getComponentCollector.ReturnType;
//#endregion
//#region src/component/component-collector-legacy.d.ts
declare namespace useComponentCollectorLegacy {
declare namespace getComponentCollectorLegacy {
type ReturnType = {
ctx: {
api: {
getAllComponents: (node: TSESTree$1.Program) => ClassComponentSemanticNode[];

@@ -310,7 +304,7 @@ };

/**
* Get a ctx and visitor object for the rule to collect class componentss
* Get a api and visitor object for the rule to collect class componentss
* @param context The ESLint rule context
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
declare function useComponentCollectorLegacy(context: RuleContext): useComponentCollectorLegacy.ReturnType;
declare function getComponentCollectorLegacy(context: RuleContext): getComponentCollectorLegacy.ReturnType;
//#endregion

@@ -538,12 +532,6 @@ //#region src/component/component-detection-legacy.d.ts

//#region src/hook/hook-collector.d.ts
type FunctionEntry = {
key: string;
node: ast.TSESTreeFunction;
};
declare namespace useHookCollector {
declare namespace getHookCollector {
type ReturnType = {
ctx: {
api: {
getAllHooks(node: TSESTree$1.Program): HookSemanticNode[];
getCurrentEntries(): FunctionEntry[];
getCurrentEntry(): FunctionEntry | null;
};

@@ -554,7 +542,7 @@ visitor: ESLintUtils.RuleListener;

/**
* Get a ctx and visitor object for the rule to collect hooks
* Get a api and visitor object for the rule to collect hooks
* @param context The ESLint rule context
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
declare function useHookCollector(context: RuleContext): useHookCollector.ReturnType;
declare function getHookCollector(context: RuleContext): getHookCollector.ReturnType;
//#endregion

@@ -633,317 +621,2 @@ //#region src/hook/hook-id.d.ts

//#endregion
//#region src/jsx/jsx-attribute-value.d.ts
/**
* Represents possible JSX attribute value types that can be resolved
*/
type JsxAttributeValue = {
kind: "missing";
node: TSESTree.JSXEmptyExpression;
toStatic(): null;
} | {
kind: "boolean";
toStatic(): true;
} | {
kind: "element";
node: TSESTree.JSXElement;
toStatic(): null;
} | {
kind: "literal";
node: TSESTree.Literal;
toStatic(): TSESTree.Literal["value"];
} | {
kind: "expression";
node: TSESTree.JSXExpressionContainer["expression"];
toStatic(): unknown;
} | {
kind: "spreadProps";
getProperty(name: string): unknown;
node: TSESTree.JSXSpreadAttribute["argument"];
toStatic(): null;
} | {
kind: "spreadChild";
getChildren(at: number): unknown;
node: TSESTree.JSXSpreadChild["expression"];
toStatic(): null;
};
//#endregion
//#region src/jsx/jsx-config.d.ts
declare const JsxEmit: {
readonly None: 0;
readonly Preserve: 1;
readonly React: 2;
readonly ReactNative: 3;
readonly ReactJSX: 4;
readonly ReactJSXDev: 5;
};
interface JsxConfig {
jsx?: number;
jsxFactory?: string;
jsxFragmentFactory?: string;
jsxImportSource?: string;
}
/**
* Get JsxConfig from the rule context by reading compiler options
* @param context The RuleContext
* @returns JsxConfig derived from compiler options
*/
declare function getJsxConfigFromContext(context: RuleContext): {
jsx: 4 | typescript.JsxEmit;
jsxFactory: string;
jsxFragmentFactory: string;
jsxImportSource: string;
};
/**
* Get JsxConfig from pragma comments (annotations) in the source code
* @param context The RuleContext
* @returns JsxConfig derived from pragma comments
*/
declare function getJsxConfigFromAnnotation(context: RuleContext): JsxConfig;
//#endregion
//#region src/jsx/jsx-detection.d.ts
/**
* BitFlags for configuring JSX detection behavior
*/
type JsxDetectionHint = bigint;
declare const JsxDetectionHint: {
readonly None: 0n;
readonly DoNotIncludeJsxWithNullValue: bigint;
readonly DoNotIncludeJsxWithNumberValue: bigint;
readonly DoNotIncludeJsxWithBigIntValue: bigint;
readonly DoNotIncludeJsxWithStringValue: bigint;
readonly DoNotIncludeJsxWithBooleanValue: bigint;
readonly DoNotIncludeJsxWithUndefinedValue: bigint;
readonly DoNotIncludeJsxWithEmptyArrayValue: bigint;
readonly DoNotIncludeJsxWithCreateElementValue: bigint;
readonly RequireAllArrayElementsToBeJsx: bigint;
readonly RequireBothSidesOfLogicalExpressionToBeJsx: bigint;
readonly RequireBothBranchesOfConditionalExpressionToBeJsx: bigint;
};
/**
* Default JSX detection configuration
* Skips undefined and boolean literals (common in React)
*/
declare const DEFAULT_JSX_DETECTION_HINT: bigint;
/**
* Determine if a node represents JSX-like content based on heuristics
* Supports configuration through hint flags to customize detection behavior
*
* @param context The rule context with scope lookup capability
* @param node The AST node to analyze
* @param hint The configuration flags to adjust detection behavior
* @returns boolean Whether the node is considered JSX-like
*/
declare function isJsxLike(context: RuleContext, node: TSESTree$1.Node | null, hint?: JsxDetectionHint): boolean;
//#endregion
//#region src/jsx/jsx-inspector.d.ts
/**
* A stateful helper that binds an ESLint `RuleContext` once and exposes
* ergonomic methods for the most common JSX inspection tasks that rules need.
*
* ### Typical usage inside a rule's `create` function
*
* ```ts
* export function create(context: RuleContext) {
* const jsx = JsxInspector.from(context);
*
* return defineRuleListener({
* JSXElement(node) {
* // element type
* const type = jsx.getElementType(node); // "div" | "React.Fragment" | …
*
* // attribute lookup + value resolution in one step
* const val = jsx.getAttributeValue(node, "sandbox");
* if (typeof val?.getStatic() === "string") { … }
*
* // simple boolean checks
* if (jsx.isHostElement(node)) { … }
* if (jsx.isFragmentElement(node)) { … }
* if (jsx.hasAttribute(node, "key")) { … }
* },
* });
* }
* ```
*/
declare class JsxInspector {
#private;
readonly context: RuleContext;
/**
* Merged JSX configuration (tsconfig compiler options + pragma annotations).
* The result is lazily computed and cached for the lifetime of this inspector.
*/
get jsxConfig(): Required<JsxConfig>;
private constructor();
/**
* Walk **up** the AST from `node` to find the nearest ancestor that is a
* `JSXAttribute` and passes the optional `test` predicate.
* @param node The starting node for the search.
* @param test A predicate function to test each ancestor node.
*/
static findParentAttribute(node: TSESTree.Node, test?: (node: TSESTree.JSXAttribute) => boolean): TSESTree.JSXAttribute | null;
/**
* Create a new `JsxInspector` bound to the given rule context.
* @param context The ESLint rule context to bind to this inspector instance.
*/
static from(context: RuleContext): JsxInspector;
/**
* Whether the node is a `JSXText` or a `Literal` node.
* @param node The node to check.
*/
static isJsxText(node: TSESTree.Node | null): node is TSESTree.JSXText | TSESTree.Literal;
/**
* Find a JSX attribute (or spread attribute containing the property) by name
* on a given element.
*
* Returns the **last** matching attribute (to mirror React's behaviour where
* later props win), or `undefined` if not found.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to find (ex: `"className"`).
*/
findAttribute(node: TSESTree.JSXElement, name: string): ast.TSESTreeJSXAttributeLike | undefined;
/**
* Get the stringified name of a `JSXAttribute` node
* (ex: `"className"`, `"aria-label"`, `"xml:space"`).
* @param node The `JSXAttribute` node to extract the name from.
* @returns The stringified name of the attribute.
*/
getAttributeName(node: TSESTree.JSXAttribute): string;
/**
* Resolve the static value of an attribute, automatically handling the
* `spreadProps` case by extracting the named property.
*
* This eliminates the repetitive pattern:
* ```ts
* const v = core.resolveJsxAttributeValue(ctx, attr);
* const s = v.kind === "spreadProps" ? v.getProperty(name) : v.toStatic();
* ```
*
* Returns `undefined` when the attribute is not present or its value
* cannot be statically determined.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to resolve (ex: `"className"`).
* @returns The static value of the attribute, or `undefined` if not found or not statically resolvable.
*/
getAttributeStaticValue(node: TSESTree.JSXElement, name: string): unknown;
/**
* **All-in-one helper** – find an attribute by name on an element *and*
* resolve its value in a single call.
*
* Returns `undefined` when the attribute is not present.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to find and resolve (ex: `"className"`).
* @returns A descriptor of the attribute's value that can be further inspected, or `undefined` if the attribute is not found.
*/
getAttributeValue(node: TSESTree.JSXElement, name: string): JsxAttributeValue | undefined;
/**
* Get the **self name** (last segment) of a JSX element type.
*
* - `<Foo.Bar.Baz>` → `"Baz"`
* - `<div>` → `"div"`
* - `<></>` → `""`
* @param node The JSX element or fragment to extract the self name from.
*/
getElementSelfName(node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
/**
* Get the string representation of a JSX element's type.
*
* - `<div>` → `"div"`
* - `<Foo.Bar>` → `"Foo.Bar"`
* - `<React.Fragment>` → `"React.Fragment"`
* - `<></>` (JSXFragment) → `""`
* @param node The JSX element or fragment to extract the type from.
*/
getElementType(node: TSESTree.JSXElement | TSESTree.JSXFragment): string;
/**
* Shorthand: check whether an attribute exists on the element.
* @param node The JSX element to check for the attribute.
* @param name The name of the attribute to check for (ex: `"className"`).
* @returns `true` if the attribute exists on the element, `false` otherwise.
*/
hasAttribute(node: TSESTree.JSXElement, name: string): boolean;
/**
* Whether the node is a React **Fragment** element (either `<Fragment>` /
* `<React.Fragment>` or the shorthand `<>` syntax).
*
* The check honours the configured `jsxFragmentFactory`.
* @param node The node to check.
*/
isFragmentElement(node: TSESTree.Node): node is TSESTree.JSXElement | TSESTree.JSXFragment;
/**
* Whether the node is a **host** (intrinsic / DOM) element – i.e. its tag
* name starts with a lowercase letter.
* @param node The node to check.
*/
isHostElement(node: TSESTree.Node): node is TSESTree.JSXElement;
/**
* Resolve the *value* of a JSX attribute (or spread attribute) into a
* descriptor that can be inspected further.
*
* See {@link JsxAttributeValue} for the full set of `kind` discriminants.
* @param attribute The attribute node to resolve the value of.
* @returns A descriptor of the attribute's value that can be further inspected.
*/
resolveAttributeValue(attribute: ast.TSESTreeJSXAttributeLike): {
readonly kind: "boolean";
readonly toStatic: () => true;
readonly node?: never;
readonly getChildren?: never;
} | {
readonly kind: "literal";
readonly node: TSESTree.BigIntLiteral | TSESTree.BooleanLiteral | TSESTree.NullLiteral | TSESTree.NumberLiteral | TSESTree.RegExpLiteral | TSESTree.StringLiteral;
readonly toStatic: () => string | number | bigint | boolean | RegExp | null;
readonly getChildren?: never;
} | {
readonly kind: "missing";
readonly node: TSESTree.JSXEmptyExpression;
readonly toStatic: () => null;
readonly getChildren?: never;
} | {
readonly kind: "expression";
readonly node: TSESTree.Expression;
readonly toStatic: () => unknown;
readonly getChildren?: never;
} | {
readonly kind: "element";
readonly node: TSESTree.JSXElement;
readonly toStatic: () => null;
readonly getChildren?: never;
} | {
readonly kind: "spreadChild";
readonly node: TSESTree.JSXEmptyExpression | TSESTree.Expression;
readonly toStatic: () => null;
readonly getChildren: (_at: number) => null;
} | {
readonly kind: "spreadProps";
readonly node: TSESTree.Expression;
readonly toStatic: () => null;
readonly getProperty: (name: string) => unknown;
};
}
//#endregion
//#region src/ref/ref-id.d.ts
declare function isRefId(node: TSESTree.Expression | TSESTree.PrivateIdentifier): boolean;
//#endregion
//#region src/ref/ref-init.d.ts
/**
* Check if the variable with the given name is initialized or derived from a ref
* @param name The variable name
* @param initialScope The initial scope
* @returns True if the variable is derived from a ref, false otherwise
*/
declare function isInitializedFromRef(name: string, initialScope: Scope): boolean;
/**
* Get the init expression of a ref variable
* @param name The variable name
* @param initialScope The initial scope
* @returns The init expression node if the variable is derived from a ref, or null otherwise
*/
declare function getRefInit(name: string, initialScope: Scope): TSESTree$1.Expression | null;
//#endregion
//#region src/ref/ref-name.d.ts
/**
* Check if a given name corresponds to a ref name
* @param name The name to check
* @returns True if the name is "ref" or ends with "Ref"
*/
declare function isRefLikeName(name: string): boolean;
//#endregion
export { ClassComponentSemanticNode, ClientFunctionSemanticNode, ComponentDetectionHint, ComponentFlag, ComponentSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, FunctionComponentSemanticNode, FunctionKind, FunctionSemanticNode, HookSemanticNode, JsxAttributeValue, JsxConfig, JsxDetectionHint, JsxEmit, JsxInspector, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, findImportSource, getComponentFlagFromInitPath, getFunctionComponentId, getJsxConfigFromAnnotation, getJsxConfigFromContext, getRefInit, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isJsxLike, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefId, isRefLikeName, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
export { ClassComponentSemanticNode, ClientFunctionSemanticNode, ComponentDetectionHint, ComponentFlag, ComponentSemanticNode, DEFAULT_COMPONENT_DETECTION_HINT, FunctionComponentSemanticNode, FunctionKind, FunctionSemanticNode, HookSemanticNode, REACT_BUILTIN_HOOK_NAMES, SemanticFunc, SemanticNode, ServerFunctionSemanticNode, findImportSource, getComponentCollector, getComponentCollectorLegacy, getComponentFlagFromInitPath, getFunctionComponentId, getHookCollector, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall };
import * as ast from "@eslint-react/ast";
import { AST_NODE_TYPES } from "@typescript-eslint/types";
import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
import { findVariable } from "@typescript-eslint/utils/ast-utils";
import { P, match } from "ts-pattern";
import { IdGenerator, RE_ANNOTATION_JSX, RE_ANNOTATION_JSX_FRAG, RE_ANNOTATION_JSX_IMPORT_SOURCE, RE_ANNOTATION_JSX_RUNTIME, RE_COMPONENT_NAME, RE_COMPONENT_NAME_LOOSE } from "@eslint-react/shared";
import { resolve } from "@eslint-react/var";
import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from "@typescript-eslint/utils";
import { JsxDetectionHint, isJsxLike } from "@eslint-react/jsx";
import { IdGenerator, RE_COMPONENT_NAME, RE_COMPONENT_NAME_LOOSE } from "@eslint-react/shared";

@@ -160,8 +159,2 @@ //#region ../../.pkgs/eff/dist/index.js

const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
function getOrElseUpdate(map, key, callback) {
if (map.has(key)) return map.get(key);
const value = callback();
map.set(key, value);
return value;
}

@@ -268,3 +261,3 @@ //#endregion

if (node.type !== AST_NODE_TYPES.CallExpression) return false;
return isReactAPI(api)(context, node.callee);
return isReactAPI(api)(context, ast.getUnderlyingExpression(node.callee));
};

@@ -443,5 +436,5 @@ return dual(2, func);

if (node == null) return false;
const returnStatement = ast.findParentNode(node, ast.is(AST_NODE_TYPES.ReturnStatement));
const enclosingFunction = ast.findParentNode(node, ast.isFunction);
if (enclosingFunction !== ast.findParentNode(returnStatement, ast.isFunction)) return false;
const returnStatement = ast.findParent(node, ast.is(AST_NODE_TYPES.ReturnStatement));
const enclosingFunction = ast.findParent(node, ast.isFunction);
if (enclosingFunction !== ast.findParent(returnStatement, ast.isFunction)) return false;
return isUseEffectSetupCallback(enclosingFunction);

@@ -469,7 +462,7 @@ }

/**
* Get a ctx and visitor object for the rule to collect hooks
* Get a api and visitor object for the rule to collect hooks
* @param context The ESLint rule context
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
function useHookCollector(context) {
function getHookCollector(context) {
const hooks = /* @__PURE__ */ new Map();

@@ -490,3 +483,3 @@ const functionEntries = [];

key,
kind: "function",
kind: "hook",
name: ast.getFullyQualifiedName(id, getText),

@@ -504,9 +497,5 @@ directives: [],

return {
ctx: {
getAllHooks(node) {
return [...hooks.values()];
},
getCurrentEntries: () => functionEntries,
getCurrentEntry
},
api: { getAllHooks(node) {
return [...hooks.values()];
} },
visitor: {

@@ -526,439 +515,2 @@ ":function": onFunctionEnter,

//#endregion
//#region src/jsx/jsx-config.ts
const JsxEmit = {
None: 0,
Preserve: 1,
React: 2,
ReactNative: 3,
ReactJSX: 4,
ReactJSXDev: 5
};
/**
* Get JsxConfig from the rule context by reading compiler options
* @param context The RuleContext
* @returns JsxConfig derived from compiler options
*/
function getJsxConfigFromContext(context) {
const options = context.sourceCode.parserServices?.program?.getCompilerOptions() ?? {};
return {
jsx: options.jsx ?? JsxEmit.ReactJSX,
jsxFactory: options.jsxFactory ?? "React.createElement",
jsxFragmentFactory: options.jsxFragmentFactory ?? "React.Fragment",
jsxImportSource: options.jsxImportSource ?? "react"
};
}
const cache = /* @__PURE__ */ new WeakMap();
/**
* Get JsxConfig from pragma comments (annotations) in the source code
* @param context The RuleContext
* @returns JsxConfig derived from pragma comments
*/
function getJsxConfigFromAnnotation(context) {
return getOrElseUpdate(cache, context.sourceCode, () => {
const options = {};
if (!context.sourceCode.text.includes("@jsx")) return options;
let jsx, jsxFrag, jsxRuntime, jsxImportSource;
for (const comment of context.sourceCode.getAllComments().reverse()) {
const value = comment.value;
jsx ??= value.match(RE_ANNOTATION_JSX)?.[1];
jsxFrag ??= value.match(RE_ANNOTATION_JSX_FRAG)?.[1];
jsxRuntime ??= value.match(RE_ANNOTATION_JSX_RUNTIME)?.[1];
jsxImportSource ??= value.match(RE_ANNOTATION_JSX_IMPORT_SOURCE)?.[1];
}
if (jsx != null) options.jsxFactory = jsx;
if (jsxFrag != null) options.jsxFragmentFactory = jsxFrag;
if (jsxRuntime != null) options.jsx = jsxRuntime === "classic" ? JsxEmit.React : JsxEmit.ReactJSX;
if (jsxImportSource != null) options.jsxImportSource = jsxImportSource;
return options;
});
}
//#endregion
//#region src/jsx/jsx-detection.ts
const JsxDetectionHint = {
None: 0n,
DoNotIncludeJsxWithNullValue: 1n << 0n,
DoNotIncludeJsxWithNumberValue: 1n << 1n,
DoNotIncludeJsxWithBigIntValue: 1n << 2n,
DoNotIncludeJsxWithStringValue: 1n << 3n,
DoNotIncludeJsxWithBooleanValue: 1n << 4n,
DoNotIncludeJsxWithUndefinedValue: 1n << 5n,
DoNotIncludeJsxWithEmptyArrayValue: 1n << 6n,
DoNotIncludeJsxWithCreateElementValue: 1n << 7n,
RequireAllArrayElementsToBeJsx: 1n << 8n,
RequireBothSidesOfLogicalExpressionToBeJsx: 1n << 9n,
RequireBothBranchesOfConditionalExpressionToBeJsx: 1n << 10n
};
/**
* Default JSX detection configuration
* Skips undefined and boolean literals (common in React)
*/
const DEFAULT_JSX_DETECTION_HINT = 0n | JsxDetectionHint.DoNotIncludeJsxWithNumberValue | JsxDetectionHint.DoNotIncludeJsxWithBigIntValue | JsxDetectionHint.DoNotIncludeJsxWithBooleanValue | JsxDetectionHint.DoNotIncludeJsxWithStringValue | JsxDetectionHint.DoNotIncludeJsxWithUndefinedValue;
/**
* Determine if a node represents JSX-like content based on heuristics
* Supports configuration through hint flags to customize detection behavior
*
* @param context The rule context with scope lookup capability
* @param node The AST node to analyze
* @param hint The configuration flags to adjust detection behavior
* @returns boolean Whether the node is considered JSX-like
*/
function isJsxLike(context, node, hint = DEFAULT_JSX_DETECTION_HINT) {
if (node == null) return false;
if (ast.isJSX(node)) return true;
switch (node.type) {
case AST_NODE_TYPES.Literal:
switch (typeof node.value) {
case "boolean": return !(hint & JsxDetectionHint.DoNotIncludeJsxWithBooleanValue);
case "string": return !(hint & JsxDetectionHint.DoNotIncludeJsxWithStringValue);
case "number": return !(hint & JsxDetectionHint.DoNotIncludeJsxWithNumberValue);
case "bigint": return !(hint & JsxDetectionHint.DoNotIncludeJsxWithBigIntValue);
}
if (node.value == null) return !(hint & JsxDetectionHint.DoNotIncludeJsxWithNullValue);
return false;
case AST_NODE_TYPES.TemplateLiteral: return !(hint & JsxDetectionHint.DoNotIncludeJsxWithStringValue);
case AST_NODE_TYPES.ArrayExpression:
if (node.elements.length === 0) return !(hint & JsxDetectionHint.DoNotIncludeJsxWithEmptyArrayValue);
if (hint & JsxDetectionHint.RequireAllArrayElementsToBeJsx) return node.elements.every((n) => isJsxLike(context, n, hint));
return node.elements.some((n) => isJsxLike(context, n, hint));
case AST_NODE_TYPES.LogicalExpression:
if (hint & JsxDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx) return isJsxLike(context, node.left, hint) && isJsxLike(context, node.right, hint);
return isJsxLike(context, node.left, hint) || isJsxLike(context, node.right, hint);
case AST_NODE_TYPES.ConditionalExpression: {
function leftHasJSX(node) {
if (Array.isArray(node.consequent)) {
if (node.consequent.length === 0) return !(hint & JsxDetectionHint.DoNotIncludeJsxWithEmptyArrayValue);
if (hint & JsxDetectionHint.RequireAllArrayElementsToBeJsx) return node.consequent.every((n) => isJsxLike(context, n, hint));
return node.consequent.some((n) => isJsxLike(context, n, hint));
}
return isJsxLike(context, node.consequent, hint);
}
function rightHasJSX(node) {
return isJsxLike(context, node.alternate, hint);
}
if (hint & JsxDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx) return leftHasJSX(node) && rightHasJSX(node);
return leftHasJSX(node) || rightHasJSX(node);
}
case AST_NODE_TYPES.SequenceExpression: return isJsxLike(context, node.expressions.at(-1) ?? null, hint);
case AST_NODE_TYPES.CallExpression:
if (hint & JsxDetectionHint.DoNotIncludeJsxWithCreateElementValue) return false;
switch (node.callee.type) {
case AST_NODE_TYPES.Identifier: return node.callee.name === "createElement";
case AST_NODE_TYPES.MemberExpression: return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "createElement";
}
return false;
case AST_NODE_TYPES.Identifier:
if (node.name === "undefined") return !(hint & JsxDetectionHint.DoNotIncludeJsxWithUndefinedValue);
if (ast.isJSXTagNameExpression(node)) return true;
return isJsxLike(context, resolve(context, node), hint);
}
return false;
}
//#endregion
//#region src/jsx/jsx-stringify.ts
/**
* Incomplete but sufficient stringification of JSX nodes for common use cases
*
* @param node JSX node from TypeScript ESTree
* @returns String representation of the JSX node
*/
function stringifyJsx(node) {
switch (node.type) {
case AST_NODE_TYPES.JSXIdentifier: return node.name;
case AST_NODE_TYPES.JSXNamespacedName: return `${node.namespace.name}:${node.name.name}`;
case AST_NODE_TYPES.JSXMemberExpression: return `${stringifyJsx(node.object)}.${stringifyJsx(node.property)}`;
case AST_NODE_TYPES.JSXText: return node.value;
case AST_NODE_TYPES.JSXOpeningElement: return `<${stringifyJsx(node.name)}>`;
case AST_NODE_TYPES.JSXClosingElement: return `</${stringifyJsx(node.name)}>`;
case AST_NODE_TYPES.JSXOpeningFragment: return "<>";
case AST_NODE_TYPES.JSXClosingFragment: return "</>";
}
}
//#endregion
//#region src/jsx/jsx-inspector.ts
/**
* A stateful helper that binds an ESLint `RuleContext` once and exposes
* ergonomic methods for the most common JSX inspection tasks that rules need.
*
* ### Typical usage inside a rule's `create` function
*
* ```ts
* export function create(context: RuleContext) {
* const jsx = JsxInspector.from(context);
*
* return defineRuleListener({
* JSXElement(node) {
* // element type
* const type = jsx.getElementType(node); // "div" | "React.Fragment" | …
*
* // attribute lookup + value resolution in one step
* const val = jsx.getAttributeValue(node, "sandbox");
* if (typeof val?.getStatic() === "string") { … }
*
* // simple boolean checks
* if (jsx.isHostElement(node)) { … }
* if (jsx.isFragmentElement(node)) { … }
* if (jsx.hasAttribute(node, "key")) { … }
* },
* });
* }
* ```
*/
var JsxInspector = class JsxInspector {
context;
/**
* Merged JSX configuration (tsconfig compiler options + pragma annotations).
* The result is lazily computed and cached for the lifetime of this inspector.
*/
get jsxConfig() {
return this.#jsxConfig ??= {
...getJsxConfigFromContext(this.context),
...getJsxConfigFromAnnotation(this.context)
};
}
/**
* Lazily resolved & cached JSX configuration (merged from tsconfig +
* pragma annotations). Use {@link jsxConfig} to access.
*/
#jsxConfig;
constructor(context) {
this.context = context;
}
/**
* Walk **up** the AST from `node` to find the nearest ancestor that is a
* `JSXAttribute` and passes the optional `test` predicate.
* @param node The starting node for the search.
* @param test A predicate function to test each ancestor node.
*/
static findParentAttribute(node, test = () => true) {
const guard = (n) => {
return n.type === AST_NODE_TYPES.JSXAttribute && test(n);
};
return ast.findParentNode(node, guard);
}
/**
* Create a new `JsxInspector` bound to the given rule context.
* @param context The ESLint rule context to bind to this inspector instance.
*/
static from(context) {
return new JsxInspector(context);
}
/**
* Whether the node is a `JSXText` or a `Literal` node.
* @param node The node to check.
*/
static isJsxText(node) {
if (node == null) return false;
return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
}
/**
* Find a JSX attribute (or spread attribute containing the property) by name
* on a given element.
*
* Returns the **last** matching attribute (to mirror React's behaviour where
* later props win), or `undefined` if not found.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to find (ex: `"className"`).
*/
findAttribute(node, name) {
return node.openingElement.attributes.findLast((attr) => {
if (attr.type === AST_NODE_TYPES.JSXAttribute) return stringifyJsx(attr.name) === name;
switch (attr.argument.type) {
case AST_NODE_TYPES.Identifier: {
const initNode = resolve(this.context, attr.argument);
if (initNode?.type === AST_NODE_TYPES.ObjectExpression) return ast.findProperty(initNode.properties, name) != null;
return false;
}
case AST_NODE_TYPES.ObjectExpression: return ast.findProperty(attr.argument.properties, name) != null;
}
return false;
});
}
/**
* Get the stringified name of a `JSXAttribute` node
* (ex: `"className"`, `"aria-label"`, `"xml:space"`).
* @param node The `JSXAttribute` node to extract the name from.
* @returns The stringified name of the attribute.
*/
getAttributeName(node) {
return stringifyJsx(node.name);
}
/**
* Resolve the static value of an attribute, automatically handling the
* `spreadProps` case by extracting the named property.
*
* This eliminates the repetitive pattern:
* ```ts
* const v = core.resolveJsxAttributeValue(ctx, attr);
* const s = v.kind === "spreadProps" ? v.getProperty(name) : v.toStatic();
* ```
*
* Returns `undefined` when the attribute is not present or its value
* cannot be statically determined.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to resolve (ex: `"className"`).
* @returns The static value of the attribute, or `undefined` if not found or not statically resolvable.
*/
getAttributeStaticValue(node, name) {
const attr = this.findAttribute(node, name);
if (attr == null) return void 0;
const resolved = this.resolveAttributeValue(attr);
if (resolved.kind === "spreadProps") return resolved.getProperty(name);
return resolved.toStatic();
}
/**
* **All-in-one helper** – find an attribute by name on an element *and*
* resolve its value in a single call.
*
* Returns `undefined` when the attribute is not present.
* @param node The JSX element to search for the attribute.
* @param name The name of the attribute to find and resolve (ex: `"className"`).
* @returns A descriptor of the attribute's value that can be further inspected, or `undefined` if the attribute is not found.
*/
getAttributeValue(node, name) {
const attr = this.findAttribute(node, name);
if (attr == null) return void 0;
return this.resolveAttributeValue(attr);
}
/**
* Get the **self name** (last segment) of a JSX element type.
*
* - `<Foo.Bar.Baz>` → `"Baz"`
* - `<div>` → `"div"`
* - `<></>` → `""`
* @param node The JSX element or fragment to extract the self name from.
*/
getElementSelfName(node) {
return this.getElementType(node).split(".").at(-1) ?? "";
}
/**
* Get the string representation of a JSX element's type.
*
* - `<div>` → `"div"`
* - `<Foo.Bar>` → `"Foo.Bar"`
* - `<React.Fragment>` → `"React.Fragment"`
* - `<></>` (JSXFragment) → `""`
* @param node The JSX element or fragment to extract the type from.
*/
getElementType(node) {
if (node.type === AST_NODE_TYPES.JSXFragment) return "";
return stringifyJsx(node.openingElement.name);
}
/**
* Shorthand: check whether an attribute exists on the element.
* @param node The JSX element to check for the attribute.
* @param name The name of the attribute to check for (ex: `"className"`).
* @returns `true` if the attribute exists on the element, `false` otherwise.
*/
hasAttribute(node, name) {
return this.findAttribute(node, name) != null;
}
/**
* Whether the node is a React **Fragment** element (either `<Fragment>` /
* `<React.Fragment>` or the shorthand `<>` syntax).
*
* The check honours the configured `jsxFragmentFactory`.
* @param node The node to check.
*/
isFragmentElement(node) {
if (node.type === AST_NODE_TYPES.JSXFragment) return true;
if (node.type !== AST_NODE_TYPES.JSXElement) return false;
const fragment = this.jsxConfig.jsxFragmentFactory.split(".").at(-1) ?? "Fragment";
return this.getElementType(node).split(".").at(-1) === fragment;
}
/**
* Whether the node is a **host** (intrinsic / DOM) element – i.e. its tag
* name starts with a lowercase letter.
* @param node The node to check.
*/
isHostElement(node) {
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
}
/**
* Resolve the *value* of a JSX attribute (or spread attribute) into a
* descriptor that can be inspected further.
*
* See {@link JsxAttributeValue} for the full set of `kind` discriminants.
* @param attribute The attribute node to resolve the value of.
* @returns A descriptor of the attribute's value that can be further inspected.
*/
resolveAttributeValue(attribute) {
if (attribute.type === AST_NODE_TYPES.JSXAttribute) return this.#resolveJsxAttribute(attribute);
return this.#resolveJsxSpreadAttribute(attribute);
}
#resolveJsxAttribute(node) {
const scope = this.context.sourceCode.getScope(node);
if (node.value == null) return {
kind: "boolean",
toStatic() {
return true;
}
};
switch (node.value.type) {
case AST_NODE_TYPES.Literal: {
const staticValue = node.value.value;
return {
kind: "literal",
node: node.value,
toStatic() {
return staticValue;
}
};
}
case AST_NODE_TYPES.JSXExpressionContainer: {
const expr = node.value.expression;
if (expr.type === AST_NODE_TYPES.JSXEmptyExpression) return {
kind: "missing",
node: expr,
toStatic() {
return null;
}
};
return {
kind: "expression",
node: expr,
toStatic() {
return getStaticValue(expr, scope)?.value;
}
};
}
case AST_NODE_TYPES.JSXElement: return {
kind: "element",
node: node.value,
toStatic() {
return null;
}
};
case AST_NODE_TYPES.JSXSpreadChild:
node.value.expression;
return {
kind: "spreadChild",
node: node.value.expression,
toStatic() {
return null;
},
getChildren(_at) {
return null;
}
};
}
}
#resolveJsxSpreadAttribute(node) {
const scope = this.context.sourceCode.getScope(node);
return {
kind: "spreadProps",
node: node.argument,
toStatic() {
return null;
},
getProperty(name) {
return match(getStaticValue(node.argument, scope)?.value).with({ [name]: P.select(P.any) }, identity).otherwise(() => null);
}
};
}
};
//#endregion
//#region src/component/component-detection-legacy.ts

@@ -1194,10 +746,10 @@ /**

...JsxDetectionHint,
DoNotIncludeFunctionDefinedAsClassMethod: 1n << 11n,
DoNotIncludeFunctionDefinedAsClassProperty: 1n << 12n,
DoNotIncludeFunctionDefinedAsObjectMethod: 1n << 13n,
DoNotIncludeFunctionDefinedAsArrayExpressionElement: 1n << 14n,
DoNotIncludeFunctionDefinedAsArrayPatternElement: 1n << 15n,
DoNotIncludeFunctionDefinedAsArbitraryCallExpressionCallback: 1n << 18n,
DoNotIncludeFunctionDefinedAsArrayFlatMapCallback: 1n << 17n,
DoNotIncludeFunctionDefinedAsArrayMapCallback: 1n << 16n,
DoNotIncludeFunctionDefinedInArrayExpression: 1n << 15n,
DoNotIncludeFunctionDefinedInArrayPattern: 1n << 14n,
DoNotIncludeFunctionDefinedOnClassMethod: 1n << 12n,
DoNotIncludeFunctionDefinedOnClassProperty: 1n << 13n,
DoNotIncludeFunctionDefinedOnObjectMethod: 1n << 11n
DoNotIncludeFunctionDefinedAsArrayFlatMapCallback: 1n << 16n,
DoNotIncludeFunctionDefinedAsArrayMapCallback: 1n << 17n
};

@@ -1207,3 +759,3 @@ /**

*/
const DEFAULT_COMPONENT_DETECTION_HINT = 0n | ComponentDetectionHint.DoNotIncludeJsxWithBigIntValue | ComponentDetectionHint.DoNotIncludeJsxWithBooleanValue | ComponentDetectionHint.DoNotIncludeJsxWithNumberValue | ComponentDetectionHint.DoNotIncludeJsxWithStringValue | ComponentDetectionHint.DoNotIncludeJsxWithUndefinedValue | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArbitraryCallExpressionCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayFlatMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayExpression | ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayPattern | ComponentDetectionHint.RequireAllArrayElementsToBeJsx | ComponentDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx | ComponentDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx;
const DEFAULT_COMPONENT_DETECTION_HINT = 0n | ComponentDetectionHint.DoNotIncludeJsxWithBigIntValue | ComponentDetectionHint.DoNotIncludeJsxWithBooleanValue | ComponentDetectionHint.DoNotIncludeJsxWithNumberValue | ComponentDetectionHint.DoNotIncludeJsxWithStringValue | ComponentDetectionHint.DoNotIncludeJsxWithUndefinedValue | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArbitraryCallExpressionCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayExpressionElement | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayFlatMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayPatternElement | ComponentDetectionHint.RequireAllArrayElementsToBeJsx | ComponentDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx | ComponentDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx;
/**

@@ -1227,15 +779,15 @@ * Determine if a function node represents a valid React component definition

case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property && parent.parent.type === AST_NODE_TYPES.ObjectExpression:
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedOnObjectMethod) return false;
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedAsObjectMethod) return false;
break;
case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.MethodDefinition:
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedOnClassMethod) return false;
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedAsClassMethod) return false;
break;
case ast.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(node) && parent.type === AST_NODE_TYPES.Property:
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedOnClassProperty) return false;
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedAsClassProperty) return false;
break;
case parent.type === AST_NODE_TYPES.ArrayPattern:
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayPattern) return false;
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayPatternElement) return false;
break;
case parent.type === AST_NODE_TYPES.ArrayExpression:
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayExpression) return false;
if (hint & ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayExpressionElement) return false;
break;

@@ -1252,3 +804,3 @@ case parent.type === AST_NODE_TYPES.CallExpression && parent.callee.type === AST_NODE_TYPES.MemberExpression && parent.callee.property.type === AST_NODE_TYPES.Identifier && parent.callee.property.name === "map":

}
const significantParent = ast.findParentNode(node, ast.isOneOf([
const significantParent = ast.findParent(node, ast.isOneOf([
AST_NODE_TYPES.JSXExpressionContainer,

@@ -1291,10 +843,10 @@ AST_NODE_TYPES.ArrowFunctionExpression,

//#region src/component/component-collector.ts
const idGen$1 = new IdGenerator("function-component:");
const idGen$1 = new IdGenerator("component:");
/**
* Get a ctx and visitor object for the rule to collect function components
* Get a api and visitor object for the rule to collect function components
* @param context The ESLint rule context
* @param options The options to use
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
function useComponentCollector(context, options = {}) {
function getComponentCollector(context, options = {}) {
const { collectDisplayName = false, hint = DEFAULT_COMPONENT_DETECTION_HINT } = options;

@@ -1307,3 +859,3 @@ const functionEntries = [];

const key = idGen$1.next();
const exp = ast.findParentNode(node, (n) => n.type === AST_NODE_TYPES.ExportDefaultDeclaration);
const exp = ast.findParent(node, (n) => n.type === AST_NODE_TYPES.ExportDefaultDeclaration);
const isExportDefault = exp != null;

@@ -1318,3 +870,3 @@ const isExportDefaultDeclaration = exp != null && ast.getUnderlyingExpression(exp.declaration) === node;

key,
kind: "function-component",
kind: "component",
name,

@@ -1341,11 +893,5 @@ directives,

return {
ctx: {
getAllComponents(node) {
return [...components.values()];
},
getCurrentEntries() {
return [...functionEntries];
},
getCurrentEntry
},
api: { getAllComponents(node) {
return [...components.values()];
} },
visitor: {

@@ -1397,9 +943,9 @@ ":function": onFunctionEnter,

/**
* Get a ctx and visitor object for the rule to collect class componentss
* Get a api and visitor object for the rule to collect class componentss
* @param context The ESLint rule context
* @returns The ctx and visitor of the collector
* @returns The api and visitor of the collector
*/
function useComponentCollectorLegacy(context) {
function getComponentCollectorLegacy(context) {
const components = /* @__PURE__ */ new Map();
const ctx = { getAllComponents(node) {
const api = { getAllComponents(node) {
return [...components.values()];

@@ -1427,3 +973,3 @@ } };

return {
ctx,
api,
visitor: {

@@ -1437,49 +983,2 @@ ClassDeclaration: collect,

//#endregion
//#region src/ref/ref-name.ts
/**
* Check if a given name corresponds to a ref name
* @param name The name to check
* @returns True if the name is "ref" or ends with "Ref"
*/
function isRefLikeName(name) {
return name === "ref" || name.endsWith("Ref");
}
//#endregion
//#region src/ref/ref-id.ts
function isRefId(node) {
return node.type === AST_NODE_TYPES.Identifier && isRefLikeName(node.name);
}
//#endregion
//#region src/ref/ref-init.ts
/**
* Check if the variable with the given name is initialized or derived from a ref
* @param name The variable name
* @param initialScope The initial scope
* @returns True if the variable is derived from a ref, false otherwise
*/
function isInitializedFromRef(name, initialScope) {
return getRefInit(name, initialScope) != null;
}
/**
* Get the init expression of a ref variable
* @param name The variable name
* @param initialScope The initial scope
* @returns The init expression node if the variable is derived from a ref, or null otherwise
*/
function getRefInit(name, initialScope) {
for (const { node } of findVariable(initialScope, name)?.defs ?? []) {
if (node.type !== AST_NODE_TYPES$1.VariableDeclarator) continue;
const init = node.init;
if (init == null) continue;
switch (true) {
case init.type === AST_NODE_TYPES$1.MemberExpression && init.object.type === AST_NODE_TYPES$1.Identifier && isRefLikeName(init.object.name): return init;
case init.type === AST_NODE_TYPES$1.CallExpression && isUseRefCall(init): return init;
}
}
return null;
}
//#endregion
export { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JsxDetectionHint, JsxEmit, JsxInspector, REACT_BUILTIN_HOOK_NAMES, findImportSource, getComponentFlagFromInitPath, getFunctionComponentId, getJsxConfigFromAnnotation, getJsxConfigFromContext, getRefInit, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isInitializedFromRef, isJsxLike, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRefId, isRefLikeName, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
export { ComponentDetectionHint, ComponentFlag, DEFAULT_COMPONENT_DETECTION_HINT, REACT_BUILTIN_HOOK_NAMES, findImportSource, getComponentCollector, getComponentCollectorLegacy, getComponentFlagFromInitPath, getFunctionComponentId, getHookCollector, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDefinition, isComponentDidCatch, isComponentDidMount, isComponentDidMountCallback, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUnmountCallback, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isComponentWrapperCallback, isComponentWrapperCallbackLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isForwardRef, isForwardRefCall, isFunctionWithLooseComponentName, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHook, isHookCall, isHookCallWithName, isHookId, isHookName, isInitializedFromReact, isInitializedFromReactNative, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isRender, isRenderMethodCallback, isRenderMethodLike, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCleanupCallback, isUseEffectLikeCall, isUseEffectSetupCallback, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseStateLikeCall, isUseSyncExternalStoreCall, isUseTransitionCall };
+11
-10
{
"name": "@eslint-react/core",
"version": "3.0.0",
"version": "4.0.0-beta.0",
"description": "ESLint React's ESLint utility module for static analysis of React core APIs and patterns.",

@@ -33,14 +33,15 @@ "homepage": "https://github.com/Rel1cx/eslint-react",

"dependencies": {
"@typescript-eslint/scope-manager": "^8.57.0",
"@typescript-eslint/types": "^8.57.0",
"@typescript-eslint/utils": "^8.57.0",
"@typescript-eslint/scope-manager": "^8.57.2",
"@typescript-eslint/types": "^8.57.2",
"@typescript-eslint/utils": "^8.57.2",
"ts-pattern": "^5.9.0",
"@eslint-react/ast": "3.0.0",
"@eslint-react/shared": "3.0.0",
"@eslint-react/var": "3.0.0"
"@eslint-react/jsx": "4.0.0-beta.0",
"@eslint-react/ast": "4.0.0-beta.0",
"@eslint-react/shared": "4.0.0-beta.0",
"@eslint-react/var": "4.0.0-beta.0"
},
"devDependencies": {
"tsdown": "^0.21.2",
"@local/configs": "0.0.0",
"@local/eff": "3.0.0-beta.72"
"tsdown": "^0.21.4",
"@local/eff": "3.0.0-beta.72",
"@local/configs": "0.0.0"
},

@@ -47,0 +48,0 @@ "peerDependencies": {