From fe5ac0682fad054a5f161b11d1d26b68fa353a88 Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Fri, 9 Aug 2019 09:20:47 +1000 Subject: [PATCH 1/3] fix(eslint-plugin): [require-await] Allow concise arrow function bodies --- .../eslint-plugin/src/rules/require-await.ts | 26 ++++++++++++++++--- .../tests/rules/require-await.test.ts | 11 ++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index cbdd08791d9f..6a7123d0eb75 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -63,6 +63,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 === 'BlockStatement')) { + const expression = parserServices.esTreeNodeToTSNodeMap.get( + node.body, + ); + scopeInfo.returnsPromise = isThenableType(expression); + } + break; } } @@ -101,6 +110,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, @@ -121,10 +142,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 3ea207713b2d..4e25fc74f377 100644 --- a/packages/eslint-plugin/tests/rules/require-await.test.ts +++ b/packages/eslint-plugin/tests/rules/require-await.test.ts @@ -72,6 +72,10 @@ ruleTester.run('require-await', rule, { return Promise.resolve(1); }`, }, + { + // Async arrow function with promise return + code: `const numberOne = async (): Promise => Promise.resolve(1);`, + }, { // Async function declaration with async function return code: `async function numberOne(): Promise { @@ -90,6 +94,13 @@ ruleTester.run('require-await', rule, { return Promise.resolve(x); }`, }, + { + // Async arrow function with async function return + code: `const numberOne = async (): Promise => getAsyncNumber(1); + const getAsyncNumber = async function(x: number): Promise { + return Promise.resolve(x); + }`, + }, ], invalid: [ From 4ac5b3a0179ea29adaf45ae82ec0b959cfae8f2e Mon Sep 17 00:00:00 2001 From: Scott O'Hara Date: Fri, 9 Aug 2019 10:21:07 +1000 Subject: [PATCH 2/3] fix(eslint-plugin): [require-await] Add more test cases for coverage --- .../tests/rules/require-await.test.ts | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/require-await.test.ts b/packages/eslint-plugin/tests/rules/require-await.test.ts index 4e25fc74f377..38a925de1d2c 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 { @@ -73,9 +85,15 @@ ruleTester.run('require-await', rule, { }`, }, { - // Async arrow function with promise return + // 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 { @@ -95,12 +113,21 @@ ruleTester.run('require-await', rule, { }`, }, { - // Async arrow function with async function return + // 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: [ From 2eb3e0383a4dd1e1b042b2c1c00dbbf794c1ceb4 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Wed, 21 Aug 2019 09:21:30 -0700 Subject: [PATCH 3/3] fix: review nit --- packages/eslint-plugin/src/rules/require-await.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index 6a7123d0eb75..6c4fd21d9e73 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -65,7 +65,7 @@ export default util.createRule({ rules.ArrowFunctionExpression(node); // If body type is not BlockStatment, we need to check the return type here - if (!(node.body.type === 'BlockStatement')) { + if (node.body.type !== AST_NODE_TYPES.BlockStatement) { const expression = parserServices.esTreeNodeToTSNodeMap.get( node.body, );