@@ -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+
1993function 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[]>(
54110export 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