From a411e1e73ddfcbc0b0aa3a7fd7883e4d3f97872f Mon Sep 17 00:00:00 2001 From: Panagiotis Vekris Date: Tue, 30 Aug 2016 21:48:54 -0700 Subject: [PATCH 1/5] [Flow] Function predicate declaration The accepted syntax for function declarations is extended to allow the following predicate declaration: FunctionReturnType := Type Predicate Type Predicate Predicate := %checks %checks ( ConditionalExpression ) --- src/plugins/flow.js | 53 +++- test/fixtures/flow/predicates/1/actual.js | 1 + test/fixtures/flow/predicates/1/expected.json | 226 +++++++++++++++ test/fixtures/flow/predicates/2/actual.js | 1 + test/fixtures/flow/predicates/2/expected.json | 256 +++++++++++++++++ test/fixtures/flow/predicates/3/actual.js | 1 + test/fixtures/flow/predicates/3/expected.json | 270 ++++++++++++++++++ 7 files changed, 805 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/flow/predicates/1/actual.js create mode 100644 test/fixtures/flow/predicates/1/expected.json create mode 100644 test/fixtures/flow/predicates/2/actual.js create mode 100644 test/fixtures/flow/predicates/2/expected.json create mode 100644 test/fixtures/flow/predicates/3/actual.js create mode 100644 test/fixtures/flow/predicates/3/expected.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 69139859fc..e5a48e86bc 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -21,6 +21,45 @@ pp.flowParseTypeInitialiser = function (tok, allowLeadingPipeOrAnd) { return type; }; +pp.flowParsePredicate = function() { + let node = this.startNode(); + let moduloLoc = this.state.startLoc; + let moduloPos = this.state.start; + this.expect(tt.modulo); + let checksLoc = this.state.startLoc; + this.expectContextual("checks"); + // Force '%' and 'checks' to be adjacent + if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) { + this.raise(moduloPos, "Unexpected token"); + } + if (this.match(tt.parenL)) { + this.next(); + node.expression = this.parseExpression(); + this.expect(tt.parenR); + return this.finishNode(node, "DeclaredPredicate"); + } else { + return this.finishNode(node, "InferredPredicate"); + } +}; + +pp.flowParseTypeAndPredicateInitialiser = function () { + let oldInType = this.state.inType; + this.state.inType = true; + this.expect(tt.colon); + let type = null; + let predicate = null; + if (this.match(tt.modulo)) { + predicate = this.flowParsePredicate(); + } else { + type = this.flowParseType(); + if (this.match(tt.modulo)) { + predicate = this.flowParsePredicate(); + } + } + this.state.inType = oldInType; + return [type, predicate]; +}; + pp.flowParseDeclareClass = function (node) { this.next(); this.flowParseInterfaceish(node, true); @@ -46,7 +85,7 @@ pp.flowParseDeclareFunction = function (node) { typeNode.params = tmp.params; typeNode.rest = tmp.rest; this.expect(tt.parenR); - typeNode.returnType = this.flowParseTypeInitialiser(); + [typeNode.returnType, node.predicate] = this.flowParseTypeAndPredicateInitialiser(); typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation"); id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation"); @@ -674,6 +713,13 @@ pp.flowParseTypeAnnotation = function () { return this.finishNode(node, "TypeAnnotation"); }; +pp.flowParseTypeAndPredicateAnnotation = function () { + let node = this.startNode(); + let predicate; + [node.typeAnnotation, predicate] = this.flowParseTypeAndPredicateInitialiser(); + return [this.finishNode(node, "TypeAnnotation"), predicate]; +}; + pp.flowParseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOptionalParam) { let ident = this.parseIdentifier(); @@ -715,7 +761,7 @@ export default function (instance) { if (this.match(tt.colon) && !allowExpression) { // if allowExpression is true then we're parsing an arrow function and if // there's a return type then it's been handled elsewhere - node.returnType = this.flowParseTypeAnnotation(); + [node.returnType, node.predicate] = this.flowParseTypeAndPredicateAnnotation(); } return inner.call(this, node, allowExpression); @@ -1161,10 +1207,11 @@ export default function (instance) { if (this.match(tt.colon)) { let state = this.state.clone(); try { - let returnType = this.flowParseTypeAnnotation(); + let [returnType, predicate] = this.flowParseTypeAndPredicateAnnotation(); if (!this.match(tt.arrow)) this.unexpected(); // assign after it is clear it is an arrow node.returnType = returnType; + node.predicate = predicate; } catch (err) { if (err instanceof SyntaxError) { this.state = state; diff --git a/test/fixtures/flow/predicates/1/actual.js b/test/fixtures/flow/predicates/1/actual.js new file mode 100644 index 0000000000..d1a1d71ebb --- /dev/null +++ b/test/fixtures/flow/predicates/1/actual.js @@ -0,0 +1 @@ +declare function foo(x: mixed): boolean %checks(x !== null); diff --git a/test/fixtures/flow/predicates/1/expected.json b/test/fixtures/flow/predicates/1/expected.json new file mode 100644 index 0000000000..4a08cb8bb8 --- /dev/null +++ b/test/fixtures/flow/predicates/1/expected.json @@ -0,0 +1,226 @@ +{ + "type": "File", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 60 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 60 + } + }, + "sourceType": "module", + "body": [ + { + "type": "DeclareFunction", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 60 + } + }, + "id": { + "type": "Identifier", + "start": 17, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 59 + }, + "identifierName": "foo" + }, + "name": "foo", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 20, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 59 + } + }, + "typeAnnotation": { + "type": "FunctionTypeAnnotation", + "start": 20, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 59 + } + }, + "typeParameters": null, + "params": [ + { + "type": "FunctionTypeParam", + "start": 21, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "name": { + "type": "Identifier", + "start": 21, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + }, + "identifierName": "x" + }, + "name": "x" + }, + "optional": false, + "typeAnnotation": { + "type": "MixedTypeAnnotation", + "start": 24, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 29 + } + } + } + } + ], + "rest": null, + "returnType": { + "type": "BooleanTypeAnnotation", + "start": 32, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 32 + }, + "end": { + "line": 1, + "column": 39 + } + } + } + } + } + }, + "predicate": { + "type": "DeclaredPredicate", + "start": 40, + "end": 59, + "loc": { + "start": { + "line": 1, + "column": 40 + }, + "end": { + "line": 1, + "column": 59 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 48, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 58 + } + }, + "left": { + "type": "Identifier", + "start": 48, + "end": 49, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 49 + }, + "identifierName": "x" + }, + "name": "x" + }, + "operator": "!==", + "right": { + "type": "NullLiteral", + "start": 54, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 54 + }, + "end": { + "line": 1, + "column": 58 + } + } + } + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/predicates/2/actual.js b/test/fixtures/flow/predicates/2/actual.js new file mode 100644 index 0000000000..e080d2b2c6 --- /dev/null +++ b/test/fixtures/flow/predicates/2/actual.js @@ -0,0 +1 @@ +var f = (x: mixed): %checks => typeof x === "string"; diff --git a/test/fixtures/flow/predicates/2/expected.json b/test/fixtures/flow/predicates/2/expected.json new file mode 100644 index 0000000000..de2075d5c4 --- /dev/null +++ b/test/fixtures/flow/predicates/2/expected.json @@ -0,0 +1,256 @@ +{ + "type": "File", + "start": 0, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 53 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 53 + } + }, + "sourceType": "module", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 53 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "f" + }, + "name": "f" + }, + "init": { + "type": "ArrowFunctionExpression", + "start": 8, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "returnType": { + "type": "TypeAnnotation", + "start": 18, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "typeAnnotation": null + }, + "predicate": { + "type": "InferredPredicate", + "start": 20, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 27 + } + } + }, + "id": null, + "generator": false, + "expression": true, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 9, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 17 + }, + "identifierName": "x" + }, + "name": "x", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 10, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 17 + } + }, + "typeAnnotation": { + "type": "MixedTypeAnnotation", + "start": 12, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + } + } + ], + "body": { + "type": "BinaryExpression", + "start": 31, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "left": { + "type": "UnaryExpression", + "start": 31, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 39 + } + }, + "operator": "typeof", + "prefix": true, + "argument": { + "type": "Identifier", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 38 + }, + "end": { + "line": 1, + "column": 39 + }, + "identifierName": "x" + }, + "name": "x" + }, + "extra": { + "parenthesizedArgument": false + } + }, + "operator": "===", + "right": { + "type": "StringLiteral", + "start": 44, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 44 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "extra": { + "rawValue": "string", + "raw": "\"string\"" + }, + "value": "string" + } + } + } + } + ], + "kind": "var" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/predicates/3/actual.js b/test/fixtures/flow/predicates/3/actual.js new file mode 100644 index 0000000000..adf3488a60 --- /dev/null +++ b/test/fixtures/flow/predicates/3/actual.js @@ -0,0 +1 @@ +function foo(x: mixed): %checks { return typeof x === "string"; }; diff --git a/test/fixtures/flow/predicates/3/expected.json b/test/fixtures/flow/predicates/3/expected.json new file mode 100644 index 0000000000..85cf61fb21 --- /dev/null +++ b/test/fixtures/flow/predicates/3/expected.json @@ -0,0 +1,270 @@ +{ + "type": "File", + "start": 0, + "end": 66, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 66 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 66, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 66 + } + }, + "sourceType": "module", + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 65, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 65 + } + }, + "id": { + "type": "Identifier", + "start": 9, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 12 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "generator": false, + "expression": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 13, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 21 + }, + "identifierName": "x" + }, + "name": "x", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 14, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "typeAnnotation": { + "type": "MixedTypeAnnotation", + "start": 16, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + } + } + } + } + ], + "returnType": { + "type": "TypeAnnotation", + "start": 22, + "end": 31, + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 31 + } + }, + "typeAnnotation": null + }, + "predicate": { + "type": "InferredPredicate", + "start": 24, + "end": 31, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 31 + } + } + }, + "body": { + "type": "BlockStatement", + "start": 32, + "end": 65, + "loc": { + "start": { + "line": 1, + "column": 32 + }, + "end": { + "line": 1, + "column": 65 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 34, + "end": 63, + "loc": { + "start": { + "line": 1, + "column": 34 + }, + "end": { + "line": 1, + "column": 63 + } + }, + "argument": { + "type": "BinaryExpression", + "start": 41, + "end": 62, + "loc": { + "start": { + "line": 1, + "column": 41 + }, + "end": { + "line": 1, + "column": 62 + } + }, + "left": { + "type": "UnaryExpression", + "start": 41, + "end": 49, + "loc": { + "start": { + "line": 1, + "column": 41 + }, + "end": { + "line": 1, + "column": 49 + } + }, + "operator": "typeof", + "prefix": true, + "argument": { + "type": "Identifier", + "start": 48, + "end": 49, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 49 + }, + "identifierName": "x" + }, + "name": "x" + }, + "extra": { + "parenthesizedArgument": false + } + }, + "operator": "===", + "right": { + "type": "StringLiteral", + "start": 54, + "end": 62, + "loc": { + "start": { + "line": 1, + "column": 54 + }, + "end": { + "line": 1, + "column": 62 + } + }, + "extra": { + "rawValue": "string", + "raw": "\"string\"" + }, + "value": "string" + } + } + } + ], + "directives": [] + } + }, + { + "type": "EmptyStatement", + "start": 65, + "end": 66, + "loc": { + "start": { + "line": 1, + "column": 65 + }, + "end": { + "line": 1, + "column": 66 + } + } + } + ], + "directives": [] + } +} \ No newline at end of file From 502b9966874c50a245c58f33104a4b245f57fe03 Mon Sep 17 00:00:00 2001 From: Panagiotis Vekris Date: Sat, 3 Sep 2016 23:51:17 -0700 Subject: [PATCH 2/5] [Flow] Minor tweaks and more examples to function predicates --- src/plugins/flow.js | 5 +++-- test/fixtures/flow/predicates/4/actual.js | 1 + test/fixtures/flow/predicates/4/options.json | 3 +++ test/fixtures/flow/predicates/5/actual.js | 3 +++ test/fixtures/flow/predicates/5/options.json | 3 +++ 5 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/flow/predicates/4/actual.js create mode 100644 test/fixtures/flow/predicates/4/options.json create mode 100644 test/fixtures/flow/predicates/5/actual.js create mode 100644 test/fixtures/flow/predicates/5/options.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index e5a48e86bc..bf84e4b959 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -30,7 +30,7 @@ pp.flowParsePredicate = function() { this.expectContextual("checks"); // Force '%' and 'checks' to be adjacent if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) { - this.raise(moduloPos, "Unexpected token"); + this.unexpected(moduloPos); } if (this.match(tt.parenL)) { this.next(); @@ -49,14 +49,15 @@ pp.flowParseTypeAndPredicateInitialiser = function () { let type = null; let predicate = null; if (this.match(tt.modulo)) { + this.state.inType = oldInType; predicate = this.flowParsePredicate(); } else { type = this.flowParseType(); + this.state.inType = oldInType; if (this.match(tt.modulo)) { predicate = this.flowParsePredicate(); } } - this.state.inType = oldInType; return [type, predicate]; }; diff --git a/test/fixtures/flow/predicates/4/actual.js b/test/fixtures/flow/predicates/4/actual.js new file mode 100644 index 0000000000..3c8bac89c9 --- /dev/null +++ b/test/fixtures/flow/predicates/4/actual.js @@ -0,0 +1 @@ +var f = (x: mixed): % checks => typeof x === "string"; diff --git a/test/fixtures/flow/predicates/4/options.json b/test/fixtures/flow/predicates/4/options.json new file mode 100644 index 0000000000..b8b06c3a03 --- /dev/null +++ b/test/fixtures/flow/predicates/4/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (1:18)" +} diff --git a/test/fixtures/flow/predicates/5/actual.js b/test/fixtures/flow/predicates/5/actual.js new file mode 100644 index 0000000000..35fc1dbfa8 --- /dev/null +++ b/test/fixtures/flow/predicates/5/actual.js @@ -0,0 +1,3 @@ +function foo(x): % checks { + return typeof x === "string"; +} diff --git a/test/fixtures/flow/predicates/5/options.json b/test/fixtures/flow/predicates/5/options.json new file mode 100644 index 0000000000..e806dd7b3a --- /dev/null +++ b/test/fixtures/flow/predicates/5/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (1:17)" +} From 7c81009ce100c072dbe4316d27910a07828f885a Mon Sep 17 00:00:00 2001 From: Panagiotis Vekris Date: Tue, 17 Jan 2017 01:05:08 -0800 Subject: [PATCH 3/5] [Flow] Clean-up and better message for function predicates --- src/plugins/flow.js | 5 ++--- test/fixtures/flow/predicates/5/options.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 24fcc4991d..e4c83b8b8b 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -25,10 +25,9 @@ pp.flowParsePredicate = function() { this.expectContextual("checks"); // Force '%' and 'checks' to be adjacent if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) { - this.unexpected(moduloPos); + this.raise(moduloPos, "Spaces between ´%´ and ´checks´ are not allowed here."); } - if (this.match(tt.parenL)) { - this.next(); + if (this.eat(tt.parenL)) { node.expression = this.parseExpression(); this.expect(tt.parenR); return this.finishNode(node, "DeclaredPredicate"); diff --git a/test/fixtures/flow/predicates/5/options.json b/test/fixtures/flow/predicates/5/options.json index e806dd7b3a..dbdc7697ac 100644 --- a/test/fixtures/flow/predicates/5/options.json +++ b/test/fixtures/flow/predicates/5/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:17)" + "throws": "Spaces between ´%´ and ´checks´ are not allowed here. (1:17)" } From f972e80e211d04764a2ec8184abcb416b9fac566 Mon Sep 17 00:00:00 2001 From: Panagiotis Vekris Date: Tue, 17 Jan 2017 08:45:56 -0800 Subject: [PATCH 4/5] [Flow] Adding abstract function predicate example --- test/fixtures/flow/predicates/6/actual.js | 1 + test/fixtures/flow/predicates/6/expected.json | 600 ++++++++++++++++++ 2 files changed, 601 insertions(+) create mode 100644 test/fixtures/flow/predicates/6/actual.js create mode 100644 test/fixtures/flow/predicates/6/expected.json diff --git a/test/fixtures/flow/predicates/6/actual.js b/test/fixtures/flow/predicates/6/actual.js new file mode 100644 index 0000000000..f1fbd33e6d --- /dev/null +++ b/test/fixtures/flow/predicates/6/actual.js @@ -0,0 +1 @@ +declare function my_filter>(v: Array, cb: P): Array<$Refine>; diff --git a/test/fixtures/flow/predicates/6/expected.json b/test/fixtures/flow/predicates/6/expected.json new file mode 100644 index 0000000000..d241da6a18 --- /dev/null +++ b/test/fixtures/flow/predicates/6/expected.json @@ -0,0 +1,600 @@ +{ + "type": "File", + "start": 0, + "end": 86, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 86 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 86, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 86 + } + }, + "sourceType": "module", + "body": [ + { + "type": "DeclareFunction", + "start": 0, + "end": 86, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 86 + } + }, + "id": { + "type": "Identifier", + "start": 17, + "end": 85, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 85 + }, + "identifierName": "my_filter" + }, + "name": "my_filter", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 26, + "end": 85, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 85 + } + }, + "typeAnnotation": { + "type": "FunctionTypeAnnotation", + "start": 26, + "end": 85, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 85 + } + }, + "typeParameters": { + "type": "TypeParameterDeclaration", + "start": 26, + "end": 42, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 42 + } + }, + "params": [ + { + "type": "TypeParameter", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 27 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "name": "T", + "variance": null + }, + { + "type": "TypeParameter", + "start": 30, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 30 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "name": "P", + "variance": null, + "bound": { + "type": "TypeAnnotation", + "start": 31, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 33, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "typeParameters": { + "type": "TypeParameterInstantiation", + "start": 38, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 38 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "params": [ + { + "type": "NumericLiteralTypeAnnotation", + "start": 39, + "end": 40, + "loc": { + "start": { + "line": 1, + "column": 39 + }, + "end": { + "line": 1, + "column": 40 + } + }, + "value": 1, + "extra": { + "rawValue": 1, + "raw": "1" + } + } + ] + }, + "id": { + "type": "Identifier", + "start": 33, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 38 + }, + "identifierName": "$Pred" + }, + "name": "$Pred" + } + } + } + } + ] + }, + "params": [ + { + "type": "FunctionTypeParam", + "start": 43, + "end": 54, + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 54 + } + }, + "name": { + "type": "Identifier", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 1, + "column": 43 + }, + "end": { + "line": 1, + "column": 44 + }, + "identifierName": "v" + }, + "name": "v" + }, + "optional": false, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 46, + "end": 54, + "loc": { + "start": { + "line": 1, + "column": 46 + }, + "end": { + "line": 1, + "column": 54 + } + }, + "typeParameters": { + "type": "TypeParameterInstantiation", + "start": 51, + "end": 54, + "loc": { + "start": { + "line": 1, + "column": 51 + }, + "end": { + "line": 1, + "column": 54 + } + }, + "params": [ + { + "type": "GenericTypeAnnotation", + "start": 52, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 52 + }, + "end": { + "line": 1, + "column": 53 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 52, + "end": 53, + "loc": { + "start": { + "line": 1, + "column": 52 + }, + "end": { + "line": 1, + "column": 53 + }, + "identifierName": "T" + }, + "name": "T" + } + } + ] + }, + "id": { + "type": "Identifier", + "start": 46, + "end": 51, + "loc": { + "start": { + "line": 1, + "column": 46 + }, + "end": { + "line": 1, + "column": 51 + }, + "identifierName": "Array" + }, + "name": "Array" + } + } + }, + { + "type": "FunctionTypeParam", + "start": 56, + "end": 61, + "loc": { + "start": { + "line": 1, + "column": 56 + }, + "end": { + "line": 1, + "column": 61 + } + }, + "name": { + "type": "Identifier", + "start": 56, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 56 + }, + "end": { + "line": 1, + "column": 58 + }, + "identifierName": "cb" + }, + "name": "cb" + }, + "optional": false, + "typeAnnotation": { + "type": "GenericTypeAnnotation", + "start": 60, + "end": 61, + "loc": { + "start": { + "line": 1, + "column": 60 + }, + "end": { + "line": 1, + "column": 61 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 60, + "end": 61, + "loc": { + "start": { + "line": 1, + "column": 60 + }, + "end": { + "line": 1, + "column": 61 + }, + "identifierName": "P" + }, + "name": "P" + } + } + } + ], + "rest": null, + "returnType": { + "type": "GenericTypeAnnotation", + "start": 64, + "end": 85, + "loc": { + "start": { + "line": 1, + "column": 64 + }, + "end": { + "line": 1, + "column": 85 + } + }, + "typeParameters": { + "type": "TypeParameterInstantiation", + "start": 69, + "end": 85, + "loc": { + "start": { + "line": 1, + "column": 69 + }, + "end": { + "line": 1, + "column": 85 + } + }, + "params": [ + { + "type": "GenericTypeAnnotation", + "start": 70, + "end": 84, + "loc": { + "start": { + "line": 1, + "column": 70 + }, + "end": { + "line": 1, + "column": 84 + } + }, + "typeParameters": { + "type": "TypeParameterInstantiation", + "start": 77, + "end": 84, + "loc": { + "start": { + "line": 1, + "column": 77 + }, + "end": { + "line": 1, + "column": 84 + } + }, + "params": [ + { + "type": "GenericTypeAnnotation", + "start": 78, + "end": 79, + "loc": { + "start": { + "line": 1, + "column": 78 + }, + "end": { + "line": 1, + "column": 79 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 78, + "end": 79, + "loc": { + "start": { + "line": 1, + "column": 78 + }, + "end": { + "line": 1, + "column": 79 + }, + "identifierName": "T" + }, + "name": "T" + } + }, + { + "type": "GenericTypeAnnotation", + "start": 80, + "end": 81, + "loc": { + "start": { + "line": 1, + "column": 80 + }, + "end": { + "line": 1, + "column": 81 + } + }, + "typeParameters": null, + "id": { + "type": "Identifier", + "start": 80, + "end": 81, + "loc": { + "start": { + "line": 1, + "column": 80 + }, + "end": { + "line": 1, + "column": 81 + }, + "identifierName": "P" + }, + "name": "P" + } + }, + { + "type": "NumericLiteralTypeAnnotation", + "start": 82, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 82 + }, + "end": { + "line": 1, + "column": 83 + } + }, + "value": 1, + "extra": { + "rawValue": 1, + "raw": "1" + } + } + ] + }, + "id": { + "type": "Identifier", + "start": 70, + "end": 77, + "loc": { + "start": { + "line": 1, + "column": 70 + }, + "end": { + "line": 1, + "column": 77 + }, + "identifierName": "$Refine" + }, + "name": "$Refine" + } + } + ] + }, + "id": { + "type": "Identifier", + "start": 64, + "end": 69, + "loc": { + "start": { + "line": 1, + "column": 64 + }, + "end": { + "line": 1, + "column": 69 + }, + "identifierName": "Array" + }, + "name": "Array" + } + } + } + } + }, + "predicate": null + } + ], + "directives": [] + } +} \ No newline at end of file From e42d60c8af63e29df5bd261e652aaf634a9701d8 Mon Sep 17 00:00:00 2001 From: Panagiotis Vekris Date: Tue, 17 Jan 2017 13:10:19 -0800 Subject: [PATCH 5/5] [Flow] Rearranging the `predicate` field to ease babel generator. --- src/plugins/flow.js | 18 ++- test/fixtures/flow/predicates/1/expected.json | 106 +++++++++--------- test/fixtures/flow/predicates/2/expected.json | 30 ++--- test/fixtures/flow/predicates/3/expected.json | 30 ++--- test/fixtures/flow/predicates/6/expected.json | 5 +- 5 files changed, 92 insertions(+), 97 deletions(-) diff --git a/src/plugins/flow.js b/src/plugins/flow.js index e4c83b8b8b..94cb78c3a4 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -80,9 +80,10 @@ pp.flowParseDeclareFunction = function (node) { typeNode.params = tmp.params; typeNode.rest = tmp.rest; this.expect(tt.parenR); - [typeNode.returnType, node.predicate] = this.flowParseTypeAndPredicateInitialiser(); - + let predicate = null; + [typeNode.returnType, predicate] = this.flowParseTypeAndPredicateInitialiser(); typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation"); + typeContainer.predicate = predicate; id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation"); this.finishNode(id, id.type); @@ -799,10 +800,8 @@ pp.flowParseTypeAnnotation = function () { pp.flowParseTypeAndPredicateAnnotation = function () { const node = this.startNode(); - const typeAnnotationAndPredicate = this.flowParseTypeAndPredicateInitialiser(); - node.typeAnnotation = typeAnnotationAndPredicate[0]; - const predicate = typeAnnotationAndPredicate[1]; - return [this.finishNode(node, "TypeAnnotation"), predicate]; + [node.typeAnnotation, node.predicate] = this.flowParseTypeAndPredicateInitialiser(); + return this.finishNode(node, "TypeAnnotation"); }; pp.flowParseTypeAnnotatableIdentifier = function () { @@ -845,7 +844,7 @@ export default function (instance) { if (this.match(tt.colon) && !allowExpression) { // if allowExpression is true then we're parsing an arrow function and if // there's a return type then it's been handled elsewhere - [node.returnType, node.predicate] = this.flowParseTypeAndPredicateAnnotation(); + node.returnType = this.flowParseTypeAndPredicateAnnotation(); } return inner.call(this, node, allowExpression); @@ -1387,16 +1386,13 @@ export default function (instance) { try { const oldNoAnonFunctionType = this.state.noAnonFunctionType; this.state.noAnonFunctionType = true; - // const returnType = this.flowParseTypeAnnotation(); - const [returnType, predicate] = this.flowParseTypeAndPredicateAnnotation(); - + const returnType = this.flowParseTypeAndPredicateAnnotation(); this.state.noAnonFunctionType = oldNoAnonFunctionType; if (this.canInsertSemicolon()) this.unexpected(); if (!this.match(tt.arrow)) this.unexpected(); // assign after it is clear it is an arrow node.returnType = returnType; - node.predicate = predicate; } catch (err) { if (err instanceof SyntaxError) { this.state = state; diff --git a/test/fixtures/flow/predicates/1/expected.json b/test/fixtures/flow/predicates/1/expected.json index 4a08cb8bb8..eb81514fc4 100644 --- a/test/fixtures/flow/predicates/1/expected.json +++ b/test/fixtures/flow/predicates/1/expected.json @@ -153,67 +153,67 @@ } } } - } - } - }, - "predicate": { - "type": "DeclaredPredicate", - "start": 40, - "end": 59, - "loc": { - "start": { - "line": 1, - "column": 40 }, - "end": { - "line": 1, - "column": 59 - } - }, - "expression": { - "type": "BinaryExpression", - "start": 48, - "end": 58, - "loc": { - "start": { - "line": 1, - "column": 48 - }, - "end": { - "line": 1, - "column": 58 - } - }, - "left": { - "type": "Identifier", - "start": 48, - "end": 49, + "predicate": { + "type": "DeclaredPredicate", + "start": 40, + "end": 59, "loc": { "start": { "line": 1, - "column": 48 + "column": 40 }, "end": { "line": 1, - "column": 49 - }, - "identifierName": "x" + "column": 59 + } }, - "name": "x" - }, - "operator": "!==", - "right": { - "type": "NullLiteral", - "start": 54, - "end": 58, - "loc": { - "start": { - "line": 1, - "column": 54 + "expression": { + "type": "BinaryExpression", + "start": 48, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 58 + } }, - "end": { - "line": 1, - "column": 58 + "left": { + "type": "Identifier", + "start": 48, + "end": 49, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 49 + }, + "identifierName": "x" + }, + "name": "x" + }, + "operator": "!==", + "right": { + "type": "NullLiteral", + "start": 54, + "end": 58, + "loc": { + "start": { + "line": 1, + "column": 54 + }, + "end": { + "line": 1, + "column": 58 + } + } } } } @@ -223,4 +223,4 @@ ], "directives": [] } -} \ No newline at end of file +} diff --git a/test/fixtures/flow/predicates/2/expected.json b/test/fixtures/flow/predicates/2/expected.json index de2075d5c4..64df4c2006 100644 --- a/test/fixtures/flow/predicates/2/expected.json +++ b/test/fixtures/flow/predicates/2/expected.json @@ -102,20 +102,20 @@ "column": 27 } }, - "typeAnnotation": null - }, - "predicate": { - "type": "InferredPredicate", - "start": 20, - "end": 27, - "loc": { - "start": { - "line": 1, - "column": 20 - }, - "end": { - "line": 1, - "column": 27 + "typeAnnotation": null, + "predicate": { + "type": "InferredPredicate", + "start": 20, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 27 + } } } }, @@ -253,4 +253,4 @@ ], "directives": [] } -} \ No newline at end of file +} diff --git a/test/fixtures/flow/predicates/3/expected.json b/test/fixtures/flow/predicates/3/expected.json index 85cf61fb21..8553cc335f 100644 --- a/test/fixtures/flow/predicates/3/expected.json +++ b/test/fixtures/flow/predicates/3/expected.json @@ -125,20 +125,20 @@ "column": 31 } }, - "typeAnnotation": null - }, - "predicate": { - "type": "InferredPredicate", - "start": 24, - "end": 31, - "loc": { - "start": { - "line": 1, - "column": 24 - }, - "end": { - "line": 1, - "column": 31 + "typeAnnotation": null, + "predicate": { + "type": "InferredPredicate", + "start": 24, + "end": 31, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 31 + } } } }, @@ -267,4 +267,4 @@ ], "directives": [] } -} \ No newline at end of file +} diff --git a/test/fixtures/flow/predicates/6/expected.json b/test/fixtures/flow/predicates/6/expected.json index d241da6a18..0805a80bd3 100644 --- a/test/fixtures/flow/predicates/6/expected.json +++ b/test/fixtures/flow/predicates/6/expected.json @@ -591,10 +591,9 @@ } } } - }, - "predicate": null + } } ], "directives": [] } -} \ No newline at end of file +}