Skip to content

Commit

Permalink
fix(eslint-plugin): [no-floating-promises] handle finally callback (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
a-tarasyuk committed Feb 19, 2020
1 parent 660bace commit 1aa7135
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/eslint-plugin/docs/rules/no-floating-promises.md
Expand Up @@ -20,6 +20,8 @@ async function returnsPromise() {
returnsPromise().then(() => {});

Promise.reject('value').catch();

Promise.reject('value').finally();
```

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

Promise.reject('value').catch(() => {});

Promise.reject('value').finally(() => {});
```

## Options
Expand Down
13 changes: 12 additions & 1 deletion packages/eslint-plugin/src/rules/no-floating-promises.ts
Expand Up @@ -114,7 +114,8 @@ export default util.createRule<Options, MessageId>({
// `.catch()` that handles the promise.
return (
!isPromiseCatchCallWithHandler(node) &&
!isPromiseThenCallWithRejectionHandler(node)
!isPromiseThenCallWithRejectionHandler(node) &&
!isPromiseFinallyCallWithHandler(node)
);
} else if (ts.isConditionalExpression(node)) {
// We must be getting the promise-like value from one of the branches of the
Expand Down Expand Up @@ -216,3 +217,13 @@ function isPromiseThenCallWithRejectionHandler(
expression.arguments.length >= 2
);
}

function isPromiseFinallyCallWithHandler(
expression: ts.CallExpression,
): boolean {
return (
tsutils.isPropertyAccessExpression(expression.expression) &&
expression.expression.name.text === 'finally' &&
expression.arguments.length >= 1
);
}
56 changes: 56 additions & 0 deletions packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
Expand Up @@ -19,7 +19,9 @@ async function test() {
await Promise.resolve("value");
Promise.resolve("value").then(() => {}, () => {});
Promise.resolve("value").then(() => {}).catch(() => {});
Promise.resolve("value").then(() => {}).catch(() => {}).finally(() => {});
Promise.resolve("value").catch(() => {});
Promise.resolve("value").finally(() => {});
return Promise.resolve("value");
}
`,
Expand All @@ -36,7 +38,9 @@ async function test() {
await Promise.reject(new Error("message"));
Promise.reject(new Error("message")).then(() => {}, () => {});
Promise.reject(new Error("message")).then(() => {}).catch(() => {});
Promise.reject(new Error("message")).then(() => {}).catch(() => {}).finally(() => {});
Promise.reject(new Error("message")).catch(() => {});
Promise.reject(new Error("message")).finally(() => {});
return Promise.reject(new Error("message"));
}
`,
Expand All @@ -45,7 +49,9 @@ async function test() {
await (async () => true)();
(async () => true)().then(() => {}, () => {});
(async () => true)().then(() => {}).catch(() => {});
(async () => true)().then(() => {}).catch(() => {}).finally(() => {});
(async () => true)().catch(() => {});
(async () => true)().finally(() => {});
return (async () => true)();
}
`,
Expand All @@ -55,7 +61,9 @@ async function test() {
await returnsPromise();
returnsPromise().then(() => {}, () => {});
returnsPromise().then(() => {}).catch(() => {});
returnsPromise().then(() => {}).catch(() => {}).finally(() => {});
returnsPromise().catch(() => {});
returnsPromise().finally(() => {});
return returnsPromise();
}
`,
Expand All @@ -64,6 +72,7 @@ async function test() {
const x = Promise.resolve();
const y = x.then(() => {});
y.catch(() => {});
y.finally(() => {});
}
`,
`
Expand All @@ -74,6 +83,7 @@ async function test() {
`
async function test() {
Promise.resolve().catch(() => {}), 123;
Promise.resolve().finally(() => {}), 123;
123, Promise.resolve().then(() => {}, () => {});
123, Promise.resolve().then(() => {}, () => {}), 123;
}
Expand All @@ -95,7 +105,9 @@ async function test() {
await promiseValue;
promiseValue.then(() => {}, () => {});
promiseValue.then(() => {}).catch(() => {});
promiseValue.then(() => {}).catch(() => {}).finally(() => {});
promiseValue.catch(() => {});
promiseValue.finally(() => {});
return promiseValue;
}
`,
Expand All @@ -106,7 +118,9 @@ async function test() {
await promiseUnion;
promiseUnion.then(() => {}, () => {});
promiseUnion.then(() => {}).catch(() => {});
promiseUnion.then(() => {}).catch(() => {}).finally(() => {});
promiseUnion.catch(() => {});
promiseValue.finally(() => {});
return promiseUnion;
}
`,
Expand All @@ -117,7 +131,9 @@ async function test() {
await promiseIntersection;
promiseIntersection.then(() => {}, () => {});
promiseIntersection.then(() => {}).catch(() => {});
promiseIntersection.then(() => {}).catch(() => {}).finally(() => {});
promiseIntersection.catch(() => {});
promiseIntersection.finally(() => {});
return promiseIntersection;
}
`,
Expand All @@ -129,7 +145,9 @@ async function test() {
await canThen;
canThen.then(() => {}, () => {});
canThen.then(() => {}).catch(() => {});
canThen.then(() => {}).catch(() => {}).finally(() => {});
canThen.catch(() => {});
canThen.finally(() => {});
return canThen;
}
`,
Expand Down Expand Up @@ -214,7 +232,9 @@ async function test() {
await promise;
promise.then(() => {}, () => {});
promise.then(() => {}).catch(() => {});
promise.then(() => {}).catch(() => {}).finally(() => {});
promise.catch(() => {});
promise.finally(() => {});
return promise;
}
`,
Expand All @@ -227,6 +247,7 @@ async function test() {
returnsPromise()?.then(() => {}, () => {});
returnsPromise()?.then(() => {})?.catch(() => {});
returnsPromise()?.catch(() => {});
returnsPromise()?.finally(() => {});
return returnsPromise();
}
`,
Expand All @@ -239,6 +260,7 @@ async function test() {
Promise.resolve("value");
Promise.resolve("value").then(() => {});
Promise.resolve("value").catch();
Promise.resolve("value").finally();
}
`,
errors: [
Expand All @@ -254,6 +276,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
{
line: 6,
messageId: 'floating',
},
],
},
{
Expand Down Expand Up @@ -286,6 +312,7 @@ async function test() {
Promise.reject(new Error("message"));
Promise.reject(new Error("message")).then(() => {});
Promise.reject(new Error("message")).catch();
Promise.reject(new Error("message")).finally();
}
`,
errors: [
Expand All @@ -301,6 +328,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
{
line: 6,
messageId: 'floating',
},
],
},
{
Expand All @@ -309,6 +340,7 @@ async function test() {
(async () => true)();
(async () => true)().then(() => {});
(async () => true)().catch();
(async () => true)().finally();
}
`,
errors: [
Expand All @@ -324,6 +356,10 @@ async function test() {
line: 5,
messageId: 'floating',
},
{
line: 6,
messageId: 'floating',
},
],
},
{
Expand All @@ -334,6 +370,7 @@ async function test() {
returnsPromise();
returnsPromise().then(() => {});
returnsPromise().catch();
returnsPromise().finally();
}
`,
errors: [
Expand All @@ -349,6 +386,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
{
line: 8,
messageId: 'floating',
},
],
},
{
Expand Down Expand Up @@ -440,6 +481,7 @@ async function test() {
promiseValue;
promiseValue.then(() => {});
promiseValue.catch();
promiseValue.finally();
}
`,
errors: [
Expand All @@ -455,6 +497,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
{
line: 8,
messageId: 'floating',
},
],
},
{
Expand All @@ -480,6 +526,7 @@ async function test() {
promiseIntersection;
promiseIntersection.then(() => {})
promiseIntersection.catch();
promiseIntersection.finally();
}
`,
errors: [
Expand All @@ -495,6 +542,10 @@ async function test() {
line: 7,
messageId: 'floating',
},
{
line: 8,
messageId: 'floating',
},
],
},
{
Expand All @@ -506,6 +557,7 @@ async function test() {
canThen;
canThen.then(() => {});
canThen.catch();
canThen.finally();
}
`,
errors: [
Expand All @@ -521,6 +573,10 @@ async function test() {
line: 8,
messageId: 'floating',
},
{
line: 9,
messageId: 'floating',
},
],
},
{
Expand Down

0 comments on commit 1aa7135

Please sign in to comment.