Skip to content

Commit 7a10045

Browse files
committed
solve simple member expression case
1 parent a0e4713 commit 7a10045

File tree

1 file changed

+79
-23
lines changed

1 file changed

+79
-23
lines changed

plugins/eslint-plugin-aws-toolkits/lib/rules/no-async-in-foreach.ts

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,89 @@ function isFunctionExpression(
1616
return node.type === AST_NODE_TYPES.ArrowFunctionExpression || node.type === AST_NODE_TYPES.FunctionExpression
1717
}
1818

19+
function isAsyncFuncIdentifier<T extends string, T2 extends readonly unknown[]>(
20+
context: RuleContext<T, T2>,
21+
funcNode: TSESTree.Identifier
22+
): boolean {
23+
const scope = context.sourceCode.getScope(funcNode)
24+
const maybeFNode = scope.variables.find((v) => v.name === funcNode.name)?.defs.find((d) => !!d)?.node ?? undefined
25+
// function declartions Ex. async function f() {}
26+
if (
27+
maybeFNode &&
28+
(isFunctionExpression(maybeFNode) || maybeFNode.type === AST_NODE_TYPES.FunctionDeclaration) &&
29+
maybeFNode.async
30+
) {
31+
return true
32+
}
33+
// variable-style function declarations Ex. const f = async function () {}
34+
if (
35+
maybeFNode &&
36+
maybeFNode.type === AST_NODE_TYPES.VariableDeclarator &&
37+
maybeFNode.init &&
38+
isFunctionExpression(maybeFNode.init) &&
39+
maybeFNode.init.async
40+
) {
41+
return true
42+
}
43+
return false
44+
}
45+
46+
function getClassDeclarationNode<T extends string, T2 extends readonly unknown[]>(
47+
context: RuleContext<T, T2>,
48+
node: TSESTree.Node
49+
): TSESTree.ClassDeclaration | undefined {
50+
console.log('in getObjectNode with %O', node)
51+
if (node.type === AST_NODE_TYPES.MemberExpression) {
52+
return getClassDeclarationNode(context, node.object)
53+
}
54+
if (node.type === AST_NODE_TYPES.NewExpression && node.callee.type === AST_NODE_TYPES.Identifier) {
55+
const className = node.callee.name
56+
const scope = context.sourceCode.getScope(node)
57+
const maybeDefNode =
58+
(scope.variables
59+
.find((v) => v.name === className)
60+
?.defs.find((d) => !!d && d.node.type === AST_NODE_TYPES.ClassDeclaration)
61+
?.node as TSESTree.ClassDeclaration) ?? undefined
62+
return maybeDefNode
63+
}
64+
}
65+
66+
function isAsyncClassMethod(defObjNode: TSESTree.ClassDeclaration, functionName: string): boolean {
67+
return defObjNode.body.body.some(
68+
(n) =>
69+
n.type === AST_NODE_TYPES.MethodDefinition &&
70+
n.kind === 'method' &&
71+
n.key.type === AST_NODE_TYPES.Identifier &&
72+
n.key.name === functionName &&
73+
n.value.async
74+
)
75+
}
76+
77+
function isAsyncFuncMemExpression<T extends string, T2 extends readonly unknown[]>(
78+
context: RuleContext<T, T2>,
79+
funcNode: TSESTree.MemberExpression
80+
): boolean {
81+
console.log('in isAsyncMemExp')
82+
if (funcNode.object.type === AST_NODE_TYPES.MemberExpression) {
83+
return isAsyncFuncMemExpression(context, funcNode.object)
84+
}
85+
if (funcNode.property.type === AST_NODE_TYPES.Identifier) {
86+
const fName = funcNode.property.name
87+
const defObjNode = getClassDeclarationNode(context, funcNode.object)
88+
return isAsyncClassMethod(defObjNode!, fName)
89+
}
90+
return false
91+
}
92+
1993
function isAsyncFunction<T extends string, T2 extends readonly unknown[]>(
2094
context: RuleContext<T, T2>,
2195
funcNode: TSESTree.CallExpressionArgument
2296
) {
2397
if (funcNode.type === AST_NODE_TYPES.Identifier) {
24-
const scope = context.sourceCode.getScope(funcNode)
25-
const maybeFNode =
26-
scope.variables.find((v) => v.name === funcNode.name)?.defs.find((d) => !!d)?.node ?? undefined
27-
// function declartions Ex. async function f() {}
28-
if (
29-
maybeFNode &&
30-
(isFunctionExpression(maybeFNode) || maybeFNode.type === AST_NODE_TYPES.FunctionDeclaration) &&
31-
maybeFNode.async
32-
) {
33-
return true
34-
}
35-
// variable-style function declarations Ex. const f = async function () {}
36-
if (
37-
maybeFNode &&
38-
maybeFNode.type === AST_NODE_TYPES.VariableDeclarator &&
39-
maybeFNode.init &&
40-
isFunctionExpression(maybeFNode.init) &&
41-
maybeFNode.init.async
42-
) {
43-
return true
44-
}
45-
return false
98+
return isAsyncFuncIdentifier(context, funcNode)
99+
}
100+
if (funcNode.type === AST_NODE_TYPES.MemberExpression) {
101+
return isAsyncFuncMemExpression(context, funcNode)
46102
}
47103
return (
48104
(funcNode.type === AST_NODE_TYPES.ArrowFunctionExpression ||
@@ -54,7 +110,7 @@ function isAsyncFunction<T extends string, T2 extends readonly unknown[]>(
54110
export default ESLintUtils.RuleCreator.withoutDocs({
55111
meta: {
56112
docs: {
57-
description: 'disallow inlining async functions with .forEach',
113+
description: 'disallow async functions with .forEach',
58114
recommended: 'recommended',
59115
},
60116
messages: {

0 commit comments

Comments
 (0)