Flow opaque type aliases parsing (#643)

* Add support for Flow opaque type aliases

* Add tests for Flow opaque type aliases
This commit is contained in:
jbrown215
2017-07-21 10:48:28 -04:00
committed by Henry Zhu
parent c88af90c0a
commit e7e7593ca5
54 changed files with 1595 additions and 3 deletions

View File

@@ -165,6 +165,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
} else if (this.isContextual("type")) {
return this.flowParseDeclareTypeAlias(node);
} else if (this.isContextual("opaque")) {
return this.flowParseDeclareOpaqueType(node);
} else if (this.isContextual("interface")) {
return this.flowParseDeclareInterface(node);
} else if (this.match(tt._export)) {
@@ -285,7 +287,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (
this.match(tt._var) || // declare export var ...
this.match(tt._function) || // declare export function ...
this.match(tt._class) // declare export class ...
this.match(tt._class) || // declare export class ...
this.isContextual("opaque") // declare export opaque ..
) {
node.declaration = this.flowParseDeclare(this.startNode());
node.default = false;
@@ -295,7 +298,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.match(tt.star) || // declare export * from ''
this.match(tt.braceL) || // declare export {} ...
this.isContextual("interface") || // declare export interface ...
this.isContextual("type") // declare export type ...
this.isContextual("type") || // declare export type ...
this.isContextual("opaque") // declare export opaque type ...
) {
node = this.parseExport(node);
if (node.type === "ExportNamedDeclaration") {
@@ -337,6 +341,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "DeclareTypeAlias");
}
flowParseDeclareOpaqueType(
node: N.FlowDeclareOpaqueType,
): N.FlowDeclareOpaqueType {
this.next();
this.flowParseOpaqueType(node, true);
return this.finishNode(node, "DeclareOpaqueType");
}
flowParseDeclareInterface(
node: N.FlowDeclareInterface,
): N.FlowDeclareInterface {
@@ -421,6 +433,34 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TypeAlias");
}
flowParseOpaqueType(
node: N.FlowOpaqueType,
declare: boolean,
): N.FlowOpaqueType {
this.expectContextual("type");
node.id = this.flowParseRestrictedIdentifier();
if (this.isRelational("<")) {
node.typeParameters = this.flowParseTypeParameterDeclaration();
} else {
node.typeParameters = null;
}
// Parse the supertype
node.supertype = null;
if (this.match(tt.colon)) {
node.supertype = this.flowParseTypeInitialiser(tt.colon);
}
node.impltype = null;
if (!declare) {
node.impltype = this.flowParseTypeInitialiser(tt.eq);
}
this.semicolon();
return this.finishNode(node, "OpaqueType");
}
// Type annotations
flowParseTypeParameter(): N.TypeParameter {
@@ -1205,6 +1245,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.flowParseInterface(node);
} else if (expr.name === "type") {
return this.flowParseTypeAlias(node);
} else if (expr.name === "opaque") {
return this.flowParseOpaqueType(node, false);
}
}
}
@@ -1217,6 +1259,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return (
this.isContextual("type") ||
this.isContextual("interface") ||
this.isContextual("opaque") ||
super.shouldParseExportDeclaration()
);
}
@@ -1224,7 +1267,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isExportDefaultSpecifier(): boolean {
if (
this.match(tt.name) &&
(this.state.value === "type" || this.state.value === "interface")
(this.state.value === "type" ||
this.state.value === "interface" ||
this.state.value == "opaque")
) {
return false;
}
@@ -1308,6 +1353,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// export type Foo = Bar;
return this.flowParseTypeAlias(declarationNode);
}
} else if (this.isContextual("opaque")) {
node.exportKind = "type";
const declarationNode = this.startNode();
this.next();
// export opaque type Foo = Bar;
return this.flowParseOpaqueType(declarationNode, false);
} else if (this.isContextual("interface")) {
node.exportKind = "type";
const declarationNode = this.startNode();