Skip to content

Commit 824edea

Browse files
Merge pull request microsoft#1368 from Microsoft/parseErrors
Remove all function expression allocations when speculatively parsing or looking ahead.
2 parents 580e23e + 405508c commit 824edea

14 files changed

Lines changed: 223 additions & 219 deletions

src/compiler/parser.ts

Lines changed: 133 additions & 117 deletions
Large diffs are not rendered by default.

src/compiler/scanner.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ module ts {
2929
scan(): SyntaxKind;
3030
setText(text: string): void;
3131
setTextPos(textPos: number): void;
32+
// Invokes the provided callback then unconditionally restores the scanner to the state it
33+
// was in immediately prior to invoking the callback. The result of invoking the callback
34+
// is returned from this function.
35+
lookAhead<T>(callback: () => T): T;
36+
37+
// Invokes the provided callback. If the callback returns something falsy, then it restores
38+
// the scanner to the state it was in immediately prior to invoking the callback. If the
39+
// callback returns something truthy, then the scanner state is not rolled back. The result
40+
// of invoking the callback is returned from this function.
3241
tryScan<T>(callback: () => T): T;
3342
}
3443

@@ -1174,15 +1183,18 @@ module ts {
11741183
return token = scanTemplateAndSetTokenValue();
11751184
}
11761185

1177-
function tryScan<T>(callback: () => T): T {
1186+
function speculationHelper<T>(callback: () => T, isLookahead: boolean): T {
11781187
var savePos = pos;
11791188
var saveStartPos = startPos;
11801189
var saveTokenPos = tokenPos;
11811190
var saveToken = token;
11821191
var saveTokenValue = tokenValue;
11831192
var savePrecedingLineBreak = precedingLineBreak;
11841193
var result = callback();
1185-
if (!result) {
1194+
1195+
// If our callback returned something 'falsy' or we're just looking ahead,
1196+
// then unconditionally restore us to where we were.
1197+
if (!result || isLookahead) {
11861198
pos = savePos;
11871199
startPos = saveStartPos;
11881200
tokenPos = saveTokenPos;
@@ -1193,6 +1205,14 @@ module ts {
11931205
return result;
11941206
}
11951207

1208+
function lookAhead<T>(callback: () => T): T {
1209+
return speculationHelper(callback, /*isLookahead:*/ true);
1210+
}
1211+
1212+
function tryScan<T>(callback: () => T): T {
1213+
return speculationHelper(callback, /*isLookahead:*/ false);
1214+
}
1215+
11961216
function setText(newText: string) {
11971217
text = newText || "";
11981218
len = text.length;
@@ -1228,6 +1248,7 @@ module ts {
12281248
setText,
12291249
setTextPos,
12301250
tryScan,
1251+
lookAhead,
12311252
};
12321253
}
12331254
}
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,12): error TS1005: ',' expected.
2-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,14): error TS1005: ';' expected.
3-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,10): error TS2304: Cannot find name 'a'.
1+
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,14): error TS1110: Type expected.
2+
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,13): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
43

54

6-
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts (3 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts (2 errors) ====
76
var v = (a): => {
8-
~
9-
!!! error TS1005: ',' expected.
107
~~
11-
!!! error TS1005: ';' expected.
12-
~
13-
!!! error TS2304: Cannot find name 'a'.
8+
!!! error TS1110: Type expected.
9+
10+
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
1411

1512
};
Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
11
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,9): error TS1127: Invalid character.
22
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,1): error TS2304: Cannot find name 'Foo'.
3-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,5): error TS2304: Cannot find name 'A'.
4-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,7): error TS2304: Cannot find name 'B'.
5-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,11): error TS2304: Cannot find name 'C'.
63

74

