Fix parsing type casted generic flow arrow exprs (#11955)

This commit is contained in:
Brian Ng
2020-08-19 14:15:01 -05:00
committed by GitHub
parent 180e9c00e3
commit 96cc8292b7
10 changed files with 282 additions and 9 deletions

View File

@@ -2674,28 +2674,57 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let typeParameters;
const arrow = this.tryParse(() => {
const arrow = this.tryParse(abort => {
typeParameters = this.flowParseTypeParameterDeclaration();
const arrowExpression = this.forwardNoArrowParamsConversionAt(
typeParameters,
() =>
super.parseMaybeAssign(
() => {
const result = super.parseMaybeAssign(
refExpressionErrors,
afterLeftParse,
refNeedsArrowPos,
),
);
this.resetStartLocationFromNode(result, typeParameters);
return result;
},
);
arrowExpression.typeParameters = typeParameters;
this.resetStartLocationFromNode(arrowExpression, typeParameters);
// <T>(() => {}: any);
if (
arrowExpression.type !== "ArrowFunctionExpression" &&
arrowExpression.extra?.parenthesized
) {
abort();
}
// The above can return a TypeCastExpression when the arrow
// expression is not wrapped in parens. See also `this.parseParenItem`.
const expr = this.maybeUnwrapTypeCastExpression(arrowExpression);
expr.typeParameters = typeParameters;
this.resetStartLocationFromNode(expr, typeParameters);
return arrowExpression;
}, state);
const arrowExpression: ?N.ArrowFunctionExpression =
arrow.node?.type === "ArrowFunctionExpression" ? arrow.node : null;
let arrowExpression: ?(
| N.ArrowFunctionExpression
| N.TypeCastExpression
) = null;
if (!arrow.error && arrowExpression) return arrowExpression;
if (
arrow.node &&
this.maybeUnwrapTypeCastExpression(arrow.node).type ===
"ArrowFunctionExpression"
) {
if (!arrow.error && !arrow.aborted) {
return arrow.node;
}
arrowExpression = arrow.node;
}
// If we are here, both JSX and Flow parsing attempts failed.
// Give the precedence to the JSX error, except if JSX had an
@@ -3482,4 +3511,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
return false;
}
maybeUnwrapTypeCastExpression(node: N.Node) {
return node.type === "TypeCastExpression" ? node.expression : node;
}
};