Skip to content

Commit

Permalink
feat: ignoreIIFE options and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
anikethsaha committed Mar 26, 2020
1 parent 0a10caf commit eb841a7
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 33 deletions.
29 changes: 29 additions & 0 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 @@ -73,6 +75,33 @@ void returnsPromise();
void Promise.reject('value');
```

### `ignoreIIFE`

This allows to skip checking of async iife

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

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

const foo = () =>
new Promise(res => {
(async function() {
await res(1);
})();
});
```

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

```ts
(async function() {
Promise.resolve();
})();
```

## When Not To Use It

If you do not use Promise-like values in your codebase or want to allow them to
Expand Down
33 changes: 20 additions & 13 deletions packages/eslint-plugin/src/rules/no-floating-promises.ts
@@ -1,22 +1,22 @@
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;
},
];

type MessageId = 'floating' | 'floatingVoid' | 'floatingFixVoid';

const possibleIifeCalleType = new Set([
'FunctionExpression',
'ArrowFunctionExpression',
]);

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

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

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

Expand Down Expand Up @@ -89,13 +91,18 @@ export default util.createRule<Options, MessageId>({
},
};

function isIife(node: ts.Node): Boolean {
if (node?.expression.type === 'CallExpression') {
if (possibleIifeCalleType.has(node?.expression?.callee.type)) {
return true;
}
function isAsyncIife(
node: TSESTree.ExpressionStatement | TSESTree.ArrowFunctionExpression,
): boolean {
if (node.expression.type !== AST_NODE_TYPES.CallExpression) {
return false;
}
return false;

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

function isUnhandledPromise(
Expand Down
180 changes: 160 additions & 20 deletions packages/eslint-plugin/tests/rules/no-floating-promises.test.ts
Expand Up @@ -250,31 +250,53 @@ async function test() {
returnsPromise()?.finally(() => {});
return returnsPromise();
}
`,
`
(async () => {
await something();
})();
`,
`
(async () => {
something();
})();
`,
'(async function foo(){})();',
`
function foo(){
(async function bar() {
})()
}
`,
`
const foo = () => new Promise((res) => {
// 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 @@ -368,6 +390,10 @@ async function test() {
}
`,
errors: [
{
line: 3,
messageId: 'floating',
},
{
line: 4,
messageId: 'floating',
Expand Down Expand Up @@ -662,5 +688,119 @@ 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: 2,
messageId: 'floating',
},
],
},
{
code: `(async function(){
await res(1)
})()`,
errors: [
{
line: 1,
messageId: 'floating',
},
],
},
{
code: `(async function(){
Promise.resolve();
})()`,
options: [{ ignoreIIFE: true }],
errors: [
{
line: 2,
messageId: 'floating',
},
],
},
{
code: `(async function(){
const promiseIntersection: Promise<number> & number;
promiseIntersection;
promiseIntersection.then(() => {})
promiseIntersection.catch();
promiseIntersection.finally();
})()`,
options: [{ ignoreIIFE: true }],
errors: [
{
line: 3,
messageId: 'floating',
},
{
line: 4,
messageId: 'floating',
},
{
line: 5,
messageId: 'floating',
},
{
line: 6,
messageId: 'floating',
},
],
},
],
});

0 comments on commit eb841a7

Please sign in to comment.