[flow] Add support for parsing _ as implicit instantiation in call/new (#8883)

* [flow] Add support for parsing  as implicit instantiation in call/new

* Update flow tests and fix underscore being a reserved type

* Rebase onto flow-test

* Fix flow commit hash
This commit is contained in:
Jordan Brown
2018-11-05 13:45:40 -05:00
committed by Daniel Tschinder
parent c6d2f45cab
commit f216a7b06f
18 changed files with 1328 additions and 4 deletions

View File

@@ -23,6 +23,9 @@ const primitiveTypes = [
"true",
"typeof",
"void",
"interface",
"extends",
"_",
];
function isEsModuleType(bodyElement: N.Node): boolean {
@@ -490,6 +493,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "InterfaceDeclaration");
}
checkNotUnderscore(word: string) {
if (word === "_") {
throw this.unexpected(
null,
"`_` is only allowed as a type argument to call or new",
);
}
}
checkReservedType(word: string, startLoc: number) {
if (primitiveTypes.indexOf(word) > -1) {
this.raise(startLoc, `Cannot overwrite primitive type ${word}`);
@@ -654,6 +666,27 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TypeParameterInstantiation");
}
flowParseTypeParameterInstantiationCallOrNew(): N.TypeParameterInstantiation {
const node = this.startNode();
const oldInType = this.state.inType;
node.params = [];
this.state.inType = true;
this.expectRelational("<");
while (!this.isRelational(">")) {
node.params.push(this.flowParseTypeOrImplicitInstantiation());
if (!this.isRelational(">")) {
this.expect(tt.comma);
}
}
this.expectRelational(">");
this.state.inType = oldInType;
return this.finishNode(node, "TypeParameterInstantiation");
}
flowParseInterfaceType(): N.FlowInterfaceType {
const node = this.startNode();
this.expectContextual("interface");
@@ -1176,6 +1209,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "StringTypeAnnotation");
default:
this.checkNotUnderscore(id.name);
return this.flowParseGenericType(startPos, startLoc, id);
}
}
@@ -1431,6 +1465,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return type;
}
flowParseTypeOrImplicitInstantiation(): N.FlowTypeAnnotation {
if (this.state.type === tt.name && this.state.value === "_") {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
const node = this.parseIdentifier();
return this.flowParseGenericType(startPos, startLoc, node);
} else {
return this.flowParseType();
}
}
flowParseTypeAnnotation(): N.FlowTypeAnnotation {
const node = this.startNode();
node.typeAnnotation = this.flowParseTypeInitialiser();
@@ -2582,7 +2627,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.callee = base;
const state = this.state.clone();
try {
node.typeArguments = this.flowParseTypeParameterInstantiation();
node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew();
this.expect(tt.parenL);
node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
if (subscriptState.optionalChainMember) {
@@ -2613,7 +2658,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (this.shouldParseTypes() && this.isRelational("<")) {
const state = this.state.clone();
try {
targs = this.flowParseTypeParameterInstantiation();
targs = this.flowParseTypeParameterInstantiationCallOrNew();
} catch (e) {
if (e instanceof SyntaxError) {
this.state = state;