@@ -115,26 +115,6 @@ export default createRule<Options, MessageIds>({
115
115
| TSESTree . FunctionDeclaration
116
116
| TSESTree . FunctionExpression ,
117
117
) : void {
118
- const signatures = services . getTypeAtLocation ( node ) . getCallSignatures ( ) ;
119
- if ( ! signatures . length ) {
120
- return ;
121
- }
122
- const returnType = checker . getReturnTypeOfSignature ( signatures [ 0 ] ) ;
123
-
124
- if (
125
- ! containsAllTypesByName (
126
- returnType ,
127
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
128
- allowAny ! ,
129
- allAllowedPromiseNames ,
130
- // If no return type is explicitly set, we check if any parts of the return type match a Promise (instead of requiring all to match).
131
- node . returnType == null ,
132
- )
133
- ) {
134
- // Return type is not a promise
135
- return ;
136
- }
137
-
138
118
if ( node . parent . type === AST_NODE_TYPES . TSAbstractMethodDefinition ) {
139
119
// Abstract method can't be async
140
120
return ;
@@ -149,7 +129,21 @@ export default createRule<Options, MessageIds>({
149
129
return ;
150
130
}
151
131
152
- if ( isTypeFlagSet ( returnType , ts . TypeFlags . Any | ts . TypeFlags . Unknown ) ) {
132
+ const signatures = services . getTypeAtLocation ( node ) . getCallSignatures ( ) ;
133
+ if ( ! signatures . length ) {
134
+ return ;
135
+ }
136
+
137
+ const returnTypes = signatures . map ( signature =>
138
+ checker . getReturnTypeOfSignature ( signature ) ,
139
+ ) ;
140
+
141
+ if (
142
+ ! allowAny &&
143
+ returnTypes . some ( type =>
144
+ isTypeFlagSet ( type , ts . TypeFlags . Any | ts . TypeFlags . Unknown ) ,
145
+ )
146
+ ) {
153
147
// Report without auto fixer because the return type is unknown
154
148
return context . report ( {
155
149
loc : getFunctionHeadLoc ( node , context . sourceCode ) ,
@@ -158,67 +152,81 @@ export default createRule<Options, MessageIds>({
158
152
} ) ;
159
153
}
160
154
161
- context . report ( {
162
- loc : getFunctionHeadLoc ( node , context . sourceCode ) ,
163
- node,
164
- messageId : 'missingAsync' ,
165
- fix : fixer => {
166
- if (
167
- node . parent . type === AST_NODE_TYPES . MethodDefinition ||
168
- ( node . parent . type === AST_NODE_TYPES . Property && node . parent . method )
169
- ) {
170
- // this function is a class method or object function property shorthand
171
- const method = node . parent ;
172
-
173
- // the token to put `async` before
174
- let keyToken = nullThrows (
175
- context . sourceCode . getFirstToken ( method ) ,
176
- NullThrowsReasons . MissingToken ( 'key token' , 'method' ) ,
177
- ) ;
178
-
179
- // if there are decorators then skip past them
155
+ if (
156
+ // require all potential return types to be promise/any/unknown
157
+ returnTypes . every ( type =>
158
+ containsAllTypesByName (
159
+ type ,
160
+ true ,
161
+ allAllowedPromiseNames ,
162
+ // If no return type is explicitly set, we check if any parts of the return type match a Promise (instead of requiring all to match).
163
+ node . returnType == null ,
164
+ ) ,
165
+ )
166
+ ) {
167
+ context . report ( {
168
+ loc : getFunctionHeadLoc ( node , context . sourceCode ) ,
169
+ node,
170
+ messageId : 'missingAsync' ,
171
+ fix : fixer => {
180
172
if (
181
- method . type === AST_NODE_TYPES . MethodDefinition &&
182
- method . decorators . length
173
+ node . parent . type === AST_NODE_TYPES . MethodDefinition ||
174
+ ( node . parent . type === AST_NODE_TYPES . Property &&
175
+ node . parent . method )
183
176
) {
184
- const lastDecorator =
185
- method . decorators [ method . decorators . length - 1 ] ;
186
- keyToken = nullThrows (
187
- context . sourceCode . getTokenAfter ( lastDecorator ) ,
188
- NullThrowsReasons . MissingToken ( 'key token' , 'last decorator' ) ,
189
- ) ;
190
- }
177
+ // this function is a class method or object function property shorthand
178
+ const method = node . parent ;
191
179
192
- // if current token is a keyword like `static` or `public` then skip it
193
- while (
194
- keyToken . type === AST_TOKEN_TYPES . Keyword &&
195
- keyToken . range [ 0 ] < method . key . range [ 0 ]
196
- ) {
197
- keyToken = nullThrows (
198
- context . sourceCode . getTokenAfter ( keyToken ) ,
199
- NullThrowsReasons . MissingToken ( 'token' , 'keyword' ) ,
180
+ // the token to put `async` before
181
+ let keyToken = nullThrows (
182
+ context . sourceCode . getFirstToken ( method ) ,
183
+ NullThrowsReasons . MissingToken ( 'key token' , 'method' ) ,
200
184
) ;
201
- }
202
185
203
- // check if there is a space between key and previous token
204
- const insertSpace = ! context . sourceCode . isSpaceBetween (
205
- nullThrows (
206
- context . sourceCode . getTokenBefore ( keyToken ) ,
207
- NullThrowsReasons . MissingToken ( 'token' , 'keyword' ) ,
208
- ) ,
209
- keyToken ,
210
- ) ;
186
+ // if there are decorators then skip past them
187
+ if (
188
+ method . type === AST_NODE_TYPES . MethodDefinition &&
189
+ method . decorators . length
190
+ ) {
191
+ const lastDecorator =
192
+ method . decorators [ method . decorators . length - 1 ] ;
193
+ keyToken = nullThrows (
194
+ context . sourceCode . getTokenAfter ( lastDecorator ) ,
195
+ NullThrowsReasons . MissingToken ( 'key token' , 'last decorator' ) ,
196
+ ) ;
197
+ }
198
+
199
+ // if current token is a keyword like `static` or `public` then skip it
200
+ while (
201
+ keyToken . type === AST_TOKEN_TYPES . Keyword &&
202
+ keyToken . range [ 0 ] < method . key . range [ 0 ]
203
+ ) {
204
+ keyToken = nullThrows (
205
+ context . sourceCode . getTokenAfter ( keyToken ) ,
206
+ NullThrowsReasons . MissingToken ( 'token' , 'keyword' ) ,
207
+ ) ;
208
+ }
209
+
210
+ // check if there is a space between key and previous token
211
+ const insertSpace = ! context . sourceCode . isSpaceBetween (
212
+ nullThrows (
213
+ context . sourceCode . getTokenBefore ( keyToken ) ,
214
+ NullThrowsReasons . MissingToken ( 'token' , 'keyword' ) ,
215
+ ) ,
216
+ keyToken ,
217
+ ) ;
211
218
212
- let code = 'async ' ;
213
- if ( insertSpace ) {
214
- code = ` ${ code } ` ;
219
+ let code = 'async ' ;
220
+ if ( insertSpace ) {
221
+ code = ` ${ code } ` ;
222
+ }
223
+ return fixer . insertTextBefore ( keyToken , code ) ;
215
224
}
216
- return fixer . insertTextBefore ( keyToken , code ) ;
217
- }
218
225
219
- return fixer . insertTextBefore ( node , 'async ' ) ;
220
- } ,
221
- } ) ;
226
+ return fixer . insertTextBefore ( node , 'async ' ) ;
227
+ } ,
228
+ } ) ;
229
+ }
222
230
}
223
231
224
232
return {
0 commit comments