From aa3cefb63d75ec91b50717ffb41e994b6dd0b3f6 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Tue, 10 Mar 2015 20:59:16 -0400 Subject: [PATCH] Check that arrow is on same line as parameters --- src/compiler/checker.ts | 11 +-- src/compiler/parser.ts | 19 ++--- src/compiler/types.ts | 4 +- .../baselines/reference/APISample_compile.js | 4 +- .../reference/APISample_compile.types | 12 ++-- tests/baselines/reference/APISample_linter.js | 4 +- .../reference/APISample_linter.types | 12 ++-- .../reference/APISample_transform.js | 4 +- .../reference/APISample_transform.types | 12 ++-- .../baselines/reference/APISample_watcher.js | 4 +- .../reference/APISample_watcher.types | 12 ++-- ...sallowLineTerminatorBeforeArrow.errors.txt | 70 ++++++++----------- 12 files changed, 82 insertions(+), 86 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dae254253ca..8322bb7c5d3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11381,11 +11381,12 @@ module ts { } function checkGrammarArrowFunction(node: FunctionLikeDeclaration): boolean { - if (node.kind === SyntaxKind.ArrowFunction) { - if ((node).lineTerminatorBeforeArrow) { - grammarErrorOnNode(node, Diagnostics.Line_terminator_not_permitted_before_arrow); - return true; - } + if (node.kind === SyntaxKind.ArrowFunction && (node).arrow) { + var arrowFunction = node; + var sourceFile = getSourceFileOfNode(node); + if (getLineAndCharacterOfPosition(sourceFile, getTokenPosOfNode(arrowFunction.arrow, sourceFile)).line !== getLineAndCharacterOfPosition(sourceFile, arrowFunction.parameters.end).line) { + return grammarErrorOnNode(arrowFunction.arrow, Diagnostics.Line_terminator_not_permitted_before_arrow); + } } return false; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 06655b1d822..6b010f584a2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -95,6 +95,7 @@ module ts { visitNodes(cbNodes, (node).typeParameters) || visitNodes(cbNodes, (node).parameters) || visitNode(cbNode, (node).type) || + visitNode(cbNode, (node).arrow) || visitNode(cbNode, (node).body); case SyntaxKind.TypeReference: return visitNode(cbNode, (node).typeName) || @@ -3006,18 +3007,19 @@ module ts { function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression { Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); - let node = createNode(SyntaxKind.ArrowFunction, identifier.pos); + let node = createNode(SyntaxKind.ArrowFunction, identifier.pos); let parameter = createNode(SyntaxKind.Parameter, identifier.pos); - parameter.name = identifier; + parameter.name = identifier; finishNode(parameter); node.parameters = >[parameter]; node.parameters.pos = parameter.pos; node.parameters.end = parameter.end; - node.lineTerminatorBeforeArrow = scanner.hasPrecedingLineBreak(); - parseExpected(SyntaxKind.EqualsGreaterThanToken); + if ((node.arrow = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>"))) { + node.arrow.parent = node; + } node.body = parseArrowFunctionExpressionBody(); return finishNode(node); @@ -3046,7 +3048,8 @@ module ts { // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. - if (parseExpected(SyntaxKind.EqualsGreaterThanToken) || token === SyntaxKind.OpenBraceToken) { + if ((arrowFunction.arrow = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>")) || token === SyntaxKind.OpenBraceToken) { + arrowFunction.arrow.parent = arrowFunction; arrowFunction.body = parseArrowFunctionExpressionBody(); } else { @@ -3141,9 +3144,9 @@ module ts { } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): FunctionExpression { - let node = createNode(SyntaxKind.ArrowFunction); + let node = createNode(SyntaxKind.ArrowFunction); // Arrow functions are never generators. - // + // // If we're speculatively parsing a signature for a parenthesized arrow function, then // we have to have a complete parameter list. Otherwise we might see something like // a => (b => c) @@ -3169,8 +3172,6 @@ module ts { return undefined; } - node.lineTerminatorBeforeArrow = scanner.hasPrecedingLineBreak(); - return node; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 56820a10924..49529bed9c6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -653,8 +653,8 @@ module ts { body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional } - export interface ArrowFunctionExpression extends FunctionExpression { - lineTerminatorBeforeArrow: boolean; + export interface ArrowFunction extends Expression, FunctionLikeDeclaration { + arrow: Node; } // The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral, diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index 316649a35c9..997bd2bd337 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -553,8 +553,8 @@ declare module "typescript" { name?: Identifier; body: Block | Expression; } - interface ArrowFunctionExpression extends FunctionExpression { - lineTerminatorBeforeArrow: boolean; + interface ArrowFunction extends Expression, FunctionLikeDeclaration { + arrow: Node; } interface LiteralExpression extends PrimaryExpression { text: string; diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index bf51bb946c0..d91d860ca8f 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -1669,12 +1669,14 @@ declare module "typescript" { >Block : Block >Expression : Expression } - interface ArrowFunctionExpression extends FunctionExpression { ->ArrowFunctionExpression : ArrowFunctionExpression ->FunctionExpression : FunctionExpression + interface ArrowFunction extends Expression, FunctionLikeDeclaration { +>ArrowFunction : ArrowFunction +>Expression : Expression +>FunctionLikeDeclaration : FunctionLikeDeclaration - lineTerminatorBeforeArrow: boolean; ->lineTerminatorBeforeArrow : boolean + arrow: Node; +>arrow : Node +>Node : Node } interface LiteralExpression extends PrimaryExpression { >LiteralExpression : LiteralExpression diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 5f7dc308820..b941acdbc52 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -584,8 +584,8 @@ declare module "typescript" { name?: Identifier; body: Block | Expression; } - interface ArrowFunctionExpression extends FunctionExpression { - lineTerminatorBeforeArrow: boolean; + interface ArrowFunction extends Expression, FunctionLikeDeclaration { + arrow: Node; } interface LiteralExpression extends PrimaryExpression { text: string; diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index ede73749eb0..b8701020e03 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -1815,12 +1815,14 @@ declare module "typescript" { >Block : Block >Expression : Expression } - interface ArrowFunctionExpression extends FunctionExpression { ->ArrowFunctionExpression : ArrowFunctionExpression ->FunctionExpression : FunctionExpression + interface ArrowFunction extends Expression, FunctionLikeDeclaration { +>ArrowFunction : ArrowFunction +>Expression : Expression +>FunctionLikeDeclaration : FunctionLikeDeclaration - lineTerminatorBeforeArrow: boolean; ->lineTerminatorBeforeArrow : boolean + arrow: Node; +>arrow : Node +>Node : Node } interface LiteralExpression extends PrimaryExpression { >LiteralExpression : LiteralExpression diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index 2d39e9a3c0c..baf3f9d8503 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -585,8 +585,8 @@ declare module "typescript" { name?: Identifier; body: Block | Expression; } - interface ArrowFunctionExpression extends FunctionExpression { - lineTerminatorBeforeArrow: boolean; + interface ArrowFunction extends Expression, FunctionLikeDeclaration { + arrow: Node; } interface LiteralExpression extends PrimaryExpression { text: string; diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index d9d1482fbc8..d214a6fc959 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -1765,12 +1765,14 @@ declare module "typescript" { >Block : Block >Expression : Expression } - interface ArrowFunctionExpression extends FunctionExpression { ->ArrowFunctionExpression : ArrowFunctionExpression ->FunctionExpression : FunctionExpression + interface ArrowFunction extends Expression, FunctionLikeDeclaration { +>ArrowFunction : ArrowFunction +>Expression : Expression +>FunctionLikeDeclaration : FunctionLikeDeclaration - lineTerminatorBeforeArrow: boolean; ->lineTerminatorBeforeArrow : boolean + arrow: Node; +>arrow : Node +>Node : Node } interface LiteralExpression extends PrimaryExpression { >LiteralExpression : LiteralExpression diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index 7fa2a92afae..d963aaff481 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -622,8 +622,8 @@ declare module "typescript" { name?: Identifier; body: Block | Expression; } - interface ArrowFunctionExpression extends FunctionExpression { - lineTerminatorBeforeArrow: boolean; + interface ArrowFunction extends Expression, FunctionLikeDeclaration { + arrow: Node; } interface LiteralExpression extends PrimaryExpression { text: string; diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 23f7ffb7148..da00b9bf466 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -1938,12 +1938,14 @@ declare module "typescript" { >Block : Block >Expression : Expression } - interface ArrowFunctionExpression extends FunctionExpression { ->ArrowFunctionExpression : ArrowFunctionExpression ->FunctionExpression : FunctionExpression + interface ArrowFunction extends Expression, FunctionLikeDeclaration { +>ArrowFunction : ArrowFunction +>Expression : Expression +>FunctionLikeDeclaration : FunctionLikeDeclaration - lineTerminatorBeforeArrow: boolean; ->lineTerminatorBeforeArrow : boolean + arrow: Node; +>arrow : Node +>Node : Node } interface LiteralExpression extends PrimaryExpression { >LiteralExpression : LiteralExpression diff --git a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.errors.txt b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.errors.txt index e9f07998504..e441752338c 100644 --- a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.errors.txt +++ b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.errors.txt @@ -1,101 +1,87 @@ -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(1,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(3,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(5,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(7,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(9,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(11,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(13,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(15,10): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(19,5): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(21,5): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(26,40): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(30,20): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(35,17): error TS1200: Line terminator not permitted before arrow. -tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(39,20): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(2,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(4,7): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(6,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(8,7): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(10,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(12,7): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(14,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(16,7): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(20,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(22,5): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(27,13): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(31,13): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(36,13): error TS1200: Line terminator not permitted before arrow. +tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts(40,9): error TS1200: Line terminator not permitted before arrow. ==== tests/cases/conformance/es6/arrowFunction/disallowLineTerminatorBeforeArrow.ts (14 errors) ==== var f1 = () - ~~ => { } - ~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f2 = (x: string, y: string) /* - ~~~~~~~~~~~~~~~~~~~~~~~~~ */ => { } - ~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f3 = (x: string, y: number, ...rest) - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => { } - ~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f4 = (x: string, y: number, ...rest) /* - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ => { } - ~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f5 = (...rest) - ~~~~~~~~~ => { } - ~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f6 = (...rest) /* - ~~~~~~~~~~~~ */ => { } - ~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f7 = (x: string, y: number, z = 10) - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => { } - ~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. var f8 = (x: string, y: number, z = 10) /* - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ => { } - ~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. function foo(func: () => boolean) { } foo(() - ~~ => true); - ~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. foo(() - ~~ => { return false; }); - ~~~~~~~~~~~~~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. module m { class City { constructor(x: number, thing = () - ~~ => 100) { - ~~~~~~~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. } public m = () - ~~ => 2 * 2 * 2 - ~~~~~~~~~~~~~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. } export enum Enum { claw = (() - ~~ => 10)() - ~~~~~~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. } export var v = x - ~ => new City(Enum.claw); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~ !!! error TS1200: Line terminator not permitted before arrow. } \ No newline at end of file