From b85d6c7e4aab58cd654854331dabd8d7450587a6 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Mon, 29 Feb 2016 17:20:55 -0800 Subject: [PATCH] Add support for Flow def-site variance syntax This syntax allows you to specify whether a type variable can appear in a covariant or contravariant position, and is super useful for, say, Promise. Right now this is hacked in jankily, but in the next major release we should stop using Identifier nodes for type parameters. --- src/plugins/flow.js | 14 + .../flow/def-site-variance/1/actual.js | 3 + .../flow/def-site-variance/1/expected.json | 336 ++++++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 test/fixtures/flow/def-site-variance/1/actual.js create mode 100644 test/fixtures/flow/def-site-variance/1/expected.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index f856955176..3ecaeb84e2 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -624,9 +624,23 @@ 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; diff --git a/test/fixtures/flow/def-site-variance/1/actual.js b/test/fixtures/flow/def-site-variance/1/actual.js new file mode 100644 index 0000000000..5eb19f458a --- /dev/null +++ b/test/fixtures/flow/def-site-variance/1/actual.js @@ -0,0 +1,3 @@ +class C<+T,-U> {} +function f<+T,-U>() {} +type T<+T,-U> = {} diff --git a/test/fixtures/flow/def-site-variance/1/expected.json b/test/fixtures/flow/def-site-variance/1/expected.json new file mode 100644 index 0000000000..b42edfb108 --- /dev/null +++ b/test/fixtures/flow/def-site-variance/1/expected.json @@ -0,0 +1,336 @@ +{ + "type": "File", + "start": 0, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "sourceType": "module", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 17 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "name": "C" + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 7, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "params": [ + { + "type": "Identifier", + "start": 9, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "name": "T", + "variance": "plus" + }, + { + "type": "Identifier", + "start": 12, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "name": "U", + "variance": "minus" + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 15, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 17 + } + }, + "body": [] + } + }, + { + "type": "FunctionDeclaration", + "start": 18, + "end": 40, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "id": { + "type": "Identifier", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 10 + } + }, + "name": "f" + }, + "generator": false, + "expression": false, + "async": false, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 28, + "end": 35, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 17 + } + }, + "params": [ + { + "type": "Identifier", + "start": 30, + "end": 31, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "name": "T", + "variance": "plus" + }, + { + "type": "Identifier", + "start": 33, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "name": "U", + "variance": "minus" + } + ] + }, + "params": [], + "body": { + "type": "BlockStatement", + "start": 38, + "end": 40, + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "body": [], + "directives": [] + } + }, + { + "type": "TypeAlias", + "start": 41, + "end": 59, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "id": { + "type": "Identifier", + "start": 46, + "end": 47, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + } + }, + "name": "T" + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 47, + "end": 54, + "loc": { + "start": { + "line": 3, + "column": 6 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "params": [ + { + "type": "Identifier", + "start": 49, + "end": 50, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + }, + "name": "T", + "variance": "plus" + }, + { + "type": "Identifier", + "start": 52, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "name": "U", + "variance": "minus" + } + ] + }, + "right": { + "type": "ObjectTypeAnnotation", + "start": 57, + "end": 59, + "loc": { + "start": { + "line": 3, + "column": 16 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "callProperties": [], + "properties": [], + "indexers": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file