Skip to content

Commit

Permalink
Flow opaque type alias backport (babel#644)
Browse files Browse the repository at this point in the history
* Flow opaque type alias backport

* Flow opaque type alias backport tests

* Only add  support for opaque types

* Remove .swp file
  • Loading branch information
jbrown215 authored and hzoo committed Aug 15, 2017
1 parent f199a61 commit a457038
Show file tree
Hide file tree
Showing 53 changed files with 1,609 additions and 2 deletions.
73 changes: 71 additions & 2 deletions src/plugins/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,31 @@ pp.flowParseDeclare = function (node) {
}
} 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)) {
return this.flowParseDeclareExportDeclaration(node);
} else {
this.unexpected();
}
};

pp.flowParseDeclareExportDeclaration = function (node) {
this.expect(tt._export);
if (
this.isContextual("opaque") // declare export opaque ...
) {
node.declaration = this.flowParseDeclare(this.startNode());
node.default = false;

return this.finishNode(node, "DeclareExportDeclaration");
}

throw this.unexpected();
};

pp.flowParseDeclareVariable = function (node) {
this.next();
node.id = this.flowParseTypeAnnotatableIdentifier();
Expand Down Expand Up @@ -185,6 +203,13 @@ pp.flowParseDeclareTypeAlias = function (node) {
return this.finishNode(node, "DeclareTypeAlias");
};

pp.flowParseDeclareOpaqueType = function (node) {
this.next();
this.flowParseOpaqueType(node, true);
return this.finishNode(node, "DeclareOpaqueType");
};


pp.flowParseDeclareInterface = function (node) {
this.next();
this.flowParseInterfaceish(node);
Expand Down Expand Up @@ -264,6 +289,33 @@ pp.flowParseTypeAlias = function (node) {
return this.finishNode(node, "TypeAlias");
};

// Opaque type aliases

pp.flowParseOpaqueType = function (node, declare) {
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

pp.flowParseTypeParameter = function () {
Expand Down Expand Up @@ -905,14 +957,21 @@ export default function (instance) {
return function (node, expr) {
if (expr.type === "Identifier") {
if (expr.name === "declare") {
if (this.match(tt._class) || this.match(tt.name) || this.match(tt._function) || this.match(tt._var)) {
if (this.match(tt._class)
|| this.match(tt.name)
|| this.match(tt._function)
|| this.match(tt._var)
|| this.match(tt._export)
) {
return this.flowParseDeclare(node);
}
} else if (this.match(tt.name)) {
if (expr.name === "interface") {
return this.flowParseInterface(node);
} else if (expr.name === "type") {
return this.flowParseTypeAlias(node);
} else if (expr.name === "opaque") {
return this.flowParseOpaqueType(node, false);
}
}
}
Expand All @@ -926,6 +985,7 @@ export default function (instance) {
return function () {
return this.isContextual("type")
|| this.isContextual("interface")
|| this.isContextual("opaque")
|| inner.call(this);
};
});
Expand All @@ -934,7 +994,9 @@ export default function (instance) {
return function () {
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;
}
Expand Down Expand Up @@ -1013,6 +1075,13 @@ export default function (instance) {
// 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare opaque type ID = number;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "Unexpected token, expected ; (1:23)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
opaque type opaque = number;
opaque type not_transparent = opaque;
150 changes: 150 additions & 0 deletions test/fixtures/flow/opaque-type-aliases/opaque_collision/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"type": "File",
"start": 0,
"end": 66,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 37
}
},
"program": {
"type": "Program",
"start": 0,
"end": 66,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 37
}
},
"sourceType": "module",
"body": [
{
"type": "OpaqueType",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 28
}
},
"id": {
"type": "Identifier",
"start": 12,
"end": 18,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 18
},
"identifierName": "opaque"
},
"name": "opaque"
},
"typeParameters": null,
"supertype": null,
"impltype": {
"type": "NumberTypeAnnotation",
"start": 21,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 21
},
"end": {
"line": 1,
"column": 27
}
}
}
},
{
"type": "OpaqueType",
"start": 29,
"end": 66,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 37
}
},
"id": {
"type": "Identifier",
"start": 41,
"end": 56,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 27
},
"identifierName": "not_transparent"
},
"name": "not_transparent"
},
"typeParameters": null,
"supertype": null,
"impltype": {
"type": "GenericTypeAnnotation",
"start": 59,
"end": 65,
"loc": {
"start": {
"line": 2,
"column": 30
},
"end": {
"line": 2,
"column": 36
}
},
"typeParameters": null,
"id": {
"type": "Identifier",
"start": 59,
"end": 65,
"loc": {
"start": {
"line": 2,
"column": 30
},
"end": {
"line": 2,
"column": 36
},
"identifierName": "opaque"
},
"name": "opaque"
}
}
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare export opaque type Foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"sourceType": "module",
"body": [
{
"type": "DeclareExportDeclaration",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 30
}
},
"declaration": {
"type": "DeclareOpaqueType",
"start": 15,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 30
}
},
"id": {
"type": "Identifier",
"start": 27,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 27
},
"end": {
"line": 1,
"column": 30
},
"identifierName": "Foo"
},
"name": "Foo"
},
"typeParameters": null,
"supertype": null,
"impltype": null
},
"default": false
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare export opaque type Foo: Bar
Loading

0 comments on commit a457038

Please sign in to comment.