Support defaults in Flow's type parameter declarations

The primary goal of this commit is to add the ability to parse type parameter
declarations with defaults, like `type Foo<T = string> = T`. While I was in the
code, I fixed a few small things, like

* Type parameter declarations need 1 or more type parameters.
* The existential type `*` is not a valid type parameter.
* The existential type `*` is a primary type
* The param list for type parameter declarations now consists of
  `TypeParameter` nodes
This commit is contained in:
Gabe Levi 2016-04-27 15:00:54 -04:00
parent b926e401c6
commit fe5193a40a
38 changed files with 3457 additions and 133 deletions

View File

@ -190,30 +190,48 @@ pp.flowParseTypeAlias = function (node) {
// Type annotations
pp.flowParseTypeParameter = function () {
let node = this.startNode();
let variance;
if (this.match(tt.plusMin)) {
if (this.state.value === "+") {
variance = "plus";
} else if (this.state.value === "-") {
variance = "minus";
}
this.eat(tt.plusMin);
}
let ident = this.flowParseTypeAnnotatableIdentifier(false, false);
node.name = ident.name;
node.variance = variance;
node.bound = ident.typeAnnotation;
if (this.match(tt.eq)) {
this.eat(tt.eq);
node.default = this.flowParseType ();
}
return this.finishNode(node, "TypeParameter");
};
pp.flowParseTypeParameterDeclaration = function () {
let node = this.startNode();
node.params = [];
this.expectRelational("<");
while (!this.isRelational(">")) {
node.params.push(this.flowParseExistentialTypeParam() || this.flowParseTypeAnnotatableIdentifier());
do {
node.params.push(this.flowParseTypeParameter());
if (!this.isRelational(">")) {
this.expect(tt.comma);
}
}
} while (!this.isRelational(">"));
this.expectRelational(">");
return this.finishNode(node, "TypeParameterDeclaration");
};
pp.flowParseExistentialTypeParam = function () {
if (this.match(tt.star)) {
let node = this.startNode();
this.next();
return this.finishNode(node, "ExistentialTypeParam");
}
};
pp.flowParseTypeParameterInstantiation = function () {
let node = this.startNode(), oldInType = this.state.inType;
node.params = [];
@ -222,7 +240,7 @@ pp.flowParseTypeParameterInstantiation = function () {
this.expectRelational("<");
while (!this.isRelational(">")) {
node.params.push(this.flowParseExistentialTypeParam() || this.flowParseType());
node.params.push(this.flowParseType());
if (!this.isRelational(">")) {
this.expect(tt.comma);
}
@ -558,6 +576,10 @@ pp.flowParsePrimaryType = function () {
this.next();
return this.finishNode(node, "ThisTypeAnnotation");
case tt.star:
this.next();
return this.finishNode(node, "ExistentialTypeParam");
default:
if (this.state.type.keyword === "typeof") {
return this.flowParseTypeofType();
@ -624,23 +646,10 @@ pp.flowParseTypeAnnotation = function () {
};
pp.flowParseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOptionalParam) {
let variance;
if (this.match(tt.plusMin)) {
if (this.state.value === "+") {
variance = "plus";
} else if (this.state.value === "-") {
variance = "minus";
}
this.eat(tt.plusMin);
}
let ident = this.parseIdentifier();
let isOptionalParam = false;
if (variance) {
ident.variance = variance;
}
if (canBeOptionalParam && this.eat(tt.question)) {
this.expect(tt.question);
isOptionalParam = true;

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 8,
"end": 14,
"loc": {
@ -88,7 +88,7 @@
}
},
"name": "T",
"typeAnnotation": {
"bound": {
"type": "TypeAnnotation",
"start": 9,
"end": 14,
@ -156,7 +156,7 @@
"body": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -60,6 +60,7 @@
},
"generator": false,
"expression": false,
"async": false,
"typeParameters": {
"type": "TypeParameterDeclaration",
"start": 12,
@ -76,7 +77,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 13,
"end": 23,
"loc": {
@ -90,7 +91,7 @@
}
},
"name": "T",
"typeAnnotation": {
"bound": {
"type": "TypeAnnotation",
"start": 14,
"end": 23,

View File

@ -212,7 +212,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 11,
"end": 12,
"loc": {
@ -257,7 +257,7 @@
],
"kind": "var"
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -121,7 +121,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 40,
"end": 41,
"loc": {

View File

@ -174,7 +174,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 56,
"end": 57,
"loc": {

View File

@ -101,7 +101,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 21,
"end": 22,
"loc": {
@ -139,7 +139,7 @@
}
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 16,
"end": 17,
"loc": {
@ -173,6 +173,7 @@
}
}
],
"mixins": [],
"body": {
"type": "ObjectTypeAnnotation",
"start": 32,
@ -240,7 +241,7 @@
"indexers": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,38 +74,38 @@
},
"params": [
{
"type": "Identifier",
"start": 9,
"type": "TypeParameter",
"start": 8,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
"column": 8
},
"end": {
"line": 1,
"column": 10
}
},
"name": "T",
"variance": "plus"
"variance": "plus",
"name": "T"
},
{
"type": "Identifier",
"start": 12,
"type": "TypeParameter",
"start": 11,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 12
"column": 11
},
"end": {
"line": 1,
"column": 13
}
},
"name": "U",
"variance": "minus"
"variance": "minus",
"name": "U"
}
]
},
@ -176,38 +176,38 @@
},
"params": [
{
"type": "Identifier",
"start": 30,
"type": "TypeParameter",
"start": 29,
"end": 31,
"loc": {
"start": {
"line": 2,
"column": 12
"column": 11
},
"end": {
"line": 2,
"column": 13
}
},
"name": "T",
"variance": "plus"
"variance": "plus",
"name": "T"
},
{
"type": "Identifier",
"start": 33,
"type": "TypeParameter",
"start": 32,
"end": 34,
"loc": {
"start": {
"line": 2,
"column": 15
"column": 14
},
"end": {
"line": 2,
"column": 16
}
},
"name": "U",
"variance": "minus"
"variance": "minus",
"name": "U"
}
]
},
@ -276,38 +276,38 @@
},
"params": [
{
"type": "Identifier",
"start": 49,
"type": "TypeParameter",
"start": 48,
"end": 50,
"loc": {
"start": {
"line": 3,
"column": 8
"column": 7
},
"end": {
"line": 3,
"column": 9
}
},
"name": "T",
"variance": "plus"
"variance": "plus",
"name": "T"
},
{
"type": "Identifier",
"start": 52,
"type": "TypeParameter",
"start": 51,
"end": 53,
"loc": {
"start": {
"line": 3,
"column": 11
"column": 10
},
"end": {
"line": 3,
"column": 12
}
},
"name": "U",
"variance": "minus"
"variance": "minus",
"name": "U"
}
]
},

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 12,
"end": 13,
"loc": {
@ -253,6 +253,7 @@
}
}
],
"mixins": [],
"body": {
"type": "ObjectTypeAnnotation",
"start": 34,
@ -272,7 +273,7 @@
"indexers": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 9,
"end": 10,
"loc": {
@ -172,7 +172,7 @@
}
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -60,6 +60,7 @@
},
"generator": false,
"expression": false,
"async": false,
"typeParameters": {
"type": "TypeParameterDeclaration",
"start": 12,
@ -76,7 +77,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 13,
"end": 14,
"loc": {

View File

@ -60,6 +60,7 @@
},
"generator": false,
"expression": false,
"async": false,
"typeParameters": {
"type": "TypeParameterDeclaration",
"start": 12,
@ -76,7 +77,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 13,
"end": 14,
"loc": {
@ -92,7 +93,7 @@
"name": "T"
},
{
"type": "Identifier",
"type": "TypeParameter",
"start": 15,
"end": 16,
"loc": {

View File

@ -90,6 +90,7 @@
"id": null,
"generator": false,
"expression": false,
"async": false,
"typeParameters": {
"type": "TypeParameterDeclaration",
"start": 10,
@ -106,7 +107,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 11,
"end": 12,
"loc": {
@ -122,7 +123,7 @@
"name": "T"
},
{
"type": "Identifier",
"type": "TypeParameter",
"start": 13,
"end": 14,
"loc": {

View File

@ -271,7 +271,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 6,
"end": 7,
"loc": {

View File

@ -271,7 +271,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 7,
"end": 8,
"loc": {

View File

@ -271,7 +271,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 12,
"end": 13,
"loc": {

View File

@ -275,7 +275,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 7,
"end": 8,
"loc": {

View File

@ -213,7 +213,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 12,
"end": 13,
"loc": {
@ -291,7 +291,7 @@
],
"kind": "var"
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -119,7 +119,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 14,
"end": 15,
"loc": {
@ -156,7 +156,7 @@
}
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -119,7 +119,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 14,
"end": 15,
"loc": {
@ -220,7 +220,7 @@
}
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 10,
"end": 11,
"loc": {
@ -109,7 +109,7 @@
"body": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 10,
"end": 11,
"loc": {
@ -173,7 +173,7 @@
"body": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 10,
"end": 11,
"loc": {
@ -157,7 +157,7 @@
"body": []
}
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 10,
"end": 11,
"loc": {
@ -156,7 +156,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 19,
"end": 20,
"loc": {

View File

@ -127,7 +127,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 18,
"end": 19,
"loc": {

View File

@ -116,7 +116,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 15,
"end": 16,
"loc": {
@ -240,7 +240,7 @@
],
"kind": "var"
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -116,7 +116,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 15,
"end": 16,
"loc": {
@ -318,7 +318,7 @@
],
"kind": "var"
}
]
},
"comments": []
],
"directives": []
}
}

View File

@ -124,7 +124,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 15,
"end": 16,
"loc": {
@ -163,7 +163,8 @@
}
],
"extra": {
"parenthesized": true
"parenthesized": true,
"parenStart": 0
}
}
}

View File

@ -74,7 +74,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 11,
"end": 12,
"loc": {

View File

@ -224,7 +224,7 @@
},
"params": [
{
"type": "Identifier",
"type": "TypeParameter",
"start": 57,
"end": 58,
"loc": {
@ -346,4 +346,4 @@
],
"directives": []
}
}
}

View File

@ -0,0 +1,21 @@
type A<T = string> = T
type A<T = *> = T
type A<T: ?string = string> = T
type A<S, T: ?string = string> = T
type A<S = number, T: ?string = string> = T
class A<T = string> {}
class A<T: ?string = string> {}
class A<S, T: ?string = string> {}
class A<S = number, T: ?string = string> {}
(class A<T = string> {})
(class A<T: ?string = string> {})
(class A<S, T: ?string = string> {})
(class A<S = number, T: ?string = string> {})
declare class A<T = string> {}
declare class A<T: ?string = string> {}
declare class A<S, T: ?string = string> {}
declare class A<S = number, T: ?string = string> {}
interface A<T = string> {}
interface A<T: ?string = string> {}
interface A<S, T: ?string = string> {}
interface A<S = number, T: ?string = string> {}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
// Type parameter declaration may not have 0 type parameters
type Foo<> = number;

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected token (2:9)"
}

View File

@ -0,0 +1,2 @@
// Star is only for type parameter initialization
type Foo<*> = number;

View File

@ -0,0 +1,148 @@
{
"type": "File",
"start": 0,
"end": 71,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"program": {
"type": "Program",
"start": 0,
"end": 71,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"sourceType": "module",
"body": [
{
"type": "TypeAlias",
"start": 50,
"end": 71,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 21
}
},
"id": {
"type": "Identifier",
"start": 55,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 8
}
},
"name": "Foo"
},
"typeParameters": {
"type": "TypeParameterDeclaration",
"start": 58,
"end": 61,
"loc": {
"start": {
"line": 2,
"column": 8
},
"end": {
"line": 2,
"column": 11
}
},
"params": [
{
"type": "ExistentialTypeParam",
"start": 59,
"end": 60,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
}
}
}
]
},
"right": {
"type": "NumberTypeAnnotation",
"start": 64,
"end": 70,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 2,
"column": 20
}
}
},
"leadingComments": [
{
"type": "CommentLine",
"value": " Star is only for type parameter initialization",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 49
}
}
}
]
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " Star is only for type parameter initialization",
"start": 0,
"end": 49,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 49
}
}
}
]
}

View File

@ -0,0 +1,3 @@
{
"throws": "Unexpected token (2:9)"
}