8000 fix(eslint-plugin): [no-floating-promises] handle finally callback (#… · Bertrand/typescript-eslint@1aa7135 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1aa7135

Browse files
authored
fix(eslint-plugin): [no-floating-promises] handle finally callback (typescript-eslint#1620)
1 parent 660bace commit 1aa7135

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

packages/eslint-plugin/docs/rules/no-floating-promises.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ async function returnsPromise() {
2020
returnsPromise().then(() => {});
2121

2222
Promise.reject('value').catch();
23+
24+
Promise.reject('value').finally();
2325
```
2426

2527
Examples of **correct** code for this rule:
@@ -37,6 +39,8 @@ returnsPromise().then(
3739
);
3840

3941
Promise.reject('value').catch(() => {});
42+
43+
Promise.reject('value').finally(() => {});
4044
```
4145

4246
## Options

packages/eslint-plugin/src/rules/no-floating-promises.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ export default util.createRule<Options, MessageId>({
114114
// `.catch()` that handles the promise.
115115
return (
116116
!isPromiseCatchCallWithHandler(node) &&
117-
!isPromiseThenCallWithRejectionHandler(node)
117+
!isPromiseThenCallWithRejectionHandler(node) &&
118+
!isPromiseFinallyCallWithHandler(node)
118119
);
119120
} else if (ts.isConditionalExpression(node)) {
120121
// We must be getting the promise-like value from one of the branches of the
@@ -216,3 +217,13 @@ function isPromiseThenCallWithRejectionHandler(
216217
expression.arguments.length >= 2
217218
);
218219
}
220+
221+
function isPromiseFinallyCallWithHandler(
222+
expression: ts.CallExpression,
223+
): boolean {
224+
return (
225+
tsutils.isPropertyAccessExpression(expression.expression) &&
226+
expression.expression.name.text === 'finally' &&
227+
expression.arguments.length >= 1
228+
);
229+
}

packages/eslint-plugin/tests/rules/no-floating-promises.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ async function test() {
1919
await Promise.resolve("value");
2020
Promise.resolve("value").then(() => {}, () => {});
2121
Promise.resolve("value").then(() => {}).catch(() => {});
22+
Promise.resolve("value").then(() => {}).catch(() => {}).finally(() => {});
2223
Promise.resolve("value").catch(() => {});
24+
Promise.resolve("value").finally(() => {});
2325
return Promise.resolve("value");
2426
}
2527
`,
@@ -36,7 +38,9 @@ async function test() {
3638
await Promise.reject(new Error("message"));
3739
Promise.reject(new Error("message")).then(() => {}, () => {});
3840
Promise.reject(new Error("message")).then(() => {}).catch(() => {});
41+
Promise.reject(new Error("message")).then(() => {}).catch(() => {}).finally(() => {});
3942
Promise.reject(new Error("message")).catch(() => {});
43+
Promise.reject(new Error("message")).finally(() => {});
4044
return Promise.reject(new Error("message"));
4145
}
4246
`,
@@ -45,7 +49,9 @@ async function test() {
4549
await (async () => true)();
4650
(async () => true)().then(() => {}, () => {});
4751
(async () => true)().then(() => {}).catch(() => {});
52+
(async () => true)().then(() => {}).catch(() => {}).finally(() => {});
4853
(async () => true)().catch(() => {});
54+
(async () => true)().finally(() => {});
4955
return (async () => true)();
5056
}
5157
`,
@@ -55,7 +61,9 @@ async function test() {
5561
await returnsPromise();
5662
returnsPromise().then(() => {}, () => {});
5763
returnsPromise().then(() => {}).catch(() => {});
64+
returnsPromise().then(() => {}).catch(() => {}).finally(() => {});
5865
returnsPromise().catch(() => {});
66+
returnsPromise().finally(() => {});
5967
return returnsPromise();
6068
}
6169
`,
@@ -64,6 +72,7 @@ async function test() {
6472
const x = Promise.resolve();
6573
const y = x.then(() => {});
6674
y.catch(() => {});
75+
y.finally(() => {});
6776
}
6877
`,
6978
`
@@ -74,6 +83,7 @@ async function test() {
7483
`
7584
async function test() {
7685
Promise.resolve().catch(() => {}), 123;
86+
Promise.resolve().finally(() => {}), 123;
7787
123, Promise.resolve().then(() => {}, () => {});
7888
123, Promise.resolve().then(() => {}, () => {}), 123;
7989
}
@@ -95,7 +105,9 @@ async function test() {
95105
await promiseValue;
96106
promiseValue.then(() => {}, () => {});
97107
promiseValue.then(() => {}).catch(() => {});
108+
promiseValue.then(() => {}).catch(() => {}).finally(() => {});
98109
promiseValue.catch(() => {});
110+
promiseValue.finally(() => {});
99111
return promiseValue;
100112
}
101113
`,
@@ -106,7 +118,9 @@ async function test() {
106118
await promiseUnion;
107119
promiseUnion.then(() => {}, () => {});
108120
promiseUnion.then(() => {}).catch(() => {});
121+
promiseUnion.then(() => {}).catch(() => {}).finally(() => {});
109122
promiseUnion.catch(() => {});
123+
promiseValue.finally(() => {});
110124
return promiseUnion;
111125
}
112126
`,
@@ -117,7 +131,9 @@ async function test() {
117131
await promiseIntersection;
118132
promiseIntersection.then(() => {}, () => {});
119133
promiseIntersection.then(() => {}).catch(() => {});
134+
promiseIntersection.then(() => {}).catch(() => {}).finally(() => {});
120135
promiseIntersection.catch(() => {});
136+
promiseIntersection.finally(() => {});
121137
return promiseIntersection;
122138
}
123139
`,
@@ -129,7 +145,9 @@ async function test() {
129145
await canThen;
130146
canThen.then(() => {}, () => {});
131147
canThen.then(() => {}).catch(() => {});
148+
canThen.then(() => {}).catch(() => {}).finally(() => {});
132149
canThen.catch(() => {});
150+
canThen.finally(() => {});
133151
return canThen;
134152
}
135153
`,
@@ -214,7 +232,9 @@ async function test() {
214232
await promise;
215233
promise.then(() => {}, () => {});
216234
promise.then(() => {}).catch(() => {});
235+
promise.then(() => {}).catch(() => {}).finally(() => {});
217236
promise.catch(() => {});
237+
promise.finally(() => {});
218238 return promise;
219239
}
220240
`,
@@ -227,6 +247,7 @@ async function test() {
227247
returnsPromise()?.then(() => {}, () => {});
228248
returnsPromise()?.then(() => {})?.catch(() => {});
229249
returnsPromise()?.catch(() => {});
250+
returnsPromise()?.finally(() => {});
230251
return returnsPromise();
231252
}
232253
`,
@@ -239,6 +260,7 @@ async function test() {
239260
Promise.resolve("value");
240261
Promise.resolve("value").then(() => {});
241262
Promise.resolve("value").catch();
263+
Promise.resolve("value").finally();
242264
}
243265
`,
244266
errors: [
@@ -254,6 +276,10 @@ async function test() {
254276
line: 5,
255277
messageId: 'floating',
256278
},
279+
{
280+
line: 6,
281+
messageId: 'floating',
282+
},
257283
],
258284
},
259285
{
@@ -286,6 +312,7 @@ async function test() {
286312
Promise.reject(new Error("message"));
287313
Promise.reject(new Error("message")).then(() => {});
288314
Promise.reject(new Error("message")).catch();
315+
Promise.reject(new Error("message")).finally();
289316
}
290317
`,
291318
errors: [
@@ -301,6 +328,10 @@ async function test() {
301328
line: 5,
302329
messageId: 'floating',
303330
},
331+
{
332+
line: 6,
333+
messageId: 'floating',
334+
},
304335
],
305336
},
306337
{
@@ -309,6 +340,7 @@ async function test() {
309340
(async () => true)();
310341
(async () => true)().then(() => {});
311342
(async () => true)().catch();
343+
(async () => true)().finally();
312344
}
313345
`,
314346
errors: [
@@ -324,6 +356,10 @@ async function test() {
324356
line: 5,
325357
messageId: 'floating',
326358
},
359+
{
360+
line: 6,
361+
messageId: 'floating',
362+
},
327363
],
328364
},
329365
{
@@ -334,6 +370,7 @@ async function test() {
334370
returnsPromise();
335371
returnsPromise().then(() => {});
336372
returnsPromise().catch();
373+
returnsPromise().finally();
337374
}
338375
`,
339376
errors: [
@@ -349,6 +386,10 @@ async function test() {
349386
line: 7,
350387
messageId: 'floating',
351388
},
389+
{
390+
line: 8,
391+
messageId: 'floating',
392+
},
352393
],
353394
},
354395
{
@@ -440,6 +481,7 @@ async function test() {
440481
promiseValue;
441482
promiseValue.then(() => {});
442483
promiseValue.catch();
484+
promiseValue.finally();
443485
}
444486
`,
445487
errors: [
@@ -455,6 +497,10 @@ async function test() {
455497
line: 7,
456498
messageId: 'floating',
457499
},
500+
{
501+
line: 8,
502+
messageId: 'floating',
503+
},
458504
],
459505
},
460506
{
@@ -480,6 +526,7 @@ async function test() {
480526
promiseIntersection;
481527
promiseIntersection.then(() => {})
482528
promiseIntersection.catch();
529+
promiseIntersection.finally();
483530
}
484531
`,
485532
errors: [
@@ -495,6 +542,10 @@ async function test() {
495542
line: 7,
496543
messageId: 'floating',
497544
},
545+
{
546+
line: 8,
547+
messageId: 'floating',
548+
},
498549
],
499550
},
500551
{
@@ -506,6 +557,7 @@ async function test() {
506557
canThen;
507558
canThen.then(() => {});
508559
canThen.catch();
560+
canThen.finally();
509561
}
510562
`,
511563
errors: [
@@ -521,6 +573,10 @@ async function test() {
521573
line: 8,
522574
messageId: 'floating',
523575
},
576+
{
577+
line: 9,
578+
messageId: 'floating',
579+
},
524580
],
525581
},
526582
{

0 commit comments

Comments
 (0)
0