Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(eslint-plugin): [require-await] handle async generators #1782

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 31, 2020
38 changes: 36 additions & 2 deletions packages/eslint-plugin/src/rules/require-await.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ interface ScopeInfo {
upper: ScopeInfo | null;
hasAwait: boolean;
hasAsync: boolean;
isGen: boolean;
isAsyncYield: boolean;
}
type FunctionNode =
| TSESTree.FunctionDeclaration
Expand Down Expand Up @@ -49,6 +51,8 @@ export default util.createRule({
upper: scopeInfo,
hasAwait: false,
hasAsync: node.async,
isGen: node.generator || false,
isAsyncYield: false,
};
}

Expand All @@ -62,7 +66,12 @@ export default util.createRule({
return;
}

if (node.async && !scopeInfo.hasAwait && !isEmptyFunction(node)) {
if (
node.async &&
!scopeInfo.hasAwait &&
!isEmptyFunction(node) &&
!(scopeInfo.isGen && scopeInfo.isAsyncYield)
) {
context.report({
node,
loc: getFunctionHeadLoc(node, sourceCode),
Expand Down Expand Up @@ -92,10 +101,34 @@ export default util.createRule({
if (!scopeInfo) {
return;
}

scopeInfo.hasAwait = true;
}

/**
* mark `scopeInfo.isAsyncYield` to `true` if its a generator
* function and the delegate is `true`
*/
function markAsHasDelegateGen(node: TSESTree.YieldExpression): void {
if (!scopeInfo || !scopeInfo.isGen || !node.argument) {
return;
}

if (node?.argument?.type === AST_NODE_TYPES.Literal) {
// making this `false` as for literals we don't need to check the definition
// eg : async function* run() { yield* 1 }
scopeInfo.isAsyncYield = false;
}

const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node?.argument);
const type = checker.getTypeAtLocation(tsNode);
const symbol = type.getSymbol();

// async function* test1() {yield* asyncGenerator() }
if (symbol?.getName() === 'AsyncGenerator') {
scopeInfo.isAsyncYield = true;
}
}

return {
FunctionDeclaration: enterFunction,
FunctionExpression: enterFunction,
Expand All @@ -106,6 +139,7 @@ export default util.createRule({

AwaitExpression: markAsHasAwait,
'ForOfStatement[await = true]': markAsHasAwait,
'YieldExpression[delegate = true]': markAsHasDelegateGen,

// check body-less async arrow function.
// ignore `async () => await foo` because it's obviously correct
Expand Down
Loading