From 8d4027cbf6c142a33309f045bba2bb000fe5ef8d Mon Sep 17 00:00:00 2001 From: Eva1ent Date: Mon, 30 Dec 2024 11:48:41 +0800 Subject: [PATCH] refactor: 'is-from-react' to use dual api --- .../core/docs/functions/isCallFromReact.md | 18 +-------- .../docs/functions/isCallFromReactMember.md | 18 +-------- .../docs/functions/isChildrenCountCall.md | 40 +++++++++++++++---- .../docs/functions/isChildrenForEachCall.md | 40 +++++++++++++++---- .../core/docs/functions/isChildrenMapCall.md | 40 +++++++++++++++---- .../functions/isChildrenOfCreateElement.md | 8 ++++ .../core/docs/functions/isChildrenOnlyCall.md | 40 +++++++++++++++---- .../docs/functions/isChildrenToArrayCall.md | 40 +++++++++++++++---- .../core/docs/functions/isCloneElementCall.md | 40 +++++++++++++++---- .../docs/functions/isCreateContextCall.md | 40 +++++++++++++++---- .../docs/functions/isCreateElementCall.md | 40 +++++++++++++++---- .../core/docs/functions/isCreateRefCall.md | 40 +++++++++++++++---- .../core/docs/functions/isForwardRefCall.md | 40 +++++++++++++++---- .../functions/isInsideCreateElementProps.md | 2 +- packages/core/docs/functions/isMemoCall.md | 40 +++++++++++++++---- packages/core/src/element/hierarchy.ts | 21 ++++++---- packages/core/src/utils/is-from-react.ts | 38 +++++++++++++++--- .../src/rules/no-unnecessary-use-callback.ts | 4 +- .../src/rules/no-unnecessary-use-memo.ts | 4 +- .../src/rules/use-state.ts | 11 +---- .../src/rules/no-array-index-key.ts | 8 ++-- 21 files changed, 428 insertions(+), 144 deletions(-) diff --git a/packages/core/docs/functions/isCallFromReact.md b/packages/core/docs/functions/isCallFromReact.md index c29ba25a4c..ec8fb893ed 100644 --- a/packages/core/docs/functions/isCallFromReact.md +++ b/packages/core/docs/functions/isCallFromReact.md @@ -6,7 +6,7 @@ # Function: isCallFromReact() -> **isCallFromReact**(`name`): (`node`, `context`) => `boolean` +> **isCallFromReact**(`name`): `IsCallFromReact` ## Parameters @@ -16,18 +16,4 @@ ## Returns -`Function` - -### Parameters - -#### node - -`CallExpression` - -#### context - -`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> - -### Returns - -`boolean` +`IsCallFromReact` diff --git a/packages/core/docs/functions/isCallFromReactMember.md b/packages/core/docs/functions/isCallFromReactMember.md index 8bdb26565f..d38d98cc8e 100644 --- a/packages/core/docs/functions/isCallFromReactMember.md +++ b/packages/core/docs/functions/isCallFromReactMember.md @@ -6,7 +6,7 @@ # Function: isCallFromReactMember() -> **isCallFromReactMember**(`pragmaMemberName`, `name`): (`node`, `context`) => `boolean` +> **isCallFromReactMember**(`pragmaMemberName`, `name`): `IsCallFromReactMember` ## Parameters @@ -20,18 +20,4 @@ ## Returns -`Function` - -### Parameters - -#### node - -`CallExpression` - -#### context - -`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> - -### Returns - -`boolean` +`IsCallFromReactMember` diff --git a/packages/core/docs/functions/isChildrenCountCall.md b/packages/core/docs/functions/isChildrenCountCall.md index b29ab1fc5b..df0cdb7204 100644 --- a/packages/core/docs/functions/isChildrenCountCall.md +++ b/packages/core/docs/functions/isChildrenCountCall.md @@ -6,18 +6,44 @@ # Function: isChildrenCountCall() -> **isChildrenCountCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isChildrenCountCall**(`context`): (`node`) => `node is CallExpression & { callee: MemberExpression }` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression & { callee: MemberExpression }` + +## Call Signature + +> **isChildrenCountCall**(`node`, `context`): `node is CallExpression & { callee: MemberExpression }` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression & { callee: MemberExpression }` diff --git a/packages/core/docs/functions/isChildrenForEachCall.md b/packages/core/docs/functions/isChildrenForEachCall.md index 911b2ba277..43219ca44c 100644 --- a/packages/core/docs/functions/isChildrenForEachCall.md +++ b/packages/core/docs/functions/isChildrenForEachCall.md @@ -6,18 +6,44 @@ # Function: isChildrenForEachCall() -> **isChildrenForEachCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isChildrenForEachCall**(`context`): (`node`) => `node is CallExpression & { callee: MemberExpression }` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression & { callee: MemberExpression }` + +## Call Signature + +> **isChildrenForEachCall**(`node`, `context`): `node is CallExpression & { callee: MemberExpression }` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression & { callee: MemberExpression }` diff --git a/packages/core/docs/functions/isChildrenMapCall.md b/packages/core/docs/functions/isChildrenMapCall.md index 22945fc84d..5c2b94d30f 100644 --- a/packages/core/docs/functions/isChildrenMapCall.md +++ b/packages/core/docs/functions/isChildrenMapCall.md @@ -6,18 +6,44 @@ # Function: isChildrenMapCall() -> **isChildrenMapCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isChildrenMapCall**(`context`): (`node`) => `node is CallExpression & { callee: MemberExpression }` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression & { callee: MemberExpression }` + +## Call Signature + +> **isChildrenMapCall**(`node`, `context`): `node is CallExpression & { callee: MemberExpression }` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression & { callee: MemberExpression }` diff --git a/packages/core/docs/functions/isChildrenOfCreateElement.md b/packages/core/docs/functions/isChildrenOfCreateElement.md index bfc547c7ef..48d2746e82 100644 --- a/packages/core/docs/functions/isChildrenOfCreateElement.md +++ b/packages/core/docs/functions/isChildrenOfCreateElement.md @@ -8,16 +8,24 @@ > **isChildrenOfCreateElement**(`node`, `context`): `boolean` +Determines whether inside `createElement`'s children. + ## Parameters ### node `Node` +The AST node to check + ### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> +The rule context + ## Returns `boolean` + +`true` if the node is inside createElement's children diff --git a/packages/core/docs/functions/isChildrenOnlyCall.md b/packages/core/docs/functions/isChildrenOnlyCall.md index 847acae802..aeb173e7eb 100644 --- a/packages/core/docs/functions/isChildrenOnlyCall.md +++ b/packages/core/docs/functions/isChildrenOnlyCall.md @@ -6,18 +6,44 @@ # Function: isChildrenOnlyCall() -> **isChildrenOnlyCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isChildrenOnlyCall**(`context`): (`node`) => `node is CallExpression & { callee: MemberExpression }` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression & { callee: MemberExpression }` + +## Call Signature + +> **isChildrenOnlyCall**(`node`, `context`): `node is CallExpression & { callee: MemberExpression }` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression & { callee: MemberExpression }` diff --git a/packages/core/docs/functions/isChildrenToArrayCall.md b/packages/core/docs/functions/isChildrenToArrayCall.md index 5da028d4f5..d63fc9b8f4 100644 --- a/packages/core/docs/functions/isChildrenToArrayCall.md +++ b/packages/core/docs/functions/isChildrenToArrayCall.md @@ -6,18 +6,44 @@ # Function: isChildrenToArrayCall() -> **isChildrenToArrayCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isChildrenToArrayCall**(`context`): (`node`) => `node is CallExpression & { callee: MemberExpression }` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression & { callee: MemberExpression }` + +## Call Signature + +> **isChildrenToArrayCall**(`node`, `context`): `node is CallExpression & { callee: MemberExpression }` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression & { callee: MemberExpression }` diff --git a/packages/core/docs/functions/isCloneElementCall.md b/packages/core/docs/functions/isCloneElementCall.md index fb4f44dac5..ec10d6fe30 100644 --- a/packages/core/docs/functions/isCloneElementCall.md +++ b/packages/core/docs/functions/isCloneElementCall.md @@ -6,18 +6,44 @@ # Function: isCloneElementCall() -> **isCloneElementCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isCloneElementCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isCloneElementCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/docs/functions/isCreateContextCall.md b/packages/core/docs/functions/isCreateContextCall.md index b97491cf2c..8cb225cc7a 100644 --- a/packages/core/docs/functions/isCreateContextCall.md +++ b/packages/core/docs/functions/isCreateContextCall.md @@ -6,18 +6,44 @@ # Function: isCreateContextCall() -> **isCreateContextCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isCreateContextCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isCreateContextCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/docs/functions/isCreateElementCall.md b/packages/core/docs/functions/isCreateElementCall.md index 47eddf4842..dbcb85ea09 100644 --- a/packages/core/docs/functions/isCreateElementCall.md +++ b/packages/core/docs/functions/isCreateElementCall.md @@ -6,18 +6,44 @@ # Function: isCreateElementCall() -> **isCreateElementCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isCreateElementCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isCreateElementCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/docs/functions/isCreateRefCall.md b/packages/core/docs/functions/isCreateRefCall.md index 86c303fc6f..e1a0d534b9 100644 --- a/packages/core/docs/functions/isCreateRefCall.md +++ b/packages/core/docs/functions/isCreateRefCall.md @@ -6,18 +6,44 @@ # Function: isCreateRefCall() -> **isCreateRefCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isCreateRefCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isCreateRefCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/docs/functions/isForwardRefCall.md b/packages/core/docs/functions/isForwardRefCall.md index aad951ef7e..4b808c0efc 100644 --- a/packages/core/docs/functions/isForwardRefCall.md +++ b/packages/core/docs/functions/isForwardRefCall.md @@ -6,18 +6,44 @@ # Function: isForwardRefCall() -> **isForwardRefCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isForwardRefCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isForwardRefCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/docs/functions/isInsideCreateElementProps.md b/packages/core/docs/functions/isInsideCreateElementProps.md index e9dd08fa26..279245febf 100644 --- a/packages/core/docs/functions/isInsideCreateElementProps.md +++ b/packages/core/docs/functions/isInsideCreateElementProps.md @@ -8,7 +8,7 @@ > **isInsideCreateElementProps**(`node`, `context`): `boolean` -Determines whether inside createElement's props. +Determines whether inside `createElement`'s props. ## Parameters diff --git a/packages/core/docs/functions/isMemoCall.md b/packages/core/docs/functions/isMemoCall.md index b1a2b7141f..27f22b1dd3 100644 --- a/packages/core/docs/functions/isMemoCall.md +++ b/packages/core/docs/functions/isMemoCall.md @@ -6,18 +6,44 @@ # Function: isMemoCall() -> **isMemoCall**(`node`, `context`): `boolean` +## Call Signature -## Parameters +> **isMemoCall**(`context`): (`node`) => `node is CallExpression` -### node +### Parameters -`CallExpression` +#### context -### context +`Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> + +### Returns + +`Function` + +#### Parameters + +##### node + +`Node` + +#### Returns + +`node is CallExpression` + +## Call Signature + +> **isMemoCall**(`node`, `context`): `node is CallExpression` + +### Parameters + +#### node + +`Node` + +#### context `Readonly`\<`RuleContext`\<`string`, readonly `unknown`[]\>\> -## Returns +### Returns -`boolean` +`node is CallExpression` diff --git a/packages/core/src/element/hierarchy.ts b/packages/core/src/element/hierarchy.ts index ac996ddaa9..b4cabd548a 100644 --- a/packages/core/src/element/hierarchy.ts +++ b/packages/core/src/element/hierarchy.ts @@ -7,7 +7,7 @@ import { AST_NODE_TYPES } from "@typescript-eslint/types"; import { isCreateElementCall } from "../utils"; /** - * Determines whether inside createElement's props. + * Determines whether inside `createElement`'s props. * @param node The AST node to check * @param context The rule context * @returns `true` if the node is inside createElement's props @@ -17,15 +17,20 @@ export function isInsideCreateElementProps( context: RuleContext, ) { return F.pipe( - AST.traverseUp(node, n => AST.is(AST_NODE_TYPES.CallExpression)(n) && isCreateElementCall(n, context)), - O.filter(AST.is(AST_NODE_TYPES.CallExpression)), - O.flatMapNullable(c => c.arguments.at(1)), - O.filter(AST.is(AST_NODE_TYPES.ObjectExpression)), - O.zipWith(AST.traverseUp(node, AST.is(AST_NODE_TYPES.ObjectExpression)), (a, b) => a === b), - O.getOrElse(F.constFalse), + O.Do, + O.bind("call", () => AST.traverseUpGuard(node, isCreateElementCall(context))), + O.bind("prop", () => AST.traverseUpGuard(node, AST.is(AST_NODE_TYPES.ObjectExpression))), + O.bind("arg1", ({ call }) => O.fromNullable(call.arguments[1])), + O.exists(({ arg1, prop }) => prop === arg1), ); } +/** + * Determines whether inside `createElement`'s children. + * @param node The AST node to check + * @param context The rule context + * @returns `true` if the node is inside createElement's children + */ export function isChildrenOfCreateElement( node: TSESTree.Node, context: RuleContext, @@ -33,7 +38,7 @@ export function isChildrenOfCreateElement( return F.pipe( O.fromNullable(node.parent), O.filter(AST.is(AST_NODE_TYPES.CallExpression)), - O.filter(n => isCreateElementCall(n, context)), + O.filter(isCreateElementCall(context)), O.exists(n => n.arguments .slice(2) diff --git a/packages/core/src/utils/is-from-react.ts b/packages/core/src/utils/is-from-react.ts index bc5113ae25..a97feaa2f7 100644 --- a/packages/core/src/utils/is-from-react.ts +++ b/packages/core/src/utils/is-from-react.ts @@ -1,4 +1,5 @@ import * as AST from "@eslint-react/ast"; +import { F } from "@eslint-react/eff"; import { unsafeReadSettings } from "@eslint-react/shared"; import type { RuleContext } from "@eslint-react/types"; import type { TSESTree } from "@typescript-eslint/types"; @@ -61,19 +62,44 @@ export function isFromReactMember( }; } -export function isCallFromReact(name: string) { - return (node: TSESTree.CallExpression, context: RuleContext) => { +type IsCallFromReact = { + (context: RuleContext): (node: TSESTree.Node) => node is TSESTree.CallExpression; + (node: TSESTree.Node, context: RuleContext): node is TSESTree.CallExpression; +}; + +export function isCallFromReact(name: string): IsCallFromReact { + return F.dual(2, (node: TSESTree.Node, context: RuleContext): node is TSESTree.CallExpression => { + if (node.type !== AST_NODE_TYPES.CallExpression) return false; if (!AST.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) return false; return isFromReact(name)(node.callee, context); - }; + }); } +type IsCallFromReactMember = { + (context: RuleContext): (node: TSESTree.Node) => node is + & TSESTree.CallExpression + & { callee: TSESTree.MemberExpression }; + ( + node: TSESTree.Node, + context: RuleContext, + ): node is + & TSESTree.CallExpression + & { callee: TSESTree.MemberExpression }; +}; + export function isCallFromReactMember( pragmaMemberName: string, name: string, -) { - return (node: TSESTree.CallExpression, context: RuleContext) => { +): IsCallFromReactMember { + return F.dual(2, ( + node: TSESTree.Node, + context: RuleContext, + ): node is + & TSESTree.CallExpression + & { callee: TSESTree.MemberExpression } => + { + if (node.type !== AST_NODE_TYPES.CallExpression) return false; if (!AST.is(AST_NODE_TYPES.MemberExpression)(node.callee)) return false; return isFromReactMember(pragmaMemberName, name)(node.callee, context); - }; + }); } diff --git a/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-callback.ts b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-callback.ts index e3d8ab4268..3ef52f405c 100644 --- a/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-callback.ts +++ b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-callback.ts @@ -39,9 +39,7 @@ export default createRule<[], MessageID>({ CallExpression(node) { if (!isReactHookCall(node)) return; const initialScope = context.sourceCode.getScope(node); - if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) { - return; - } + if (!isUseCallbackCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return; const scope = context.sourceCode.getScope(node); const component = scope.block; if (!AST.isFunction(component)) return; diff --git a/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-memo.ts b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-memo.ts index 1c63502b9c..7b97cb08cd 100644 --- a/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-memo.ts +++ b/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-unnecessary-use-memo.ts @@ -38,9 +38,7 @@ export default createRule<[], MessageID>({ CallExpression(node) { if (!isReactHookCall(node)) return; const initialScope = context.sourceCode.getScope(node); - if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) { - return; - } + if (!isUseMemoCall(node, context) && !alias.some(isReactHookCallWithNameLoose(node))) return; const scope = context.sourceCode.getScope(node); const component = scope.block; if (!AST.isFunction(component)) return; diff --git a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/use-state.ts b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/use-state.ts index 7dccb19035..fee6fef006 100644 --- a/packages/plugins/eslint-plugin-react-naming-convention/src/rules/use-state.ts +++ b/packages/plugins/eslint-plugin-react-naming-convention/src/rules/use-state.ts @@ -49,15 +49,8 @@ export default createRule<[], MessageID>({ for (const { hookCalls } of components.values()) { if (hookCalls.length === 0) continue; for (const hookCall of hookCalls) { - if ( - !isUseStateCall(hookCall, context) - && !alias.some(isReactHookCallWithNameLoose(hookCall)) - ) { - continue; - } - if (hookCall.parent.type !== AST_NODE_TYPES.VariableDeclarator) { - continue; - } + if (!isUseStateCall(hookCall, context) && !alias.some(isReactHookCallWithNameLoose(hookCall))) continue; + if (hookCall.parent.type !== AST_NODE_TYPES.VariableDeclarator) continue; const { id } = hookCall.parent; const descriptor = O.some({ messageId: "useState", node: id } as const); F.pipe( diff --git a/packages/plugins/eslint-plugin-react-x/src/rules/no-array-index-key.ts b/packages/plugins/eslint-plugin-react-x/src/rules/no-array-index-key.ts index 5709453b0e..354f7cdcf1 100644 --- a/packages/plugins/eslint-plugin-react-x/src/rules/no-array-index-key.ts +++ b/packages/plugins/eslint-plugin-react-x/src/rules/no-array-index-key.ts @@ -1,6 +1,6 @@ import * as AST from "@eslint-react/ast"; import { isCloneElementCall, isCreateElementCall, isInitializedFromReact } from "@eslint-react/core"; -import { isNullable, O } from "@eslint-react/eff"; +import { isNullable, O, or } from "@eslint-react/eff"; import { unsafeReadSettings } from "@eslint-react/shared"; import type { RuleContext, RuleFeature } from "@eslint-react/types"; import { AST_NODE_TYPES } from "@typescript-eslint/types"; @@ -116,14 +116,12 @@ export default createRule<[], MessageID>({ create(context) { const indexParamNames: O.Option[] = []; + const isCreateOrCloneElementCall = or(isCreateElementCall(context), isCloneElementCall(context)); + function isArrayIndex(node: TSESTree.Node): node is TSESTree.Identifier { return node.type === AST_NODE_TYPES.Identifier && indexParamNames.some(O.exists((name) => name === node.name)); } - function isCreateOrCloneElementCall(node: TSESTree.CallExpression) { - return isCreateElementCall(node, context) || isCloneElementCall(node, context); - } - function getReportDescriptor(node: TSESTree.Node): ReportDescriptor[] { // key={bar} if (isArrayIndex(node)) return [{ messageId: "noArrayIndexKey", node }];