From 4477fb74ae8beb8b5fda778ea8ef46ef332d55f6 Mon Sep 17 00:00:00 2001 From: islandryu Date: Fri, 7 Jan 2022 17:04:39 +0900 Subject: [PATCH] fix(eslint-plugin): return-await in binary expression --- .../eslint-plugin/src/rules/return-await.ts | 35 ++++++++- .../tests/rules/return-await.test.ts | 76 +++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 93b863757a0..67595e47b09 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -4,6 +4,7 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; +import { isBinaryExpression } from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -154,6 +155,12 @@ export default util.createRule({ fixer: TSESLint.RuleFixer, node: TSESTree.Expression, ): TSESLint.RuleFix | TSESLint.RuleFix[] { + if (node.parent?.type === AST_NODE_TYPES.LogicalExpression) { + return [ + fixer.insertTextBefore(node, '(await '), + fixer.insertTextAfter(node, ')'), + ]; + } if (node.type !== AST_NODE_TYPES.TSAsExpression) { return fixer.insertTextBefore(node, 'await '); } @@ -259,6 +266,22 @@ export default util.createRule({ } } + function testLogicalExpression( + node: TSESTree.LogicalExpression, + tsNode: ts.BinaryExpression, + ): void { + const left = node.left; + const tsLeft = tsNode.left; + const right = node.right; + const tsRight = tsNode.right; + test(right, tsRight); + if (isLogicalExpression(left) && isBinaryExpression(tsLeft)) { + testLogicalExpression(left, tsLeft); + } else { + test(left, tsLeft); + } + } + function findPossiblyReturnedNodes( node: TSESTree.Expression, ): TSESTree.Expression[] { @@ -298,9 +321,19 @@ export default util.createRule({ } findPossiblyReturnedNodes(node.argument).forEach(node => { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - test(node, tsNode); + if (isLogicalExpression(node) && isBinaryExpression(tsNode)) { + testLogicalExpression(node, tsNode); + } else { + test(node, tsNode); + } }); }, }; }, }); + +function isLogicalExpression( + node: TSESTree.Node, +): node is TSESTree.LogicalExpression { + return node.type === AST_NODE_TYPES.LogicalExpression; +} diff --git a/packages/eslint-plugin/tests/rules/return-await.test.ts b/packages/eslint-plugin/tests/rules/return-await.test.ts index 1c0a9cdd2a1..83b27e0e69d 100644 --- a/packages/eslint-plugin/tests/rules/return-await.test.ts +++ b/packages/eslint-plugin/tests/rules/return-await.test.ts @@ -909,5 +909,81 @@ async function test(): Promise { }, ], }, + { + code: ` + async function bar() {} + async function foo() { + try { + return undefined || bar(); + } catch {} + } + `, + output: ` + async function bar() {} + async function foo() { + try { + return undefined || (await bar()); + } catch {} + } + `, + errors: [ + { + line: 5, + messageId: 'requiredPromiseAwait', + }, + ], + }, + { + code: ` + async function bar() {} + async function foo() { + try { + return bar() || undefined || bar(); + } catch {} + } + `, + output: ` + async function bar() {} + async function foo() { + try { + return (await bar()) || undefined || (await bar()); + } catch {} + } + `, + errors: [ + { + line: 5, + messageId: 'requiredPromiseAwait', + }, + { + line: 5, + messageId: 'requiredPromiseAwait', + }, + ], + }, + { + code: ` + async function bar() {} + async function foo() { + try { + return window.foo ?? bar(); + } catch {} + } + `, + output: ` + async function bar() {} + async function foo() { + try { + return window.foo ?? (await bar()); + } catch {} + } + `, + errors: [ + { + line: 5, + messageId: 'requiredPromiseAwait', + }, + ], + }, ], });