From 57d7cf54c696a67017791db09976df4769e1d834 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 23 Jul 2014 13:31:24 -0700 Subject: [PATCH] Improved "certainty" when parsing arrow-function-lookin' expressions. --- src/compiler/parser.ts | 22 +++++++++++++++---- .../arrowFunctionsMissingTokens.errors.txt | 22 ++++--------------- ...serErrorRecovery_ParameterList5.errors.txt | 12 ++++------ .../parserUnterminatedGeneric2.errors.txt | 22 +++---------------- .../parserX_ArrowFunction1.errors.txt | 10 ++------- 5 files changed, 31 insertions(+), 57 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index cdcf9345be9..df45db2a415 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1448,12 +1448,10 @@ module ts { // Indicates whether we are certain that we should parse an arrow expression. var triState = isParenthesizedArrowFunctionExpression(); - // It is not a parenthesized arrow function. if (triState === Tristate.False) { return undefined; } - // If we're certain that we have an arrow function expression, then just parse one out. if (triState === Tristate.True) { var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken); @@ -1468,8 +1466,8 @@ module ts { } } - // Otherwise, *maybe* we had an arrow function and we need to *try* to parse it out - // (which will ensure we rollback if we fail). + // *Maybe* we had an arrow function and we need to try to parse it out, + // rolling back and trying other parses if we fail. var sig = tryParse(parseSignatureIfArrowOrBraceFollows); if (sig === undefined) { return undefined; @@ -1522,6 +1520,12 @@ module ts { return Tristate.False; } + // If we have something like "(a:", then we must have a + // type-annotated parameter in an arrow function expression. + if (nextToken() === SyntaxKind.ColonToken) { + return Tristate.True; + } + // This *could* be a parenthesized arrow function. // Return Unknown to let the caller know. return Tristate.Unknown; @@ -1547,9 +1551,19 @@ module ts { function parseSignatureIfArrowOrBraceFollows(): ParsedSignature { var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken); + + // Parsing a signature isn't enough. + // Parenthesized arrow signatures often look like other valid expressions. + // For instance: + // - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value. + // - "(x,y)" is a comma expression parsed as a signature with two parameters. + // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation. + // + // So we need just a bit of lookahead to ensure that it can only be a signature. if (token === SyntaxKind.EqualsGreaterThanToken || token === SyntaxKind.OpenBraceToken) { return sig; } + return undefined; } diff --git a/tests/baselines/reference/arrowFunctionsMissingTokens.errors.txt b/tests/baselines/reference/arrowFunctionsMissingTokens.errors.txt index 61a3bb002e7..f6072db0839 100644 --- a/tests/baselines/reference/arrowFunctionsMissingTokens.errors.txt +++ b/tests/baselines/reference/arrowFunctionsMissingTokens.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/arrowFunctionsMissingTokens.ts (31 errors) ==== +==== tests/cases/compiler/arrowFunctionsMissingTokens.ts (24 errors) ==== module missingArrowsWithCurly { var a = () { }; @@ -94,26 +94,12 @@ !!! Cannot find name 'x'. var d = (x: number, y: string); - ~ -!!! ')' expected. - ~ -!!! ',' expected. - ~ -!!! Cannot find name 'x'. + ~ +!!! '=>' expected. var e = (x: number, y: string): void; - ~ -!!! ')' expected. - ~ -!!! ',' expected. - ~ -!!! Variable declaration expected. - ~~~~ -!!! Variable declaration expected. ~ -!!! Expression expected. - ~ -!!! Cannot find name 'x'. +!!! '=>' expected. } module okay { diff --git a/tests/baselines/reference/parserErrorRecovery_ParameterList5.errors.txt b/tests/baselines/reference/parserErrorRecovery_ParameterList5.errors.txt index 7e22c1e111f..ba862a3afb6 100644 --- a/tests/baselines/reference/parserErrorRecovery_ParameterList5.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ParameterList5.errors.txt @@ -1,10 +1,6 @@ -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList5.ts (4 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList5.ts (2 errors) ==== (a:number => { } - ~ -!!! ')' expected. ~~ -!!! ';' expected. - ~ -!!! Cannot find name 'a'. - ~~~~~~ -!!! Cannot find name 'number'. \ No newline at end of file +!!! ',' expected. + ~ +!!! ')' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserUnterminatedGeneric2.errors.txt b/tests/baselines/reference/parserUnterminatedGeneric2.errors.txt index f0ab0ad10b1..8d9a411a7eb 100644 --- a/tests/baselines/reference/parserUnterminatedGeneric2.errors.txt +++ b/tests/baselines/reference/parserUnterminatedGeneric2.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserUnterminatedGeneric2.ts (23 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserUnterminatedGeneric2.ts (15 errors) ==== declare module ng { interfaceICompiledExpression { ~ @@ -6,24 +6,8 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! Cannot find name 'interfaceICompiledExpression'. (context: any, locals?: any): any; - ~ -!!! ')' expected. - ~ -!!! Expression expected. - ~ -!!! ';' expected. - ~ -!!! Statement expected. - ~~~~~~~ -!!! Cannot find name 'context'. - ~~~ -!!! Cannot find name 'any'. - ~~~~~~ -!!! Cannot find name 'locals'. - ~~~ -!!! Cannot find name 'any'. - ~~~ -!!! Cannot find name 'any'. + ~ +!!! '=>' expected. assign(context: any, value: any): any; ~ !!! ',' expected. diff --git a/tests/baselines/reference/parserX_ArrowFunction1.errors.txt b/tests/baselines/reference/parserX_ArrowFunction1.errors.txt index 68e0e0b6eb6..2443366b415 100644 --- a/tests/baselines/reference/parserX_ArrowFunction1.errors.txt +++ b/tests/baselines/reference/parserX_ArrowFunction1.errors.txt @@ -1,12 +1,6 @@ -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction1.ts (4 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction1.ts (1 errors) ==== var v = (a: ) => { - ~ -!!! ')' expected. ~ -!!! Variable declaration expected. - ~~ -!!! ';' expected. - ~ -!!! Cannot find name 'a'. +!!! Type expected. }; \ No newline at end of file