From 7dc1b4e7e9eb61b45447b43f962880ffd2936205 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 3 Nov 2015 13:48:03 +0000 Subject: [PATCH] add ExistentialTypeParam - fixes #2587 --- .../babel-generator/src/generators/flow.js | 4 + .../test/fixtures/flow/type-alias/actual.js | 3 +- .../test/fixtures/flow/type-alias/expected.js | 1 + packages/babel-types/src/definitions/flow.js | 4 + packages/babylon/src/plugins/flow.js | 14 +- packages/babylon/src/tokenizer/context.js | 2 + .../existential-type-param/actual.js | 1 + .../existential-type-param/expected.json | 177 ++++++++++++++++++ 8 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/actual.js create mode 100644 packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/expected.json diff --git a/packages/babel-generator/src/generators/flow.js b/packages/babel-generator/src/generators/flow.js index c0e5a10211..5e9a149e9e 100644 --- a/packages/babel-generator/src/generators/flow.js +++ b/packages/babel-generator/src/generators/flow.js @@ -46,6 +46,10 @@ export function DeclareVariable(node: Object) { this.semicolon(); } +export function ExistentialTypeParam() { + this.push("*"); +} + export function FunctionTypeAnnotation(node: Object, parent: Object) { this.print(node.typeParameters, node); this.push("("); diff --git a/packages/babel-generator/test/fixtures/flow/type-alias/actual.js b/packages/babel-generator/test/fixtures/flow/type-alias/actual.js index a56fa1a17b..17f785b98e 100644 --- a/packages/babel-generator/test/fixtures/flow/type-alias/actual.js +++ b/packages/babel-generator/test/fixtures/flow/type-alias/actual.js @@ -1,3 +1,4 @@ type FBID = number; -type Foo = Bar +type Foo = Bar; +type Maybe = _Maybe; export type Foo = number; diff --git a/packages/babel-generator/test/fixtures/flow/type-alias/expected.js b/packages/babel-generator/test/fixtures/flow/type-alias/expected.js index f0a50c1904..17f785b98e 100644 --- a/packages/babel-generator/test/fixtures/flow/type-alias/expected.js +++ b/packages/babel-generator/test/fixtures/flow/type-alias/expected.js @@ -1,3 +1,4 @@ type FBID = number; type Foo = Bar; +type Maybe = _Maybe; export type Foo = number; diff --git a/packages/babel-types/src/definitions/flow.js b/packages/babel-types/src/definitions/flow.js index daaed5636a..aec33a4df2 100644 --- a/packages/babel-types/src/definitions/flow.js +++ b/packages/babel-types/src/definitions/flow.js @@ -79,6 +79,10 @@ defineType("DeclareVariable", { } }); +defineType("ExistentialTypeParam", { + aliases: ["Flow"] +}); + defineType("FunctionTypeAnnotation", { visitor: ["typeParameters", "params", "rest", "returnType"], aliases: ["Flow"], diff --git a/packages/babylon/src/plugins/flow.js b/packages/babylon/src/plugins/flow.js index 5022203f86..06af0a4838 100644 --- a/packages/babylon/src/plugins/flow.js +++ b/packages/babylon/src/plugins/flow.js @@ -164,7 +164,7 @@ pp.flowParseTypeParameterDeclaration = function () { this.expectRelational("<"); while (!this.isRelational(">")) { - node.params.push(this.flowParseTypeAnnotatableIdentifier()); + node.params.push(this.parseFlowTypeParam()); if (!this.isRelational(">")) { this.expect(tt.comma); } @@ -174,6 +174,16 @@ pp.flowParseTypeParameterDeclaration = function () { return this.finishNode(node, "TypeParameterDeclaration"); }; +pp.parseFlowTypeParam = function () { + if (this.match(tt.star)) { + let node = this.startNode(); + this.next(); + return this.finishNode(node, "ExistentialTypeParam"); + } else { + return this.flowParseTypeAnnotatableIdentifier(); + } +}; + pp.flowParseTypeParameterInstantiation = function () { let node = this.startNode(), oldInType = this.state.inType; node.params = []; @@ -182,7 +192,7 @@ pp.flowParseTypeParameterInstantiation = function () { this.expectRelational("<"); while (!this.isRelational(">")) { - node.params.push(this.flowParseType()); + node.params.push(this.parseFlowTypeParam()); if (!this.isRelational(">")) { this.expect(tt.comma); } diff --git a/packages/babylon/src/tokenizer/context.js b/packages/babylon/src/tokenizer/context.js index 7b7236e500..a8e592da6e 100644 --- a/packages/babylon/src/tokenizer/context.js +++ b/packages/babylon/src/tokenizer/context.js @@ -56,6 +56,8 @@ tt.parenR.updateContext = tt.braceR.updateContext = function () { }; tt.name.updateContext = function (prevType) { + this.state.exprAllowed = false; + if (prevType === tt._let || prevType === tt._const || prevType === tt._var) { if (lineBreak.test(this.input.slice(this.state.end))) { this.state.exprAllowed = true; diff --git a/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/actual.js b/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/actual.js new file mode 100644 index 0000000000..83f6d6f432 --- /dev/null +++ b/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/actual.js @@ -0,0 +1 @@ +type Maybe = _Maybe; diff --git a/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/expected.json b/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/expected.json new file mode 100644 index 0000000000..a412ffa9a8 --- /dev/null +++ b/packages/babylon/test/fixtures/flow/type-annotations/existential-type-param/expected.json @@ -0,0 +1,177 @@ +{ + "type": "File", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "sourceType": "module", + "body": [ + { + "type": "TypeAlias", + "start": 0, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "id": { + "type": "Identifier", + "start": 5, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "name": "Maybe" + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 10, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "params": [ + { + "type": "Identifier", + "start": 11, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "name": "T" + } + ] + }, + "right": { + "type": "GenericTypeAnnotation", + "start": 16, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "typeParameters": { + "type": "TypeParameterInstantiation", + "start": 22, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "params": [ + { + "type": "Identifier", + "start": 23, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 23 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "name": "T" + }, + { + "type": "ExistentialTypeParam", + "start": 26, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 27 + } + } + } + ] + }, + "id": { + "type": "Identifier", + "start": 16, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "name": "_Maybe" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file