From 29fddfd149599c241d011fb9e1eb2bc830098d4e Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Thu, 22 Aug 2019 02:48:44 +1000 Subject: [PATCH] fix(eslint-plugin): [require-await] Allow concise arrow function bodies (#826) --- .../eslint-plugin/src/rules/require-await.ts | 26 ++++++++++-- .../tests/rules/require-await.test.ts | 42 ++++++++++++++++++- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index 7441b464896..065066dece2 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -64,6 +64,15 @@ export default util.createRule({ case AST_NODE_TYPES.ArrowFunctionExpression: 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( + node.body, + ); + scopeInfo.returnsPromise = isThenableType(expression); + } + break; } } @@ -102,6 +111,18 @@ export default util.createRule({ } } + /** + * Checks if the node returns a thenable type + * + * @param {ASTNode} node - The node to check + * @returns {boolean} + */ + function isThenableType(node: ts.Node) { + const type = checker.getTypeAtLocation(node); + + return tsutils.isThenableType(checker, node, type); + } + return { 'FunctionDeclaration[async = true]': enterFunction, 'FunctionExpression[async = true]': enterFunction, @@ -122,10 +143,7 @@ export default util.createRule({ return; } - const type = checker.getTypeAtLocation(expression); - if (tsutils.isThenableType(checker, expression, type)) { - scopeInfo.returnsPromise = true; - } + scopeInfo.returnsPromise = isThenableType(expression); }, AwaitExpression: rules.AwaitExpression as TSESLint.RuleFunction< diff --git a/packages/eslint-plugin/tests/rules/require-await.test.ts b/packages/eslint-plugin/tests/rules/require-await.test.ts index 3ea207713b2..38a925de1d2 100644 --- a/packages/eslint-plugin/tests/rules/require-await.test.ts +++ b/packages/eslint-plugin/tests/rules/require-await.test.ts @@ -41,9 +41,15 @@ ruleTester.run('require-await', rule, { }`, }, { - // Non-async arrow function expression + // 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 { @@ -57,9 +63,15 @@ ruleTester.run('require-await', rule, { }`, }, { - // Async arrow function expression with await + // 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 { @@ -72,6 +84,16 @@ ruleTester.run('require-await', rule, { 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 { @@ -90,6 +112,22 @@ ruleTester.run('require-await', rule, { 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); + }`, + }, ], invalid: [