From 56c00b32e47967ec0fb065e49063317e02181d0b Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Tue, 19 Nov 2019 09:09:23 -0800 Subject: [PATCH] fix(eslint-plugin): [req-await] crash on nonasync promise return (#1228) --- .../eslint-plugin/src/rules/require-await.ts | 19 +- .../tests/rules/require-await.test.ts | 181 ++++++++---------- .../eslint-plugin/typings/eslint-rules.d.ts | 2 +- 3 files changed, 90 insertions(+), 112 deletions(-) diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index 5f27f8ad8a1..4db47f9e075 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -42,13 +42,12 @@ export default util.createRule({ } return { - 'FunctionDeclaration[async = true]': rules.FunctionDeclaration, - 'FunctionExpression[async = true]': rules.FunctionExpression, + FunctionDeclaration: rules.FunctionDeclaration, + FunctionExpression: rules.FunctionExpression, + ArrowFunctionExpression: rules.ArrowFunctionExpression, 'ArrowFunctionExpression[async = true]'( node: TSESTree.ArrowFunctionExpression, ): void { - rules.ArrowFunctionExpression(node); - // If body type is not BlockStatment, we need to check the return type here if (node.body.type !== AST_NODE_TYPES.BlockStatement) { const expression = parserServices.esTreeNodeToTSNodeMap.get( @@ -56,15 +55,13 @@ export default util.createRule({ ); if (expression && isThenableType(expression)) { // tell the base rule to mark the scope as having an await so it ignores it - rules.AwaitExpression(node as never); + rules.AwaitExpression(); } } }, - 'FunctionDeclaration[async = true]:exit': - rules['FunctionDeclaration:exit'], - 'FunctionExpression[async = true]:exit': rules['FunctionExpression:exit'], - 'ArrowFunctionExpression[async = true]:exit': - rules['ArrowFunctionExpression:exit'], + 'FunctionDeclaration:exit': rules['FunctionDeclaration:exit'], + 'FunctionExpression:exit': rules['FunctionExpression:exit'], + 'ArrowFunctionExpression:exit': rules['ArrowFunctionExpression:exit'], AwaitExpression: rules.AwaitExpression, ForOfStatement: rules.ForOfStatement, @@ -74,7 +71,7 @@ export default util.createRule({ >(node); if (expression && isThenableType(expression)) { // tell the base rule to mark the scope as having an await so it ignores it - rules.AwaitExpression(node as never); + rules.AwaitExpression(); } }, }; diff --git a/packages/eslint-plugin/tests/rules/require-await.test.ts b/packages/eslint-plugin/tests/rules/require-await.test.ts index 09b54bd3a99..fff294f7ccb 100644 --- a/packages/eslint-plugin/tests/rules/require-await.test.ts +++ b/packages/eslint-plugin/tests/rules/require-await.test.ts @@ -28,106 +28,87 @@ const noAwaitAsyncFunctionExpression: any = { ruleTester.run('require-await', rule, { valid: [ - { - // Non-async function declaration - code: `function numberOne(): number { - return 1; - }`, - }, - { - // Non-async function expression - code: `const numberOne = function(): number { - return 1; - }`, - }, - { - // Non-async arrow function expression (concise-body) - code: `const numberOne = (): number => 1;`, - }, - { - // Non-async arrow function expression (block-body) - code: `const numberOne = (): number => { - return 1; - };`, - }, - { - // Async function declaration with await - code: `async function numberOne(): Promise { - return await 1; - }`, - }, - { - // Async function expression with await - code: `const numberOne = async function(): Promise { - return await 1; - }`, - }, - { - // Async arrow function expression with await (concise-body) - code: `const numberOne = async (): Promise => await 1;`, - }, - { - // Async arrow function expression with await (block-body) - code: `const numberOne = async (): Promise => { - return await 1; - };`, - }, - { - // Async function declaration with promise return - code: `async function numberOne(): Promise { - return Promise.resolve(1); - }`, - }, - { - // Async function expression with promise return - code: `const numberOne = async function(): Promise { - return Promise.resolve(1); - }`, - }, - { - // Async arrow function with promise return (concise-body) - code: `const numberOne = async (): Promise => Promise.resolve(1);`, - }, - { - // Async arrow function with promise return (block-body) - code: `const numberOne = async (): Promise => { - return Promise.resolve(1); - };`, - }, - { - // Async function declaration with async function return - code: `async function numberOne(): Promise { - return getAsyncNumber(1); - } - async function getAsyncNumber(x: number): Promise { - return Promise.resolve(x); - }`, - }, - { - // Async function expression with async function return - code: `const numberOne = async function(): Promise { - return getAsyncNumber(1); - } - const getAsyncNumber = async function(x: number): Promise { - return Promise.resolve(x); - }`, - }, - { - // Async arrow function with async function return (concise-body) - code: `const numberOne = async (): Promise => getAsyncNumber(1); - const getAsyncNumber = async function(x: number): Promise { - return Promise.resolve(x); - }`, - }, - { - // Async arrow function with async function return (block-body) - code: `const numberOne = async (): Promise => { - return getAsyncNumber(1); - }; - const getAsyncNumber = async function(x: number): Promise { - return Promise.resolve(x); - }`, - }, + // Non-async function declaration + `function numberOne(): number { + return 1; + }`, + // Non-async function expression + `const numberOne = function(): number { + return 1; + }`, + // Non-async arrow function expression (concise-body) + `const numberOne = (): number => 1;`, + // Non-async arrow function expression (block-body) + `const numberOne = (): number => { + return 1; + };`, + // Non-async function that returns a promise + // https://github.com/typescript-eslint/typescript-eslint/issues/1226 + ` +function delay() { + return Promise.resolve(); +} + `, + ` +const delay = () => { + return Promise.resolve(); +} + `, + `const delay = () => Promise.resolve();`, + // Async function declaration with await + `async function numberOne(): Promise { + return await 1; + }`, + // Async function expression with await + `const numberOne = async function(): Promise { + return await 1; + }`, + // Async arrow function expression with await (concise-body) + `const numberOne = async (): Promise => await 1;`, + // Async arrow function expression with await (block-body) + `const numberOne = async (): Promise => { + return await 1; + };`, + // Async function declaration with promise return + `async function numberOne(): Promise { + return Promise.resolve(1); + }`, + // Async function expression with promise return + `const numberOne = async function(): Promise { + return Promise.resolve(1); + }`, + // Async arrow function with promise return (concise-body) + `const numberOne = async (): Promise => Promise.resolve(1);`, + // Async arrow function with promise return (block-body) + `const numberOne = async (): Promise => { + return Promise.resolve(1); + };`, + // Async function declaration with async function return + `async function numberOne(): Promise { + return getAsyncNumber(1); + } + async function getAsyncNumber(x: number): Promise { + return Promise.resolve(x); + }`, + // Async function expression with async function return + `const numberOne = async function(): Promise { + return getAsyncNumber(1); + } + const getAsyncNumber = async function(x: number): Promise { + return Promise.resolve(x); + }`, + // Async arrow function with async function return (concise-body) + `const numberOne = async (): Promise => getAsyncNumber(1); + const getAsyncNumber = async function(x: number): Promise { + return Promise.resolve(x); + }`, + // Async arrow function with async function return (block-body) + `const numberOne = async (): Promise => { + return getAsyncNumber(1); + }; + const getAsyncNumber = async function(x: number): Promise { + return Promise.resolve(x); + }`, // https://github.com/typescript-eslint/typescript-eslint/issues/1188 ` async function testFunction(): Promise { diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 8037e624c4f..2ec44b6dbc2 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -451,7 +451,7 @@ declare module 'eslint/lib/rules/require-await' { node: TSESTree.ArrowFunctionExpression, ): void; ReturnStatement(node: TSESTree.ReturnStatement): void; - AwaitExpression(node: TSESTree.AwaitExpression): void; + AwaitExpression(): void; ForOfStatement(node: TSESTree.ForOfStatement): void; } >;