@@ -3,17 +3,19 @@ import { ASTUtils } from '@typescript-eslint/utils';
3
3
import { createTestingLibraryRule } from '../create-testing-library-rule' ;
4
4
import {
5
5
findClosestCallExpressionNode ,
6
+ findClosestFunctionExpressionNode ,
6
7
getDeepestIdentifierNode ,
7
8
getFunctionName ,
8
9
getInnermostReturningFunction ,
10
+ getReferenceNode ,
9
11
getVariableReferences ,
10
12
isCallExpression ,
11
13
isObjectPattern ,
12
14
isPromiseHandled ,
13
15
isProperty ,
14
16
} from '../node-utils' ;
15
17
16
- import type { TSESTree } from '@typescript-eslint/utils' ;
18
+ import type { TSESLint , TSESTree } from '@typescript-eslint/utils' ;
17
19
18
20
export const RULE_NAME = 'await-async-utils' ;
19
21
export type MessageIds = 'asyncUtilWrapper' | 'awaitAsyncUtil' ;
@@ -40,6 +42,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
40
42
'Promise returned from {{ name }} wrapper over async util must be handled' ,
41
43
} ,
42
44
schema : [ ] ,
45
+ fixable : 'code' ,
43
46
} ,
44
47
defaultOptions : [ ] ,
45
48
@@ -90,6 +93,33 @@ export default createTestingLibraryRule<Options, MessageIds>({
90
93
}
91
94
}
92
95
}
96
+ function wrapWithFunctionExpressionFix (
97
+ fixer : TSESLint . RuleFixer ,
98
+ ruleFix : TSESLint . RuleFix ,
99
+ functionExpression :
100
+ | TSESTree . ArrowFunctionExpression
101
+ | TSESTree . FunctionDeclaration
102
+ | TSESTree . FunctionExpression
103
+ | null
104
+ ) {
105
+ if ( functionExpression && ! functionExpression . async ) {
106
+ /**
107
+ * Mutate the actual node so if other nodes exist in this
108
+ * function expression body they don't also try to fix it.
109
+ */
110
+ functionExpression . async = true ;
111
+
112
+ return [ ruleFix , fixer . insertTextBefore ( functionExpression , 'async ' ) ] ;
113
+ }
114
+ return ruleFix ;
115
+ }
116
+
117
+ function insertAwaitBeforeNode (
118
+ fixer : TSESLint . RuleFixer ,
119
+ node : TSESTree . Node
120
+ ) {
121
+ return fixer . insertTextBefore ( node , 'await ' ) ;
122
+ }
93
123
94
124
/*
95
125
Either we report a direct usage of an async util or a usage of a wrapper
@@ -155,6 +185,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
155
185
context ,
156
186
closestCallExpression . parent
157
187
) ;
188
+ const functionExpression = findClosestFunctionExpressionNode ( node ) ;
158
189
159
190
if ( references . length === 0 ) {
160
191
if ( ! isPromiseHandled ( callExpressionIdentifier ) ) {
@@ -164,6 +195,17 @@ export default createTestingLibraryRule<Options, MessageIds>({
164
195
data : {
165
196
name : callExpressionIdentifier . name ,
166
197
} ,
198
+ fix : ( fixer ) => {
199
+ const referenceNode = getReferenceNode (
200
+ callExpressionIdentifier
201
+ ) ;
202
+ const awaitFix = insertAwaitBeforeNode ( fixer , referenceNode ) ;
203
+ return wrapWithFunctionExpressionFix (
204
+ fixer ,
205
+ awaitFix ,
206
+ functionExpression
207
+ ) ;
208
+ } ,
167
209
} ) ;
168
210
}
169
211
} else {
@@ -176,6 +218,14 @@ export default createTestingLibraryRule<Options, MessageIds>({
176
218
data : {
177
219
name : callExpressionIdentifier . name ,
178
220
} ,
221
+ fix : ( fixer ) => {
222
+ const awaitFix = insertAwaitBeforeNode ( fixer , referenceNode ) ;
223
+ return wrapWithFunctionExpressionFix (
224
+ fixer ,
225
+ awaitFix ,
226
+ functionExpression
227
+ ) ;
228
+ } ,
179
229
} ) ;
180
230
return ;
181
231
}
0 commit comments