diff --git a/src/parser/expression.js b/src/parser/expression.js index a520b7fe2d..2f00e5d1a5 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -577,7 +577,7 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow this.expect(tt.parenR); let arrowNode = this.startNodeAt(startPos, startLoc); - if (canBeArrow && !this.canInsertSemicolon() && (arrowNode = this.parseArrow(arrowNode))) { + if (canBeArrow && this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode))) { for (let param of exprList) { if (param.extra && param.extra.parenthesized) this.unexpected(param.extra.parenStart); } @@ -613,6 +613,10 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow return val; }; +pp.shouldParseArrow = function () { + return !this.canInsertSemicolon(); +}; + pp.parseArrow = function (node) { if (this.eat(tt.arrow)) { return node; diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 95cbefe4f7..ef9a73a073 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1178,6 +1178,7 @@ export default function (instance) { let state = this.state.clone(); try { let returnType = this.flowParseTypeAnnotation(); + if (this.canInsertSemicolon()) this.unexpected(); if (!this.match(tt.arrow)) this.unexpected(); // assign after it is clear it is an arrow node.returnType = returnType; @@ -1194,6 +1195,12 @@ export default function (instance) { }; }); + instance.extend("shouldParseArrow", function (inner) { + return function () { + return this.match(tt.colon) || inner.call(this); + }; + }); + instance.extend("isClassMutatorStarter", function (inner) { return function () { if (this.isRelational("<")) { diff --git a/test/fixtures/flow/type-annotations/arrow-func-return-newline/actual.js b/test/fixtures/flow/type-annotations/arrow-func-return-newline/actual.js new file mode 100644 index 0000000000..0ab00aa677 --- /dev/null +++ b/test/fixtures/flow/type-annotations/arrow-func-return-newline/actual.js @@ -0,0 +1,2 @@ +const x = (foo: string) +: number => {} diff --git a/test/fixtures/flow/type-annotations/arrow-func-return-newline/expected.json b/test/fixtures/flow/type-annotations/arrow-func-return-newline/expected.json new file mode 100644 index 0000000000..cf9973aad7 --- /dev/null +++ b/test/fixtures/flow/type-annotations/arrow-func-return-newline/expected.json @@ -0,0 +1,199 @@ +{ + "type": "File", + "start": 0, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "sourceType": "module", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 6, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "x" + }, + "name": "x" + }, + "init": { + "type": "ArrowFunctionExpression", + "start": 10, + "end": 38, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "returnType": { + "type": "TypeAnnotation", + "start": 24, + "end": 32, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "typeAnnotation": { + "type": "NumberTypeAnnotation", + "start": 26, + "end": 32, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 8 + } + } + } + }, + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 11, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 22 + }, + "identifierName": "foo" + }, + "name": "foo", + "typeAnnotation": { + "type": "TypeAnnotation", + "start": 14, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "typeAnnotation": { + "type": "StringTypeAnnotation", + "start": 16, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 22 + } + } + } + } + } + ], + "body": { + "type": "BlockStatement", + "start": 36, + "end": 38, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "body": [], + "directives": [] + } + } + } + ], + "kind": "const" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/actual.js b/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/actual.js new file mode 100644 index 0000000000..f7dfb8b119 --- /dev/null +++ b/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/actual.js @@ -0,0 +1,2 @@ +(): string +=> {} \ No newline at end of file diff --git a/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/options.json b/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/options.json new file mode 100644 index 0000000000..a659adb24d --- /dev/null +++ b/test/fixtures/flow/type-annotations/invalid-line-terminator-arrow/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (1:1)" +}