Skip to content

Commit 40f6ed0

Browse files
Merge pull request #262 from Microsoft/trylessCatchesFinallyParseNicely
Improved errors for 'catch'/'finally' blocks missing 'try' statements
2 parents 21fb3bc + add65f1 commit 40f6ed0

File tree

5 files changed

+66
-11
lines changed

5 files changed

+66
-11
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,4 +1271,4 @@
12711271
"category": "Error",
12721272
"code": -9999999
12731273
}
1274-
}
1274+
}

src/compiler/parser.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,20 +2665,28 @@ module ts {
26652665
case SyntaxKind.ThrowKeyword:
26662666
case SyntaxKind.TryKeyword:
26672667
case SyntaxKind.DebuggerKeyword:
2668+
// 'catch' and 'finally' do not actually indicate that the code is part of a statement,
2669+
// however, we say they are here so that we may gracefully parse them and error later.
2670+
case SyntaxKind.CatchKeyword:
2671+
case SyntaxKind.FinallyKeyword:
26682672
return true;
26692673
case SyntaxKind.InterfaceKeyword:
26702674
case SyntaxKind.ClassKeyword:
26712675
case SyntaxKind.ModuleKeyword:
26722676
case SyntaxKind.EnumKeyword:
26732677
// When followed by an identifier, these do not start a statement but might
26742678
// instead be following declarations
2675-
if (isDeclaration()) return false;
2679+
if (isDeclaration()) {
2680+
return false;
2681+
}
26762682
case SyntaxKind.PublicKeyword:
26772683
case SyntaxKind.PrivateKeyword:
26782684
case SyntaxKind.StaticKeyword:
26792685
// When followed by an identifier or keyword, these do not start a statement but
26802686
// might instead be following type members
2681-
if (lookAhead(() => nextToken() >= SyntaxKind.Identifier)) return false;
2687+
if (lookAhead(() => nextToken() >= SyntaxKind.Identifier)) {
2688+
return false;
2689+
}
26822690
default:
26832691
return isExpression();
26842692
}
@@ -2715,6 +2723,9 @@ module ts {
27152723
case SyntaxKind.ThrowKeyword:
27162724
return parseThrowStatement();
27172725
case SyntaxKind.TryKeyword:
2726+
// Include the next two for error recovery.
2727+
case SyntaxKind.CatchKeyword:
2728+
case SyntaxKind.FinallyKeyword:
27182729
return parseTryStatement();
27192730
case SyntaxKind.DebuggerKeyword:
27202731
return parseDebuggerStatement();
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (4 errors) ====
1+
==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (6 errors) ====
22
function fn() {
33
try {
44
} catch { // syntax error, missing '(x)'
@@ -8,11 +8,34 @@
88

99
catch(x) { } // error missing try
1010
~~~~~
11-
!!! Statement expected.
12-
~
13-
!!! '=>' expected.
11+
!!! 'try' expected.
1412

15-
finally{ } // error missing try
13+
finally{ } // potential error; can be absorbed by the 'catch'
14+
}
15+
16+
function fn2() {
17+
finally { } // error missing try
18+
~~~~~~~
19+
!!! 'try' expected.
20+
catch (x) { } // error missing try
21+
~~~~~
22+
!!! 'try' expected.
23+
24+
// no error
25+
try {
26+
}
27+
finally {
28+
}
29+
30+
// error missing try
31+
finally {
1632
~~~~~~~
17-
!!! Statement expected.
33+
!!! 'try' expected.
34+
}
35+
36+
// error missing try
37+
catch (x) {
38+
~~~~~
39+
!!! 'try' expected.
40+
}
1841
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
==== tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken1.ts (2 errors) ====
1+
==== tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken1.ts (3 errors) ====
22
a / finally
33
~~~~~~~
44
!!! Expression expected.
5+
6+
!!! '{' expected.
57
~
68
!!! Cannot find name 'a'.

tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,24 @@ function fn() {
55

66
catch(x) { } // error missing try
77

8-
finally{ } // error missing try
8+
finally{ } // potential error; can be absorbed by the 'catch'
9+
}
10+
11+
function fn2() {
12+
finally { } // error missing try
13+
catch (x) { } // error missing try
14+
15+
// no error
16+
try {
17+
}
18+
finally {
19+
}
20+
21+
// error missing try
22+
finally {
23+
}
24+
25+
// error missing try
26+
catch (x) {
27+
}
928
}

0 commit comments

Comments
 (0)