8-
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts (5 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts (2 errors) ====
96
Foo<A,B,\ C>(4, 5, 6);
107

118
!!! error TS1127: Invalid character.
129
~~~
13-
!!! error TS2304: Cannot find name 'Foo'.
14-
~
15-
!!! error TS2304: Cannot find name 'A'.
16-
~
17-
!!! error TS2304: Cannot find name 'B'.
18-
~
19-
!!! error TS2304: Cannot find name 'C'.
10+
!!! error TS2304: Cannot find name 'Foo'.
Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
tests/cases/compiler/genericCallWithoutArgs.ts(4,17): error TS1109: Expression expected.
2-
tests/cases/compiler/genericCallWithoutArgs.ts(4,18): error TS1003: Identifier expected.
3-
tests/cases/compiler/genericCallWithoutArgs.ts(4,3): error TS2304: Cannot find name 'number'.
4-
tests/cases/compiler/genericCallWithoutArgs.ts(4,10): error TS2304: Cannot find name 'string'.
1+
tests/cases/compiler/genericCallWithoutArgs.ts(4,17): error TS1005: '(' expected.
2+
tests/cases/compiler/genericCallWithoutArgs.ts(4,18): error TS1005: ')' expected.
53

64

7-
==== tests/cases/compiler/genericCallWithoutArgs.ts (4 errors) ====
5+
==== tests/cases/compiler/genericCallWithoutArgs.ts (2 errors) ====
86
function f<X, Y>(x: X, y: Y) {
97
}
108

119
f<number,string>.
1210
~
13-
!!! error TS1109: Expression expected.
11+
!!! error TS1005: '(' expected.
1412

15-
!!! error TS1003: Identifier expected.
16-
~~~~~~
17-
!!! error TS2304: Cannot find name 'number'.
18-
~~~~~~
19-
!!! error TS2304: Cannot find name 'string'.
13+
!!! error TS1005: ')' expected.
Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
tests/cases/compiler/genericCallsWithoutParens.ts(2,18): error TS1109: Expression expected.
2-
tests/cases/compiler/genericCallsWithoutParens.ts(7,22): error TS1109: Expression expected.
3-
tests/cases/compiler/genericCallsWithoutParens.ts(2,11): error TS2304: Cannot find name 'number'.
4-
tests/cases/compiler/genericCallsWithoutParens.ts(7,15): error TS2304: Cannot find name 'number'.
1+
tests/cases/compiler/genericCallsWithoutParens.ts(2,18): error TS1005: '(' expected.
2+
tests/cases/compiler/genericCallsWithoutParens.ts(7,22): error TS1005: '(' expected.
53

64

7-
==== tests/cases/compiler/genericCallsWithoutParens.ts (4 errors) ====
5+
==== tests/cases/compiler/genericCallsWithoutParens.ts (2 errors) ====
86
function f<T>() { }
97
var r = f<number>; // parse error
108
~
11-
!!! error TS1109: Expression expected.
12-
~~~~~~
13-
!!! error TS2304: Cannot find name 'number'.
9+
!!! error TS1005: '(' expected.
1410

1511
class C<T> {
1612
foo: T;
1713
}
1814
var c = new C<number>; // parse error
1915
~
20-
!!! error TS1109: Expression expected.
21-
~~~~~~
22-
!!! error TS2304: Cannot find name 'number'.
16+
!!! error TS1005: '(' expected.
2317

2418

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(10,1): error TS1109: Expression expected.
2-
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(9,16): error TS2304: Cannot find name 'number'.
1+
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(10,1): error TS1005: '(' expected.
32

43

5-
==== tests/cases/compiler/genericConstructExpressionWithoutArgs.ts (2 errors) ====
4+
==== tests/cases/compiler/genericConstructExpressionWithoutArgs.ts (1 errors) ====
65
class B { }
76
var b = new B; // no error
87

@@ -12,8 +11,6 @@ tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(9,16): error TS230
1211

1312
var c = new C // C<any>
1413
var c2 = new C<number> // error, type params are actually part of the arg list so you need both
15-
~~~~~~
16-
!!! error TS2304: Cannot find name 'number'.
1714

1815

19-
!!! error TS1109: Expression expected.
16+
!!! error TS1005: '(' expected.
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,26): error TS1109: Expression expected.
2-
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,19): error TS2304: Cannot find name 'number'.
1+
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,26): error TS1005: '(' expected.
32

43

5-
==== tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts (2 errors) ====
4+
==== tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts (1 errors) ====
65
class SS<T>{
76

87
}
98

109
var x1 = new SS<number>(); // OK
1110
var x2 = new SS < number>; // Correctly give error
1211
~
13-
!!! error TS1109: Expression expected.
14-
~~~~~~
15-
!!! error TS2304: Cannot find name 'number'.
12+
!!! error TS1005: '(' expected.
1613
var x3 = new SS(); // OK
1714
var x4 = new SS; // Should be allowed, but currently give error ('supplied parameters do not match any signature of the call target')
1815

tests/baselines/reference/newOperatorErrorCases.errors.txt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(27,16): error TS1005: ',' expected.
2-
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,23): error TS1109: Expression expected.
3-
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,16): error TS2304: Cannot find name 'string'.
2+
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,23): error TS1005: '(' expected.
43
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(37,9): error TS2350: Only a void function can be called with the 'new' keyword.
54

65

7-
==== tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts (4 errors) ====
6+
==== tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts (3 errors) ====
87

98
class C0 {
109

@@ -40,9 +39,7 @@ tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(37,9):
4039
var c1: T<{}>;
4140
var c2 = new T<string>; // Parse error
4241
~
43-
!!! error TS1109: Expression expected.
44-
~~~~~~
45-
!!! error TS2304: Cannot find name 'string'.
42+
!!! error TS1005: '(' expected.
4643

4744

4845
// Construct expression of non-void returning function
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,12): error TS1109: Expression expected.
1+
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,12): error TS1005: '(' expected.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,1): error TS2346: Supplied parameters do not match any signature of call target.
23
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,10): error TS2304: Cannot find name 'A'.
34

45

5-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts (2 errors) ====
6+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts (3 errors) ====
67
new Date<A>
78

8-
!!! error TS1109: Expression expected.
9+
!!! error TS1005: '(' expected.
10+
~~~~~~~~~~~
11+
!!! error TS2346: Supplied parameters do not match any signature of call target.
912
~
1013
!!! error TS2304: Cannot find name 'A'.

0 commit comments

Comments
 (0)