UNPKG

eslint-plugin-react-hooks-extra

Version:

ESLint React's ESLint plugin for React Hooks related rules.

588 lines (569 loc) • 26.6 kB
//#region rolldown:runtime var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (all) => { let target = {}; for (var name$2 in all) __defProp(target, name$2, { get: all[name$2], enumerable: true }); return target; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let __eslint_react_shared = require("@eslint-react/shared"); __eslint_react_shared = __toESM(__eslint_react_shared); let __eslint_react_ast = require("@eslint-react/ast"); __eslint_react_ast = __toESM(__eslint_react_ast); let __eslint_react_core = require("@eslint-react/core"); __eslint_react_core = __toESM(__eslint_react_core); let __eslint_react_eff = require("@eslint-react/eff"); __eslint_react_eff = __toESM(__eslint_react_eff); let __eslint_react_var = require("@eslint-react/var"); __eslint_react_var = __toESM(__eslint_react_var); let __typescript_eslint_types = require("@typescript-eslint/types"); __typescript_eslint_types = __toESM(__typescript_eslint_types); let ts_pattern = require("ts-pattern"); ts_pattern = __toESM(ts_pattern); let __typescript_eslint_utils = require("@typescript-eslint/utils"); __typescript_eslint_utils = __toESM(__typescript_eslint_utils); //#region src/configs/recommended.ts var recommended_exports = __export({ name: () => name$1, rules: () => rules }); const name$1 = "react-hooks-extra/recommended"; const rules = { "react-hooks-extra/no-direct-set-state-in-use-effect": "warn", "react-hooks-extra/no-unnecessary-use-prefix": "warn", "react-hooks-extra/prefer-use-state-lazy-initialization": "warn" }; //#endregion //#region package.json var name = "eslint-plugin-react-hooks-extra"; var version = "1.53.1"; //#endregion //#region src/utils/create-rule.ts const createRule = __typescript_eslint_utils.ESLintUtils.RuleCreator((0, __eslint_react_shared.getDocsUrl)("hooks-extra")); //#endregion //#region src/utils/is-from-hook-call.ts function isFromHookCall(context, name$2, settings, predicate = __eslint_react_eff.constTrue) { const hookAlias = settings.additionalHooks[name$2] ?? []; return (topLevelId) => { const variable = __eslint_react_var.findVariable(topLevelId, context.sourceCode.getScope(topLevelId)); const variableNode = __eslint_react_var.getVariableInitNode(variable, 0); if (variableNode == null) return false; if (variableNode.type !== __typescript_eslint_types.AST_NODE_TYPES.CallExpression) return false; if (!__eslint_react_core.isReactHookCallWithNameAlias(context, name$2, hookAlias)(variableNode)) return false; return predicate(topLevelId, variableNode); }; } //#endregion //#region src/utils/is-from-use-state-call.ts function isFromUseStateCall(context, settings) { const predicate = (topLevelId, call) => { const { parent } = call; if (!("id" in parent) || parent.id?.type !== __typescript_eslint_types.AST_NODE_TYPES.ArrayPattern) return true; return parent.id.elements.findIndex((e) => e?.type === __typescript_eslint_types.AST_NODE_TYPES.Identifier && e.name === topLevelId.name) === 1; }; return isFromHookCall(context, "useState", settings, predicate); } //#endregion //#region src/utils/is-set-function-call.ts function isSetFunctionCall(context, settings) { const isIdFromUseStateCall = isFromUseStateCall(context, settings); return (node) => { switch (node.callee.type) { case __typescript_eslint_types.AST_NODE_TYPES.CallExpression: { const { callee } = node.callee; if (callee.type !== __typescript_eslint_types.AST_NODE_TYPES.MemberExpression) return false; if (!("name" in callee.object)) return false; const isAt = callee.property.type === __typescript_eslint_types.AST_NODE_TYPES.Identifier && callee.property.name === "at"; const [index] = node.callee.arguments; if (!isAt || index == null) return false; const indexScope = context.sourceCode.getScope(node); return __eslint_react_var.toStaticValue({ kind: "lazy", node: index, initialScope: indexScope }).value === 1 && isIdFromUseStateCall(callee.object); } case __typescript_eslint_types.AST_NODE_TYPES.Identifier: return isIdFromUseStateCall(node.callee); case __typescript_eslint_types.AST_NODE_TYPES.MemberExpression: { if (!("name" in node.callee.object)) return false; const property = node.callee.property; const propertyScope = context.sourceCode.getScope(node); return __eslint_react_var.toStaticValue({ kind: "lazy", node: property, initialScope: propertyScope }).value === 1 && isIdFromUseStateCall(node.callee.object); } default: return false; } }; } //#endregion //#region src/utils/is-then-call.ts function isThenCall(node) { return node.callee.type === __typescript_eslint_types.AST_NODE_TYPES.MemberExpression && node.callee.property.type === __typescript_eslint_types.AST_NODE_TYPES.Identifier && node.callee.property.name === "then"; } //#endregion //#region src/utils/is-variable-declarator-from-hook-call.ts function isVariableDeclaratorFromHookCall(node) { if (node.type !== __typescript_eslint_types.AST_NODE_TYPES.VariableDeclarator) return false; if (node.id.type !== __typescript_eslint_types.AST_NODE_TYPES.Identifier) return false; if (node.init?.type !== __typescript_eslint_types.AST_NODE_TYPES.CallExpression) return false; switch (node.init.callee.type) { case __typescript_eslint_types.AST_NODE_TYPES.Identifier: return __eslint_react_core.isReactHookName(node.init.callee.name); case __typescript_eslint_types.AST_NODE_TYPES.MemberExpression: return node.init.callee.property.type === __typescript_eslint_types.AST_NODE_TYPES.Identifier && __eslint_react_core.isReactHookName(node.init.callee.property.name); default: return false; } } //#endregion //#region src/hooks/use-no-direct-set-state-in-use-effect.ts function useNoDirectSetStateInUseEffect(context, options) { const { onViolation, useEffectKind } = options; const settings = (0, __eslint_react_shared.getSettingsFromContext)(context); const hooks = settings.additionalHooks; const getText = (n) => context.sourceCode.getText(n); const isUseEffectLikeCall = __eslint_react_core.isReactHookCallWithNameAlias(context, useEffectKind, hooks[useEffectKind]); const isUseStateCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useState", hooks.useState); const isUseMemoCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useMemo", hooks.useMemo); const isUseCallbackCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useCallback", hooks.useCallback); const isSetStateCall = isSetFunctionCall(context, settings); const isIdFromUseStateCall = isFromUseStateCall(context, settings); const functionEntries = []; const setupFunctionRef = { current: null }; const setupFunctionIdentifiers = []; const indFunctionCalls = []; const indSetStateCalls = /* @__PURE__ */ new WeakMap(); const indSetStateCallsInUseEffectArg0 = /* @__PURE__ */ new WeakMap(); const indSetStateCallsInUseEffectSetup = /* @__PURE__ */ new Map(); const indSetStateCallsInUseMemoOrCallback = /* @__PURE__ */ new WeakMap(); const onSetupFunctionEnter = (node) => { setupFunctionRef.current = node; }; const onSetupFunctionExit = (node) => { if (setupFunctionRef.current === node) setupFunctionRef.current = null; }; function isFunctionOfUseEffectSetup(node) { return node.parent?.type === __typescript_eslint_types.AST_NODE_TYPES.CallExpression && node.parent.callee !== node && isUseEffectLikeCall(node.parent); } function getCallName(node) { if (node.type === __typescript_eslint_types.AST_NODE_TYPES.CallExpression) return __eslint_react_ast.toString(node.callee, getText); return __eslint_react_ast.toString(node, getText); } function getCallKind(node) { return (0, ts_pattern.match)(node).when(isUseStateCall, () => "useState").when(isUseEffectLikeCall, () => useEffectKind).when(isSetStateCall, () => "setState").when(isThenCall, () => "then").otherwise(() => "other"); } function getFunctionKind(node) { const parent = __eslint_react_ast.findParentNode(node, (0, __eslint_react_eff.not)(__eslint_react_ast.isTypeExpression)) ?? node.parent; switch (true) { case node.async: case parent.type === __typescript_eslint_types.AST_NODE_TYPES.CallExpression && isThenCall(parent): return "deferred"; case node.type !== __typescript_eslint_types.AST_NODE_TYPES.FunctionDeclaration && parent.type === __typescript_eslint_types.AST_NODE_TYPES.CallExpression && parent.callee === node: return "immediate"; case isFunctionOfUseEffectSetup(node): return "setup"; default: return "other"; } } return { ":function"(node) { const kind = getFunctionKind(node); functionEntries.push({ kind, node }); if (kind === "setup") onSetupFunctionEnter(node); }, ":function:exit"(node) { const { kind } = functionEntries.at(-1) ?? {}; if (kind === "setup") onSetupFunctionExit(node); functionEntries.pop(); }, CallExpression(node) { const setupFunction = setupFunctionRef.current; const pEntry = functionEntries.at(-1); if (pEntry == null || pEntry.node.async) return; (0, ts_pattern.match)(getCallKind(node)).with("setState", () => { switch (true) { case pEntry.kind === "deferred": case pEntry.node.async: break; case pEntry.node === setupFunction: case pEntry.kind === "immediate" && __eslint_react_ast.findParentNode(pEntry.node, __eslint_react_ast.isFunction) === setupFunction: onViolation(context, node, { name: context.sourceCode.getText(node.callee) }); return; default: { const vd = __eslint_react_ast.findParentNode(node, isVariableDeclaratorFromHookCall); if (vd == null) (0, __eslint_react_eff.getOrElseUpdate)(indSetStateCalls, pEntry.node, () => []).push(node); else (0, __eslint_react_eff.getOrElseUpdate)(indSetStateCallsInUseMemoOrCallback, vd.init, () => []).push(node); } } }).with(useEffectKind, () => { if (__eslint_react_ast.isFunction(node.arguments.at(0))) return; setupFunctionIdentifiers.push(...__eslint_react_ast.getNestedIdentifiers(node)); }).with("other", () => { if (pEntry.node !== setupFunction) return; indFunctionCalls.push(node); }).otherwise(__eslint_react_eff.constVoid); }, Identifier(node) { if (node.parent.type === __typescript_eslint_types.AST_NODE_TYPES.CallExpression && node.parent.callee === node) return; if (!isIdFromUseStateCall(node)) return; switch (node.parent.type) { case __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression: { const parent = node.parent.parent; if (parent.type !== __typescript_eslint_types.AST_NODE_TYPES.CallExpression) break; if (!isUseMemoCall(parent)) break; const vd = __eslint_react_ast.findParentNode(parent, isVariableDeclaratorFromHookCall); if (vd != null) (0, __eslint_react_eff.getOrElseUpdate)(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node); break; } case __typescript_eslint_types.AST_NODE_TYPES.CallExpression: if (node !== node.parent.arguments.at(0)) break; if (isUseCallbackCall(node.parent)) { const vd = __eslint_react_ast.findParentNode(node.parent, isVariableDeclaratorFromHookCall); if (vd != null) (0, __eslint_react_eff.getOrElseUpdate)(indSetStateCallsInUseEffectArg0, vd.init, () => []).push(node); break; } if (isUseEffectLikeCall(node.parent)) (0, __eslint_react_eff.getOrElseUpdate)(indSetStateCallsInUseEffectSetup, node.parent, () => []).push(node); } }, "Program:exit"() { const getSetStateCalls = (id, initialScope) => { const node = __eslint_react_var.getVariableInitNode(__eslint_react_var.findVariable(id, initialScope), 0); switch (node?.type) { case __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression: case __typescript_eslint_types.AST_NODE_TYPES.FunctionDeclaration: case __typescript_eslint_types.AST_NODE_TYPES.FunctionExpression: return indSetStateCalls.get(node) ?? []; case __typescript_eslint_types.AST_NODE_TYPES.CallExpression: return indSetStateCallsInUseMemoOrCallback.get(node) ?? indSetStateCallsInUseEffectArg0.get(node) ?? []; } return []; }; for (const [, calls] of indSetStateCallsInUseEffectSetup) for (const call of calls) onViolation(context, call, { name: call.name }); for (const { callee } of indFunctionCalls) { if (!("name" in callee)) continue; const { name: name$2 } = callee; const setStateCalls = getSetStateCalls(name$2, context.sourceCode.getScope(callee)); for (const setStateCall of setStateCalls) onViolation(context, setStateCall, { name: getCallName(setStateCall) }); } for (const id of setupFunctionIdentifiers) { const setStateCalls = getSetStateCalls(id.name, context.sourceCode.getScope(id)); for (const setStateCall of setStateCalls) onViolation(context, setStateCall, { name: getCallName(setStateCall) }); } } }; } //#endregion //#region src/rules/no-direct-set-state-in-use-effect.ts const RULE_NAME$5 = "no-direct-set-state-in-use-effect"; const RULE_FEATURES$5 = ["EXP"]; var no_direct_set_state_in_use_effect_default = createRule({ meta: { type: "problem", docs: { description: "Disallow direct calls to the `set` function of `useState` in `useEffect`.", [Symbol.for("rule_features")]: RULE_FEATURES$5 }, messages: { noDirectSetStateInUseEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useEffect'." }, schema: [] }, name: RULE_NAME$5, create: create$5, defaultOptions: [] }); function create$5(context) { if (!/use\w*Effect/u.test(context.sourceCode.text)) return {}; return useNoDirectSetStateInUseEffect(context, { onViolation(ctx, node, data) { ctx.report({ messageId: "noDirectSetStateInUseEffect", node, data }); }, useEffectKind: "useEffect" }); } //#endregion //#region src/rules/no-direct-set-state-in-use-layout-effect.ts const RULE_NAME$4 = "no-direct-set-state-in-use-layout-effect"; const RULE_FEATURES$4 = ["EXP"]; var no_direct_set_state_in_use_layout_effect_default = createRule({ meta: { type: "problem", docs: { description: "Disallow direct calls to the `set` function of `useState` in `useLayoutEffect`.", [Symbol.for("rule_features")]: RULE_FEATURES$4 }, messages: { noDirectSetStateInUseLayoutEffect: "Do not call the 'set' function '{{name}}' of 'useState' directly in 'useLayoutEffect'." }, schema: [] }, name: RULE_NAME$4, create: create$4, defaultOptions: [] }); function create$4(context) { if (!/use\w*Effect/u.test(context.sourceCode.text)) return {}; return useNoDirectSetStateInUseEffect(context, { onViolation(ctx, node, data) { ctx.report({ messageId: "noDirectSetStateInUseLayoutEffect", node, data }); }, useEffectKind: "useLayoutEffect" }); } //#endregion //#region src/rules/no-unnecessary-use-callback.ts const RULE_NAME$3 = "no-unnecessary-use-callback"; const RULE_FEATURES$3 = ["EXP"]; var no_unnecessary_use_callback_default = createRule({ meta: { type: "problem", docs: { description: "Disallow unnecessary usage of `useCallback`.", [Symbol.for("rule_features")]: RULE_FEATURES$3 }, messages: { noUnnecessaryUseCallback: "An 'useCallback' with empty deps and no references to the component scope may be unnecessary." }, schema: [] }, name: RULE_NAME$3, create: create$3, defaultOptions: [] }); function create$3(context) { if (!context.sourceCode.text.includes("use")) return {}; const alias = (0, __eslint_react_shared.getSettingsFromContext)(context).additionalHooks.useCallback ?? []; const isUseCallbackCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useCallback", alias); return { CallExpression(node) { if (!__eslint_react_core.isReactHookCall(node)) return; const initialScope = context.sourceCode.getScope(node); if (!isUseCallbackCall(node)) return; const component = context.sourceCode.getScope(node).block; if (!__eslint_react_ast.isFunction(component)) return; const [arg0, arg1] = node.arguments; if (arg0 == null || arg1 == null) return; if (!(0, ts_pattern.match)(arg1).with({ type: __typescript_eslint_types.AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: __typescript_eslint_types.AST_NODE_TYPES.Identifier }, (n) => { const variable = __eslint_react_var.findVariable(n.name, initialScope); const variableNode = __eslint_react_var.getVariableInitNode(variable, 0); if (variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.ArrayExpression) return false; return variableNode.elements.length === 0; }).otherwise(() => false)) return; const arg0Node = (0, ts_pattern.match)(arg0).with({ type: __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => { if (n.body.type === __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression) return n.body; return n; }).with({ type: __typescript_eslint_types.AST_NODE_TYPES.FunctionExpression }, __eslint_react_eff.identity).with({ type: __typescript_eslint_types.AST_NODE_TYPES.Identifier }, (n) => { const variable = __eslint_react_var.findVariable(n.name, initialScope); const variableNode = __eslint_react_var.getVariableInitNode(variable, 0); if (variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.FunctionExpression) return null; return variableNode; }).otherwise(() => null); if (arg0Node == null) return; const arg0NodeScope = context.sourceCode.getScope(arg0Node); if (!__eslint_react_var.getChidScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({ messageId: "noUnnecessaryUseCallback", node }); } }; } //#endregion //#region src/rules/no-unnecessary-use-memo.ts const RULE_NAME$2 = "no-unnecessary-use-memo"; const RULE_FEATURES$2 = ["EXP"]; var no_unnecessary_use_memo_default = createRule({ meta: { type: "problem", docs: { description: "Disallow unnecessary usage of `useMemo`.", [Symbol.for("rule_features")]: RULE_FEATURES$2 }, messages: { noUnnecessaryUseMemo: "An 'useMemo' with empty deps and no references to the component scope may be unnecessary." }, schema: [] }, name: RULE_NAME$2, create: create$2, defaultOptions: [] }); function create$2(context) { if (!context.sourceCode.text.includes("use")) return {}; const alias = (0, __eslint_react_shared.getSettingsFromContext)(context).additionalHooks.useMemo ?? []; const isUseMemoCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useMemo", alias); return { CallExpression(node) { if (!__eslint_react_core.isReactHookCall(node)) return; const initialScope = context.sourceCode.getScope(node); if (!isUseMemoCall(node)) return; const component = context.sourceCode.getScope(node).block; if (!__eslint_react_ast.isFunction(component)) return; const [arg0, arg1] = node.arguments; if (arg0 == null || arg1 == null) return; if (__eslint_react_ast.isFunction(arg0) && [...__eslint_react_ast.getNestedCallExpressions(arg0.body), ...__eslint_react_ast.getNestedNewExpressions(arg0.body)].length > 0) return; if (!(0, ts_pattern.match)(arg1).with({ type: __typescript_eslint_types.AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: __typescript_eslint_types.AST_NODE_TYPES.Identifier }, (n) => { const variable = __eslint_react_var.findVariable(n.name, initialScope); const variableNode = __eslint_react_var.getVariableInitNode(variable, 0); if (variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.ArrayExpression) return false; return variableNode.elements.length === 0; }).otherwise(() => false)) return; const arg0Node = (0, ts_pattern.match)(arg0).with({ type: __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression }, (n) => { if (n.body.type === __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression) return n.body; return n; }).with({ type: __typescript_eslint_types.AST_NODE_TYPES.FunctionExpression }, __eslint_react_eff.identity).with({ type: __typescript_eslint_types.AST_NODE_TYPES.Identifier }, (n) => { const variable = __eslint_react_var.findVariable(n.name, initialScope); const variableNode = __eslint_react_var.getVariableInitNode(variable, 0); if (variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.ArrowFunctionExpression && variableNode?.type !== __typescript_eslint_types.AST_NODE_TYPES.FunctionExpression) return null; return variableNode; }).otherwise(() => null); if (arg0Node == null) return; const arg0NodeScope = context.sourceCode.getScope(arg0Node); if (!__eslint_react_var.getChidScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({ messageId: "noUnnecessaryUseMemo", node }); } }; } //#endregion //#region src/rules/no-unnecessary-use-prefix.ts const RULE_NAME$1 = "no-unnecessary-use-prefix"; const RULE_FEATURES$1 = []; const WELL_KNOWN_HOOKS = ["useMDXComponents"]; function containsUseComments(context, node) { return context.sourceCode.getCommentsInside(node).some(({ value }) => /use\([\s\S]*?\)/u.test(value) || /use[A-Z0-9]\w*\([\s\S]*?\)/u.test(value)); } var no_unnecessary_use_prefix_default = createRule({ meta: { type: "problem", docs: { description: "Enforces that a function with the `use` prefix should use at least one Hook inside of it.", [Symbol.for("rule_features")]: RULE_FEATURES$1 }, messages: { noUnnecessaryUsePrefix: "If your function doesn't call any Hooks, avoid the 'use' prefix. Instead, write it as a regular function without the 'use' prefix." }, schema: [] }, name: RULE_NAME$1, create: create$1, defaultOptions: [] }); function create$1(context) { const { ctx, listeners } = __eslint_react_core.useHookCollector(); return { ...listeners, "Program:exit"(program) { const allHooks = ctx.getAllHooks(program); for (const { id, name: name$2, node, hookCalls } of allHooks.values()) { if (WELL_KNOWN_HOOKS.includes(name$2)) continue; if (__eslint_react_ast.isEmptyFunction(node)) continue; if (hookCalls.length > 0) continue; if (containsUseComments(context, node)) continue; context.report({ messageId: "noUnnecessaryUsePrefix", node: id ?? node, data: { name: name$2 } }); } } }; } //#endregion //#region src/rules/prefer-use-state-lazy-initialization.ts const RULE_NAME = "prefer-use-state-lazy-initialization"; const RULE_FEATURES = ["EXP"]; const ALLOW_LIST = [ "Boolean", "String", "Number" ]; var prefer_use_state_lazy_initialization_default = createRule({ meta: { type: "problem", docs: { description: "Enforces function calls made inside `useState` to be wrapped in an `initializer function`.", [Symbol.for("rule_features")]: RULE_FEATURES }, messages: { preferUseStateLazyInitialization: "To prevent re-computation, consider using lazy initial state for useState calls that involve function calls. Ex: 'useState(() => getValue())'." }, schema: [] }, name: RULE_NAME, create, defaultOptions: [] }); function create(context) { const alias = (0, __eslint_react_shared.getSettingsFromContext)(context).additionalHooks.useState ?? []; const isUseStateCall = __eslint_react_core.isReactHookCallWithNameAlias(context, "useState", alias); return { CallExpression(node) { if (!__eslint_react_core.isReactHookCall(node)) return; if (!isUseStateCall(node)) return; const [useStateInput] = node.arguments; if (useStateInput == null) return; for (const expr of __eslint_react_ast.getNestedNewExpressions(useStateInput)) { if (!("name" in expr.callee)) continue; if (ALLOW_LIST.includes(expr.callee.name)) continue; if (__eslint_react_ast.findParentNode(expr, (n) => __eslint_react_core.isUseCall(context, n)) != null) continue; context.report({ messageId: "preferUseStateLazyInitialization", node: expr }); } for (const expr of __eslint_react_ast.getNestedCallExpressions(useStateInput)) { if (!("name" in expr.callee)) continue; if (__eslint_react_core.isReactHookName(expr.callee.name)) continue; if (ALLOW_LIST.includes(expr.callee.name)) continue; if (__eslint_react_ast.findParentNode(expr, (n) => __eslint_react_core.isUseCall(context, n)) != null) continue; context.report({ messageId: "preferUseStateLazyInitialization", node: expr }); } } }; } //#endregion //#region src/plugin.ts const plugin = { meta: { name, version }, rules: { "no-direct-set-state-in-use-effect": no_direct_set_state_in_use_effect_default, "no-direct-set-state-in-use-layout-effect": no_direct_set_state_in_use_layout_effect_default, "no-unnecessary-use-callback": no_unnecessary_use_callback_default, "no-unnecessary-use-memo": no_unnecessary_use_memo_default, "no-unnecessary-use-prefix": no_unnecessary_use_prefix_default, "prefer-use-state-lazy-initialization": prefer_use_state_lazy_initialization_default, "ensure-custom-hooks-using-other-hooks": no_unnecessary_use_prefix_default, "ensure-use-callback-has-non-empty-deps": no_unnecessary_use_callback_default, "ensure-use-memo-has-non-empty-deps": no_unnecessary_use_memo_default, "no-redundant-custom-hook": no_unnecessary_use_prefix_default, "no-useless-custom-hooks": no_unnecessary_use_prefix_default } }; //#endregion //#region src/index.ts const { toFlatConfig, toLegacyConfig } = (0, __eslint_react_shared.getConfigAdapters)("react-hooks-extra", plugin); var src_default = { ...plugin, configs: { ["recommended"]: toFlatConfig(recommended_exports), ["recommended-legacy"]: toLegacyConfig(recommended_exports) } }; //#endregion module.exports = src_default;