rewrite async function parsing, properly parse flow return types of arrow functions - fixes #1991

This commit is contained in:
Sebastian McKenzie
2015-07-15 20:08:10 +01:00
parent 4b276b938b
commit afacd62738
4 changed files with 767 additions and 98 deletions

View File

@@ -596,7 +596,9 @@ export default function (instance) {
// function name(): string {}
instance.extend("parseFunctionBody", function (inner) {
return function (node, allowExpression) {
if (this.type === tt.colon) {
if (this.type === tt.colon && !allowExpression) {
// if allowExpression is true then we're parsing an arrow function and if
// there's a return type then it's been handled elsewhere
node.returnType = this.flowParseTypeAnnotation();
}
@@ -644,12 +646,24 @@ export default function (instance) {
});
instance.extend("parseParenItem", function () {
return function (node, startLoc, startPos) {
return function (node, startLoc, startPos, forceArrow?) {
if (this.type === tt.colon) {
var typeCastNode = this.startNodeAt(startLoc, startPos);
typeCastNode.expression = node;
typeCastNode.typeAnnotation = this.flowParseTypeAnnotation();
return this.finishNode(typeCastNode, "TypeCastExpression");
if (forceArrow && this.type !== tt.arrow) {
this.unexpected();
}
if (this.eat(tt.arrow)) {
// ((lol): number => {});
var func = this.parseArrowExpression(this.startNodeAt(startLoc, startPos), [node]);
func.returnType = typeCastNode.typeAnnotation;
return func;
} else {
return this.finishNode(typeCastNode, "TypeCastExpression");
}
} else {
return node;
}
@@ -819,4 +833,52 @@ export default function (instance) {
}
};
});
// var foo = (async (): number => {});
instance.extend("parseAsyncArrowFromCallExpression", function (inner) {
return function (node, call) {
if (this.type === tt.colon) {
node.returnType = this.flowParseTypeAnnotation();
}
return inner.call(this, node, call);
};
});
instance.extend("parseParenAndDistinguishExpression", function (inner) {
return function (startPos, startLoc, canBeArrow, isAsync) {
if (this.lookahead().type === tt.parenR) {
// var foo = (): number => {};
this.expect(tt.parenL);
this.expect(tt.parenR);
let node = this.startNodeAt(startPos, startLoc);
if (this.type === tt.colon) node.returnType = this.flowParseTypeAnnotation();
this.expect(tt.arrow);
return this.parseArrowExpression(node, [], isAsync);
} else {
// var foo = (foo): number => {};
startPos = startPos || this.start;
startLoc = startLoc || this.startLoc;
let node = inner.call(this, startPos, startLoc, canBeArrow, isAsync);
var state = this.getState();
if (this.type === tt.colon) {
try {
return this.parseParenItem(node, startPos, startLoc, true);
} catch (err) {
if (err instanceof SyntaxError) {
this.setState(state);
return node;
} else {
throw err;
}
}
} else {
return node;
}
}
};
});
}