Skip to content

Commit

Permalink
feat(eslint-plugin): [no-floating-promise] add option to ignore IIFEs (
Browse files Browse the repository at this point in the history
  • Loading branch information
anikethsaha committed Apr 20, 2020
1 parent c5106dd commit cea51bf
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 5 deletions.
24 changes: 21 additions & 3 deletions packages/eslint-plugin/docs/rules/no-floating-promises.md
Expand Up @@ -51,6 +51,8 @@ The rule accepts an options object with the following properties:
type Options = {
// if true, checking void expressions will be skipped
ignoreVoid?: boolean;
// if true, checking for async iife will be skipped
ignoreIIFE?: boolean;
};

const defaults = {
Expand All @@ -60,7 +62,8 @@ const defaults = {

### `ignoreVoid`

This allows to easily suppress false-positives with void operator.
This allows you to stop the rule reporting promises consumed with void operator.
This can be a good way to explicitly mark a promise as intentionally not awaited.

Examples of **correct** code for this rule with `{ ignoreVoid: true }`:

Expand All @@ -73,10 +76,25 @@ void returnsPromise();
void Promise.reject('value');
```

### `ignoreIIFE`

This allows you to skip checking of async iife

Examples of **correct** code for this rule with `{ ignoreIIFE: true }`:

```ts
await(async function() {
await res(1);
})();

(async function() {
await res(1);
})();
```

## When Not To Use It

If you do not use Promise-like values in your codebase or want to allow them to
remain unhandled.
If you do not use Promise-like values in your codebase, or want to allow them to remain unhandled.

## Related to

Expand Down
26 changes: 25 additions & 1 deletion packages/eslint-plugin/src/rules/no-floating-promises.ts
@@ -1,12 +1,17 @@
import * as tsutils from 'tsutils';
import * as ts from 'typescript';
import { TSESLint } from '@typescript-eslint/experimental-utils';
import {
TSESLint,
AST_NODE_TYPES,
TSESTree,
} from '@typescript-eslint/experimental-utils';

import * as util from '../util';

type Options = [
{
ignoreVoid?: boolean;
ignoreIIFE?: boolean;
},
];

Expand All @@ -33,6 +38,7 @@ export default util.createRule<Options, MessageId>({
type: 'object',
properties: {
ignoreVoid: { type: 'boolean' },
ignoreIIFE: { type: 'boolean' },
},
additionalProperties: false,
},
Expand All @@ -42,6 +48,7 @@ export default util.createRule<Options, MessageId>({
defaultOptions: [
{
ignoreVoid: false,
ignoreIIFE: false,
},
],

Expand All @@ -54,6 +61,10 @@ export default util.createRule<Options, MessageId>({
ExpressionStatement(node): void {
const { expression } = parserServices.esTreeNodeToTSNodeMap.get(node);

if (options.ignoreIIFE && isAsyncIife(node)) {
return;
}

if (isUnhandledPromise(checker, expression)) {
if (options.ignoreVoid) {
context.report({
Expand All @@ -80,6 +91,19 @@ export default util.createRule<Options, MessageId>({
},
};

function isAsyncIife(node: TSESTree.ExpressionStatement): boolean {
if (node.expression.type !== AST_NODE_TYPES.CallExpression) {
return false;
}

return (
node.expression.type === AST_NODE_TYPES.CallExpression &&
(node.expression.callee.type ===
AST_NODE_TYPES.ArrowFunctionExpression ||
node.expression.callee.type === AST_NODE_TYPES.FunctionExpression)
);
}

function isUnhandledPromise(
checker: ts.TypeChecker,
node: ts.Node,
Expand Down
169 changes: 169 additions & 0 deletions packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
Expand Up @@ -335,6 +335,54 @@ async function test() {
return returnsPromise();
}
`,
// ignoreIIFE
{
code: `
(async () => {
await something();
})();
`,
options: [{ ignoreIIFE: true }],
},
{
code: `
(async () => {
something();
})();
`,
options: [{ ignoreIIFE: true }],
},
{
code: '(async function foo() {})();',
options: [{ ignoreIIFE: true }],
},
{
code: `
function foo() {
(async function bar() {})();
}
`,
options: [{ ignoreIIFE: true }],
},
{
code: `
const foo = () =>
new Promise(res => {
(async function() {
await res(1);
})();
});
`,
options: [{ ignoreIIFE: true }],
},
{
code: `
(async function() {
await res(1);
})();
`,
options: [{ ignoreIIFE: true }],
},
],

invalid: [
Expand Down Expand Up @@ -726,5 +774,126 @@ async function test() {
},
],
},
{
code: `
(async () => {
await something();
})();
`,
errors: [
{
line: 2,
messageId: 'floating',
},
],
},
{
code: `
(async () => {
something();
})();
`,
errors: [
{
line: 2,
messageId: 'floating',
},
],
},
{
code: '(async function foo() {})();',
errors: [
{
line: 1,
messageId: 'floating',
},
],
},
{
code: `
function foo() {
(async function bar() {})();
}
`,
errors: [
{
line: 3,
messageId: 'floating',
},
],
},
{
code: `
const foo = () =>
new Promise(res => {
(async function() {
await res(1);
})();
});
`,
errors: [
{
line: 4,
messageId: 'floating',
},
],
},
{
code: `
(async function() {
await res(1);
})();
`,
errors: [
{
line: 2,
messageId: 'floating',
},
],
},
{
code: `
(async function() {
Promise.resolve();
})();
`,
options: [{ ignoreIIFE: true }],
errors: [
{
line: 3,
messageId: 'floating',
},
],
},
{
code: `
(async function() {
const promiseIntersection: Promise<number> & number;
promiseIntersection;
promiseIntersection.then(() => {});
promiseIntersection.catch();
promiseIntersection.finally();
})();
`,
options: [{ ignoreIIFE: true }],
errors: [
{
line: 4,
messageId: 'floating',
},
{
line: 5,
messageId: 'floating',
},
{
line: 6,
messageId: 'floating',
},
{
line: 7,
messageId: 'floating',
},
],
},
],
});
3 changes: 2 additions & 1 deletion packages/typescript-estree/src/ts-estree/ts-estree.ts
Expand Up @@ -392,7 +392,8 @@ export type LeftHandSideExpression =
| PrimaryExpression
| TaggedTemplateExpression
| TSNonNullExpression
| TSAsExpression;
| TSAsExpression
| ArrowFunctionExpression;
export type Literal =
| BooleanLiteral
| NumberLiteral
Expand Down

0 comments on commit cea51bf

Please sign in to comment.