@typescript-eslint/eslint-plugin 7.11.1-alpha.10 → 7.11.1-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -43,6 +43,8 @@ exports.default = (0, util_1.createRule)({
|
|
|
43
43
|
nonPromiseAwait: 'Returning an awaited value that is not a promise is not allowed.',
|
|
44
44
|
disallowedPromiseAwait: 'Returning an awaited promise is not allowed in this context.',
|
|
45
45
|
requiredPromiseAwait: 'Returning an awaited promise is required in this context.',
|
|
46
|
+
requiredPromiseAwaitSuggestion: 'Add `await` before the expression. Use caution as this may impact control flow.',
|
|
47
|
+
disallowedPromiseAwaitSuggestion: 'Remove `await` before the expression. Use caution as this may impact control flow.',
|
|
46
48
|
},
|
|
47
49
|
schema: [
|
|
48
50
|
{
|
|
@@ -65,49 +67,75 @@ exports.default = (0, util_1.createRule)({
|
|
|
65
67
|
function exitFunction() {
|
|
66
68
|
scopeInfoStack.pop();
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
ancestor = ancestor.parent;
|
|
70
|
+
/**
|
|
71
|
+
* Tests whether a node is inside of an explicit error handling context
|
|
72
|
+
* (try/catch/finally) in a way that throwing an exception will have an
|
|
73
|
+
* impact on the program's control flow.
|
|
74
|
+
*/
|
|
75
|
+
function affectsExplicitErrorHandling(node) {
|
|
76
|
+
// If an error-handling block is followed by another error-handling block,
|
|
77
|
+
// control flow is affected by whether promises in it are awaited or not.
|
|
78
|
+
// Otherwise, we need to check recursively for nested try statements until
|
|
79
|
+
// we get to the top level of a function or the program. If by then,
|
|
80
|
+
// there's no offending error-handling blocks, it doesn't affect control
|
|
81
|
+
// flow.
|
|
82
|
+
const tryAncestorResult = findContainingTryStatement(node);
|
|
83
|
+
if (tryAncestorResult == null) {
|
|
84
|
+
return false;
|
|
85
85
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (ts.isTryStatement(ancestor.parent) &&
|
|
92
|
-
ts.isBlock(ancestor) &&
|
|
93
|
-
ancestor.parent.end === ancestor.end) {
|
|
86
|
+
const { tryStatement, block } = tryAncestorResult;
|
|
87
|
+
switch (block) {
|
|
88
|
+
case 'try':
|
|
89
|
+
// Try blocks are always followed by either a catch or finally,
|
|
90
|
+
// so exceptions thrown here always affect control flow.
|
|
94
91
|
return true;
|
|
92
|
+
case 'catch':
|
|
93
|
+
// Exceptions thrown in catch blocks followed by a finally block affect
|
|
94
|
+
// control flow.
|
|
95
|
+
if (tryStatement.finallyBlock != null) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
// Otherwise recurse.
|
|
99
|
+
return affectsExplicitErrorHandling(tryStatement);
|
|
100
|
+
case 'finally':
|
|
101
|
+
return affectsExplicitErrorHandling(tryStatement);
|
|
102
|
+
default: {
|
|
103
|
+
const __never = block;
|
|
104
|
+
throw new Error(`Unexpected block type: ${String(__never)}`);
|
|
95
105
|
}
|
|
96
|
-
ancestor = ancestor.parent;
|
|
97
106
|
}
|
|
98
|
-
return false;
|
|
99
107
|
}
|
|
100
|
-
|
|
108
|
+
/**
|
|
109
|
+
* A try _statement_ is the whole thing that encompasses try block,
|
|
110
|
+
* catch clause, and finally block. This function finds the nearest
|
|
111
|
+
* enclosing try statement (if present) for a given node, and reports which
|
|
112
|
+
* part of the try statement the node is in.
|
|
113
|
+
*/
|
|
114
|
+
function findContainingTryStatement(node) {
|
|
115
|
+
let child = node;
|
|
101
116
|
let ancestor = node.parent;
|
|
102
117
|
while (ancestor && !ts.isFunctionLike(ancestor)) {
|
|
103
118
|
if (ts.isTryStatement(ancestor)) {
|
|
104
|
-
|
|
119
|
+
let block;
|
|
120
|
+
if (child === ancestor.tryBlock) {
|
|
121
|
+
block = 'try';
|
|
122
|
+
}
|
|
123
|
+
else if (child === ancestor.catchClause) {
|
|
124
|
+
block = 'catch';
|
|
125
|
+
}
|
|
126
|
+
else if (child === ancestor.finallyBlock) {
|
|
127
|
+
block = 'finally';
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
tryStatement: ancestor,
|
|
131
|
+
block: (0, util_1.nullThrows)(block, 'Child of a try statement must be a try block, catch clause, or finally block'),
|
|
132
|
+
};
|
|
105
133
|
}
|
|
134
|
+
child = ancestor;
|
|
106
135
|
ancestor = ancestor.parent;
|
|
107
136
|
}
|
|
108
|
-
return
|
|
137
|
+
return undefined;
|
|
109
138
|
}
|
|
110
|
-
// function findTokensToRemove()
|
|
111
139
|
function removeAwait(fixer, node) {
|
|
112
140
|
// Should always be an await node; but let's be safe.
|
|
113
141
|
/* istanbul ignore if */ if (!(0, util_1.isAwaitExpression)(node)) {
|
|
@@ -163,29 +191,27 @@ exports.default = (0, util_1.createRule)({
|
|
|
163
191
|
if (isAwait && !isThenable) {
|
|
164
192
|
// any/unknown could be thenable; do not auto-fix
|
|
165
193
|
const useAutoFix = !((0, util_1.isTypeAnyType)(type) || (0, util_1.isTypeUnknownType)(type));
|
|
166
|
-
const fix = (fixer) => removeAwait(fixer, node);
|
|
167
194
|
context.report({
|
|
168
195
|
messageId: 'nonPromiseAwait',
|
|
169
196
|
node,
|
|
170
|
-
...(useAutoFix
|
|
171
|
-
|
|
172
|
-
:
|
|
173
|
-
|
|
174
|
-
{
|
|
175
|
-
messageId: 'nonPromiseAwait',
|
|
176
|
-
fix,
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
|
-
}),
|
|
197
|
+
...fixOrSuggest(useAutoFix, {
|
|
198
|
+
messageId: 'nonPromiseAwait',
|
|
199
|
+
fix: fixer => removeAwait(fixer, node),
|
|
200
|
+
}),
|
|
180
201
|
});
|
|
181
202
|
return;
|
|
182
203
|
}
|
|
204
|
+
const affectsErrorHandling = affectsExplicitErrorHandling(expression);
|
|
205
|
+
const useAutoFix = !affectsErrorHandling;
|
|
183
206
|
if (option === 'always') {
|
|
184
207
|
if (!isAwait && isThenable) {
|
|
185
208
|
context.report({
|
|
186
209
|
messageId: 'requiredPromiseAwait',
|
|
187
210
|
node,
|
|
188
|
-
|
|
211
|
+
...fixOrSuggest(useAutoFix, {
|
|
212
|
+
messageId: 'requiredPromiseAwaitSuggestion',
|
|
213
|
+
fix: fixer => insertAwait(fixer, node, isHigherPrecedenceThanAwait(expression)),
|
|
214
|
+
}),
|
|
189
215
|
});
|
|
190
216
|
}
|
|
191
217
|
return;
|
|
@@ -195,31 +221,33 @@ exports.default = (0, util_1.createRule)({
|
|
|
195
221
|
context.report({
|
|
196
222
|
messageId: 'disallowedPromiseAwait',
|
|
197
223
|
node,
|
|
198
|
-
|
|
224
|
+
...fixOrSuggest(useAutoFix, {
|
|
225
|
+
messageId: 'disallowedPromiseAwaitSuggestion',
|
|
226
|
+
fix: fixer => removeAwait(fixer, node),
|
|
227
|
+
}),
|
|
199
228
|
});
|
|
200
229
|
}
|
|
201
230
|
return;
|
|
202
231
|
}
|
|
203
232
|
if (option === 'in-try-catch') {
|
|
204
|
-
|
|
205
|
-
if (isAwait && !isInTryCatch) {
|
|
233
|
+
if (isAwait && !affectsErrorHandling) {
|
|
206
234
|
context.report({
|
|
207
235
|
messageId: 'disallowedPromiseAwait',
|
|
208
236
|
node,
|
|
209
|
-
|
|
237
|
+
...fixOrSuggest(useAutoFix, {
|
|
238
|
+
messageId: 'disallowedPromiseAwaitSuggestion',
|
|
239
|
+
fix: fixer => removeAwait(fixer, node),
|
|
240
|
+
}),
|
|
210
241
|
});
|
|
211
242
|
}
|
|
212
|
-
else if (!isAwait &&
|
|
213
|
-
if (inCatch(expression) && !hasFinallyBlock(expression)) {
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (isReturnPromiseInFinally(expression)) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
243
|
+
else if (!isAwait && affectsErrorHandling) {
|
|
219
244
|
context.report({
|
|
220
245
|
messageId: 'requiredPromiseAwait',
|
|
221
246
|
node,
|
|
222
|
-
|
|
247
|
+
...fixOrSuggest(useAutoFix, {
|
|
248
|
+
messageId: 'requiredPromiseAwaitSuggestion',
|
|
249
|
+
fix: fixer => insertAwait(fixer, node, isHigherPrecedenceThanAwait(expression)),
|
|
250
|
+
}),
|
|
223
251
|
});
|
|
224
252
|
}
|
|
225
253
|
return;
|
|
@@ -263,4 +291,7 @@ exports.default = (0, util_1.createRule)({
|
|
|
263
291
|
};
|
|
264
292
|
},
|
|
265
293
|
});
|
|
294
|
+
function fixOrSuggest(useFix, suggestion) {
|
|
295
|
+
return useFix ? { fix: suggestion.fix } : { suggest: [suggestion] };
|
|
296
|
+
}
|
|
266
297
|
//# sourceMappingURL=return-await.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"return-await.js","sourceRoot":"","sources":["../../src/rules/return-await.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AACA,oDAA0D;AAC1D,sDAAwC;AACxC,+CAAiC;AAEjC,
|
|
1
|
+
{"version":3,"file":"return-await.js","sourceRoot":"","sources":["../../src/rules/return-await.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,13 +26,15 @@ const defaultOptions: Options = 'in-try-catch';
|
|
|
26
26
|
|
|
27
27
|
### `in-try-catch`
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
In cases where returning an unawaited promise would cause unexpected error-handling control flow, the rule enforces that `await` must be used.
|
|
30
|
+
Otherwise, the rule enforces that `await` must _not_ be used.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- if you `return` a promise within a `
|
|
35
|
-
- if you `return` a promise within a `finally`, then it
|
|
32
|
+
Listing the error-handling cases exhaustively:
|
|
33
|
+
|
|
34
|
+
- if you `return` a promise within a `try`, then it must be `await`ed, since it will always be followed by a `catch` or `finally`.
|
|
35
|
+
- if you `return` a promise within a `catch`, and there is _no_ `finally`, then it must _not_ be `await`ed.
|
|
36
|
+
- if you `return` a promise within a `catch`, and there _is_ a `finally`, then it _must_ be `await`ed.
|
|
37
|
+
- if you `return` a promise within a `finally`, then it must not be `await`ed.
|
|
36
38
|
|
|
37
39
|
Examples of code with `in-try-catch`:
|
|
38
40
|
|
|
@@ -42,23 +44,34 @@ Examples of code with `in-try-catch`:
|
|
|
42
44
|
```ts option='"in-try-catch"'
|
|
43
45
|
async function invalidInTryCatch1() {
|
|
44
46
|
try {
|
|
45
|
-
return Promise.
|
|
46
|
-
} catch (e) {
|
|
47
|
+
return Promise.reject('try');
|
|
48
|
+
} catch (e) {
|
|
49
|
+
// Doesn't execute due to missing await.
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
async function invalidInTryCatch2() {
|
|
50
54
|
try {
|
|
51
55
|
throw new Error('error');
|
|
52
56
|
} catch (e) {
|
|
53
|
-
|
|
57
|
+
// Unnecessary await; rejections here don't impact control flow.
|
|
58
|
+
return await Promise.reject('catch');
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
// Prints 'starting async work', 'cleanup', 'async work done'.
|
|
57
63
|
async function invalidInTryCatch3() {
|
|
64
|
+
async function doAsyncWork(): Promise<void> {
|
|
65
|
+
console.log('starting async work');
|
|
66
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
67
|
+
console.log('async work done');
|
|
68
|
+
}
|
|
69
|
+
|
|
58
70
|
try {
|
|
59
71
|
throw new Error('error');
|
|
60
72
|
} catch (e) {
|
|
61
|
-
|
|
73
|
+
// Missing await.
|
|
74
|
+
return doAsyncWork();
|
|
62
75
|
} finally {
|
|
63
76
|
console.log('cleanup');
|
|
64
77
|
}
|
|
@@ -70,7 +83,8 @@ async function invalidInTryCatch4() {
|
|
|
70
83
|
} catch (e) {
|
|
71
84
|
throw new Error('error2');
|
|
72
85
|
} finally {
|
|
73
|
-
|
|
86
|
+
// Unnecessary await; rejections here don't impact control flow.
|
|
87
|
+
return await Promise.reject('finally');
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
|
|
@@ -89,23 +103,32 @@ async function invalidInTryCatch6() {
|
|
|
89
103
|
```ts option='"in-try-catch"'
|
|
90
104
|
async function validInTryCatch1() {
|
|
91
105
|
try {
|
|
92
|
-
return await Promise.
|
|
93
|
-
} catch (e) {
|
|
106
|
+
return await Promise.reject('try');
|
|
107
|
+
} catch (e) {
|
|
108
|
+
// Executes as expected.
|
|
109
|
+
}
|
|
94
110
|
}
|
|
95
111
|
|
|
96
112
|
async function validInTryCatch2() {
|
|
97
113
|
try {
|
|
98
114
|
throw new Error('error');
|
|
99
115
|
} catch (e) {
|
|
100
|
-
return Promise.
|
|
116
|
+
return Promise.reject('catch');
|
|
101
117
|
}
|
|
102
118
|
}
|
|
103
119
|
|
|
120
|
+
// Prints 'starting async work', 'async work done', 'cleanup'.
|
|
104
121
|
async function validInTryCatch3() {
|
|
122
|
+
async function doAsyncWork(): Promise<void> {
|
|
123
|
+
console.log('starting async work');
|
|
124
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
125
|
+
console.log('async work done');
|
|
126
|
+
}
|
|
127
|
+
|
|
105
128
|
try {
|
|
106
129
|
throw new Error('error');
|
|
107
130
|
} catch (e) {
|
|
108
|
-
return await
|
|
131
|
+
return await doAsyncWork();
|
|
109
132
|
} finally {
|
|
110
133
|
console.log('cleanup');
|
|
111
134
|
}
|
|
@@ -117,7 +140,7 @@ async function validInTryCatch4() {
|
|
|
117
140
|
} catch (e) {
|
|
118
141
|
throw new Error('error2');
|
|
119
142
|
} finally {
|
|
120
|
-
return Promise.
|
|
143
|
+
return Promise.reject('finally');
|
|
121
144
|
}
|
|
122
145
|
}
|
|
123
146
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescript-eslint/eslint-plugin",
|
|
3
|
-
"version": "7.11.1-alpha.
|
|
3
|
+
"version": "7.11.1-alpha.12",
|
|
4
4
|
"description": "TypeScript plugin for ESLint",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@eslint-community/regexpp": "^4.10.0",
|
|
65
|
-
"@typescript-eslint/scope-manager": "7.11.1-alpha.
|
|
66
|
-
"@typescript-eslint/type-utils": "7.11.1-alpha.
|
|
67
|
-
"@typescript-eslint/utils": "7.11.1-alpha.
|
|
68
|
-
"@typescript-eslint/visitor-keys": "7.11.1-alpha.
|
|
65
|
+
"@typescript-eslint/scope-manager": "7.11.1-alpha.12",
|
|
66
|
+
"@typescript-eslint/type-utils": "7.11.1-alpha.12",
|
|
67
|
+
"@typescript-eslint/utils": "7.11.1-alpha.12",
|
|
68
|
+
"@typescript-eslint/visitor-keys": "7.11.1-alpha.12",
|
|
69
69
|
"graphemer": "^1.4.0",
|
|
70
70
|
"ignore": "^5.3.1",
|
|
71
71
|
"natural-compare": "^1.4.0",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"@types/marked": "^5.0.2",
|
|
77
77
|
"@types/mdast": "^4.0.3",
|
|
78
78
|
"@types/natural-compare": "*",
|
|
79
|
-
"@typescript-eslint/rule-schema-to-typescript-types": "7.11.1-alpha.
|
|
80
|
-
"@typescript-eslint/rule-tester": "7.11.1-alpha.
|
|
79
|
+
"@typescript-eslint/rule-schema-to-typescript-types": "7.11.1-alpha.12",
|
|
80
|
+
"@typescript-eslint/rule-tester": "7.11.1-alpha.12",
|
|
81
81
|
"ajv": "^6.12.6",
|
|
82
82
|
"cross-env": "^7.0.3",
|
|
83
83
|
"cross-fetch": "*",
|