From d5c663685402a623e36a60f069f3025dcec77378 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 12 Dec 2014 03:46:32 -0800 Subject: [PATCH] Parse function and variable declarations uniformly, whether they're at teh top level, or inside a method. This is necessary for incremental parsing correctness, as the incremental parser will attempt to reuse these types of nodes in both contexts, and we much ensure it creates the same trees you would get if you were parsing normally. --- src/compiler/parser.ts | 12 +++++++++ .../reference/anonymousModules.errors.txt | 25 ++---------------- ...functionsWithModifiersInBlocks1.errors.txt | 26 +++++++++++++++++++ .../reference/innerModExport1.errors.txt | 11 +------- .../reference/innerModExport2.errors.txt | 17 +++++------- ...rserModifierOnStatementInBlock1.errors.txt | 11 ++++---- ...rserModifierOnStatementInBlock3.errors.txt | 12 ++++----- ...rserModifierOnStatementInBlock4.errors.txt | 13 +++------- .../functionsWithModifiersInBlocks1.ts | 5 ++++ tests/cases/unittests/incrementalParser.ts | 5 ++-- 10 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt create mode 100644 tests/cases/compiler/functionsWithModifiersInBlocks1.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 37565a89843..291eeb8c4ba 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3965,6 +3965,18 @@ module ts { } function isStartOfStatement(inErrorRecovery: boolean): boolean { + // Functions and variable statements are allowed as a statement. But as per the grammar, + // they also allow modifiers. So we have to check for those statements that might be + // following modifiers.This ensures that things work properly when incrementally parsing + // as the parser will produce the same FunctionDeclaraiton or VariableStatement if it has + // the same text regardless of whether it is inside a block or not. + if (isModifier(token)) { + var result = lookAhead(parseVariableStatementOrFunctionDeclarationWithModifiers); + if (result) { + return true; + } + } + switch (token) { case SyntaxKind.SemicolonToken: // If we're in error recovery, then we don't want to treat ';' as an empty statement. diff --git a/tests/baselines/reference/anonymousModules.errors.txt b/tests/baselines/reference/anonymousModules.errors.txt index 43b3d544a8b..1d63cc41c50 100644 --- a/tests/baselines/reference/anonymousModules.errors.txt +++ b/tests/baselines/reference/anonymousModules.errors.txt @@ -1,29 +1,18 @@ tests/cases/compiler/anonymousModules.ts(1,8): error TS1005: ';' expected. -tests/cases/compiler/anonymousModules.ts(2,2): error TS1129: Statement expected. -tests/cases/compiler/anonymousModules.ts(2,2): error TS1148: Cannot compile external modules unless the '--module' flag is provided. tests/cases/compiler/anonymousModules.ts(4,9): error TS1005: ';' expected. -tests/cases/compiler/anonymousModules.ts(5,3): error TS1129: Statement expected. -tests/cases/compiler/anonymousModules.ts(6,2): error TS1128: Declaration or statement expected. tests/cases/compiler/anonymousModules.ts(10,9): error TS1005: ';' expected. -tests/cases/compiler/anonymousModules.ts(13,1): error TS1128: Declaration or statement expected. tests/cases/compiler/anonymousModules.ts(1,1): error TS2304: Cannot find name 'module'. tests/cases/compiler/anonymousModules.ts(4,2): error TS2304: Cannot find name 'module'. -tests/cases/compiler/anonymousModules.ts(5,14): error TS2395: Individual declarations in merged declaration bar must be all exported or all local. -tests/cases/compiler/anonymousModules.ts(8,6): error TS2395: Individual declarations in merged declaration bar must be all exported or all local. tests/cases/compiler/anonymousModules.ts(10,2): error TS2304: Cannot find name 'module'. -==== tests/cases/compiler/anonymousModules.ts (13 errors) ==== +==== tests/cases/compiler/anonymousModules.ts (6 errors) ==== module { ~ !!! error TS1005: ';' expected. ~~~~~~ !!! error TS2304: Cannot find name 'module'. export var foo = 1; - ~~~~~~ -!!! error TS1129: Statement expected. - ~~~~~~~~~~~~~~~~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. module { ~ @@ -31,17 +20,9 @@ tests/cases/compiler/anonymousModules.ts(10,2): error TS2304: Cannot find name ' ~~~~~~ !!! error TS2304: Cannot find name 'module'. export var bar = 1; - ~~~~~~ -!!! error TS1129: Statement expected. - ~~~ -!!! error TS2395: Individual declarations in merged declaration bar must be all exported or all local. } - ~ -!!! error TS1128: Declaration or statement expected. var bar = 2; - ~~~ -!!! error TS2395: Individual declarations in merged declaration bar must be all exported or all local. module { ~ @@ -50,6 +31,4 @@ tests/cases/compiler/anonymousModules.ts(10,2): error TS2304: Cannot find name ' !!! error TS2304: Cannot find name 'module'. var x = bar; } - } - ~ -!!! error TS1128: Declaration or statement expected. \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt b/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt new file mode 100644 index 00000000000..557c67e496a --- /dev/null +++ b/tests/baselines/reference/functionsWithModifiersInBlocks1.errors.txt @@ -0,0 +1,26 @@ +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(2,4): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(3,4): error TS1184: Modifiers cannot appear here. +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,12): error TS1029: 'export' modifier must precede 'declare' modifier. +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(2,21): error TS2393: Duplicate function implementation. +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(3,20): error TS2393: Duplicate function implementation. +tests/cases/compiler/functionsWithModifiersInBlocks1.ts(4,28): error TS2393: Duplicate function implementation. + + +==== tests/cases/compiler/functionsWithModifiersInBlocks1.ts (6 errors) ==== + { + declare function f() { } + ~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + ~ +!!! error TS2393: Duplicate function implementation. + export function f() { } + ~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + ~ +!!! error TS2393: Duplicate function implementation. + declare export function f() { } + ~~~~~~ +!!! error TS1029: 'export' modifier must precede 'declare' modifier. + ~ +!!! error TS2393: Duplicate function implementation. + } \ No newline at end of file diff --git a/tests/baselines/reference/innerModExport1.errors.txt b/tests/baselines/reference/innerModExport1.errors.txt index 11e9cdc01d1..9e5840f2ccd 100644 --- a/tests/baselines/reference/innerModExport1.errors.txt +++ b/tests/baselines/reference/innerModExport1.errors.txt @@ -1,11 +1,8 @@ tests/cases/compiler/innerModExport1.ts(5,12): error TS1005: ';' expected. -tests/cases/compiler/innerModExport1.ts(7,9): error TS1129: Statement expected. -tests/cases/compiler/innerModExport1.ts(14,5): error TS1148: Cannot compile external modules unless the '--module' flag is provided. -tests/cases/compiler/innerModExport1.ts(17,1): error TS1128: Declaration or statement expected. tests/cases/compiler/innerModExport1.ts(5,5): error TS2304: Cannot find name 'module'. -==== tests/cases/compiler/innerModExport1.ts (5 errors) ==== +==== tests/cases/compiler/innerModExport1.ts (2 errors) ==== module Outer { // inner mod 1 @@ -17,8 +14,6 @@ tests/cases/compiler/innerModExport1.ts(5,5): error TS2304: Cannot find name 'mo !!! error TS2304: Cannot find name 'module'. var non_export_var = 0; export var export_var = 1; - ~~~~~~ -!!! error TS1129: Statement expected. function NonExportFunc() { return 0; } @@ -26,12 +21,8 @@ tests/cases/compiler/innerModExport1.ts(5,5): error TS2304: Cannot find name 'mo } export var outer_var_export = 0; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. export function outerFuncExport() { return 0; } } - ~ -!!! error TS1128: Declaration or statement expected. Outer.ExportFunc(); \ No newline at end of file diff --git a/tests/baselines/reference/innerModExport2.errors.txt b/tests/baselines/reference/innerModExport2.errors.txt index 1adcc46d441..79ba22e58ab 100644 --- a/tests/baselines/reference/innerModExport2.errors.txt +++ b/tests/baselines/reference/innerModExport2.errors.txt @@ -1,12 +1,11 @@ tests/cases/compiler/innerModExport2.ts(5,12): error TS1005: ';' expected. -tests/cases/compiler/innerModExport2.ts(7,9): error TS1129: Statement expected. -tests/cases/compiler/innerModExport2.ts(15,5): error TS1148: Cannot compile external modules unless the '--module' flag is provided. -tests/cases/compiler/innerModExport2.ts(18,1): error TS1128: Declaration or statement expected. tests/cases/compiler/innerModExport2.ts(5,5): error TS2304: Cannot find name 'module'. +tests/cases/compiler/innerModExport2.ts(7,20): error TS2395: Individual declarations in merged declaration export_var must be all exported or all local. +tests/cases/compiler/innerModExport2.ts(13,9): error TS2395: Individual declarations in merged declaration export_var must be all exported or all local. tests/cases/compiler/innerModExport2.ts(20,7): error TS2339: Property 'NonExportFunc' does not exist on type 'typeof Outer'. -==== tests/cases/compiler/innerModExport2.ts (6 errors) ==== +==== tests/cases/compiler/innerModExport2.ts (5 errors) ==== module Outer { // inner mod 1 @@ -18,23 +17,21 @@ tests/cases/compiler/innerModExport2.ts(20,7): error TS2339: Property 'NonExport !!! error TS2304: Cannot find name 'module'. var non_export_var = 0; export var export_var = 1; - ~~~~~~ -!!! error TS1129: Statement expected. + ~~~~~~~~~~ +!!! error TS2395: Individual declarations in merged declaration export_var must be all exported or all local. function NonExportFunc() { return 0; } export function ExportFunc() { return 0; } } var export_var: number; + ~~~~~~~~~~ +!!! error TS2395: Individual declarations in merged declaration export_var must be all exported or all local. export var outer_var_export = 0; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. export function outerFuncExport() { return 0; } } - ~ -!!! error TS1128: Declaration or statement expected. Outer.NonExportFunc(); ~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/parserModifierOnStatementInBlock1.errors.txt b/tests/baselines/reference/parserModifierOnStatementInBlock1.errors.txt index c24bc0997c6..5fa104a0e83 100644 --- a/tests/baselines/reference/parserModifierOnStatementInBlock1.errors.txt +++ b/tests/baselines/reference/parserModifierOnStatementInBlock1.errors.txt @@ -1,16 +1,15 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts(1,1): error TS1148: Cannot compile external modules unless the '--module' flag is provided. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts(2,4): error TS1129: Statement expected. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts(3,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts(2,4): error TS1184: Modifiers cannot appear here. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts (3 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock1.ts (2 errors) ==== export function foo() { ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. export var x = this; + ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~ -!!! error TS1129: Statement expected. +!!! error TS1184: Modifiers cannot appear here. } ~ -!!! error TS1128: Declaration or statement expected. +!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. \ No newline at end of file diff --git a/tests/baselines/reference/parserModifierOnStatementInBlock3.errors.txt b/tests/baselines/reference/parserModifierOnStatementInBlock3.errors.txt index ebb793783a2..5bc5a49670e 100644 --- a/tests/baselines/reference/parserModifierOnStatementInBlock3.errors.txt +++ b/tests/baselines/reference/parserModifierOnStatementInBlock3.errors.txt @@ -1,17 +1,17 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts(1,1): error TS1148: Cannot compile external modules unless the '--module' flag is provided. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts(2,4): error TS1129: Statement expected. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts(4,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts(2,4): error TS1184: Modifiers cannot appear here. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts (3 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock3.ts (2 errors) ==== export function foo() { ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. export function bar() { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~ -!!! error TS1129: Statement expected. +!!! error TS1184: Modifiers cannot appear here. } + ~~~~ } ~ -!!! error TS1128: Declaration or statement expected. +!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. \ No newline at end of file diff --git a/tests/baselines/reference/parserModifierOnStatementInBlock4.errors.txt b/tests/baselines/reference/parserModifierOnStatementInBlock4.errors.txt index b84f88c0b9a..4fc38af7d5d 100644 --- a/tests/baselines/reference/parserModifierOnStatementInBlock4.errors.txt +++ b/tests/baselines/reference/parserModifierOnStatementInBlock4.errors.txt @@ -1,18 +1,11 @@ -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts(2,4): error TS1129: Statement expected. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts(2,4): error TS1148: Cannot compile external modules unless the '--module' flag is provided. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts(4,1): error TS1128: Declaration or statement expected. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts(2,4): error TS1184: Modifiers cannot appear here. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts (3 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserModifierOnStatementInBlock4.ts (1 errors) ==== { export function bar() { ~~~~~~ -!!! error TS1129: Statement expected. - ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. } - ~~~~ -!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided. } - ~ -!!! error TS1128: Declaration or statement expected. \ No newline at end of file diff --git a/tests/cases/compiler/functionsWithModifiersInBlocks1.ts b/tests/cases/compiler/functionsWithModifiersInBlocks1.ts new file mode 100644 index 00000000000..2a03d962ffb --- /dev/null +++ b/tests/cases/compiler/functionsWithModifiersInBlocks1.ts @@ -0,0 +1,5 @@ +{ + declare function f() { } + export function f() { } + declare export function f() { } +} \ No newline at end of file diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index 282f126344b..1628325371f 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -183,7 +183,6 @@ module ts { describe('Incremental',() => { it('Inserting into method',() => { - debugger; var source = "class C {\r\n" + " public foo1() { }\r\n" + " public foo2() {\r\n" + @@ -745,12 +744,13 @@ module m3 { }\ }); it('Surrounding function declarations with block',() => { + debugger; var source = "declare function F1() { } export function F2() { } declare export function F3() { }" var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, 0, "{"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); }); it('Removing block around function declarations',() => { @@ -772,7 +772,6 @@ module m3 { }\ }); it('Moving methods from object literal to class',() => { - debugger; var source = "var v = { public A() { } public B() { } public C() { } }" var oldText = ScriptSnapshot.fromString(source);