mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Better error recovery when errant semicolon found in a class.
This commit is contained in:
parent
9ecf01b57a
commit
cece68098a
@ -619,14 +619,14 @@ module ts {
|
||||
}
|
||||
|
||||
// True if positioned at the start of a list element
|
||||
function isListElement(kind: ParsingContext): boolean {
|
||||
function isListElement(kind: ParsingContext, inErrorRecovery: boolean): boolean {
|
||||
switch (kind) {
|
||||
case ParsingContext.SourceElements:
|
||||
case ParsingContext.ModuleElements:
|
||||
return isSourceElement();
|
||||
return isSourceElement(inErrorRecovery);
|
||||
case ParsingContext.BlockStatements:
|
||||
case ParsingContext.SwitchClauseStatements:
|
||||
return isStatement();
|
||||
return isStatement(inErrorRecovery);
|
||||
case ParsingContext.SwitchClauses:
|
||||
return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
|
||||
case ParsingContext.TypeMembers:
|
||||
@ -650,6 +650,8 @@ module ts {
|
||||
case ParsingContext.TypeArguments:
|
||||
return isType();
|
||||
}
|
||||
|
||||
Debug.fail("Non-exhaustive case in 'isListElement'.");
|
||||
}
|
||||
|
||||
// True if positioned at a list terminator
|
||||
@ -717,10 +719,12 @@ module ts {
|
||||
}
|
||||
|
||||
// True if positioned at element or terminator of the current list or any enclosing list
|
||||
function isInParsingContext(): boolean {
|
||||
function isInSomeParsingContext(): boolean {
|
||||
for (var kind = 0; kind < ParsingContext.Count; kind++) {
|
||||
if (parsingContext & (1 << kind)) {
|
||||
if (isListElement(kind) || isListTerminator(kind)) return true;
|
||||
if (isListElement(kind, /* inErrorRecovery */ true) || isListTerminator(kind)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,12 +738,12 @@ module ts {
|
||||
var result = <NodeArray<T>>[];
|
||||
result.pos = getNodePos();
|
||||
while (!isListTerminator(kind)) {
|
||||
if (isListElement(kind)) {
|
||||
if (isListElement(kind, /* inErrorRecovery */ false)) {
|
||||
result.push(parseElement());
|
||||
}
|
||||
else {
|
||||
error(parsingContextErrors(kind));
|
||||
if (isInParsingContext()) {
|
||||
if (isInSomeParsingContext()) {
|
||||
break;
|
||||
}
|
||||
nextToken();
|
||||
@ -761,7 +765,7 @@ module ts {
|
||||
var errorCountBeforeParsingList = file.syntacticErrors.length;
|
||||
var commaStart = -1; // Meaning the previous token was not a comma
|
||||
while (true) {
|
||||
if (isListElement(kind)) {
|
||||
if (isListElement(kind, /* inErrorRecovery */ false)) {
|
||||
result.push(parseElement());
|
||||
commaStart = scanner.getTokenPos();
|
||||
if (parseOptional(SyntaxKind.CommaToken)) {
|
||||
@ -791,7 +795,7 @@ module ts {
|
||||
}
|
||||
else {
|
||||
error(parsingContextErrors(kind));
|
||||
if (token !== SyntaxKind.CommaToken && isInParsingContext()) {
|
||||
if (token !== SyntaxKind.CommaToken && isInSomeParsingContext()) {
|
||||
break;
|
||||
}
|
||||
nextToken();
|
||||
@ -2066,12 +2070,19 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function isStatement(): boolean {
|
||||
function isStatement(inErrorRecovery: boolean): boolean {
|
||||
switch (token) {
|
||||
case SyntaxKind.SemicolonToken:
|
||||
// If we're in error recovery, then we don't want to treat ';' as an empty statement.
|
||||
// The problem is that ';' can show up in far too many contexts, and if we see one
|
||||
// and assume it's a statement, then we may bail out innapropriately from whatever
|
||||
// we're parsing. For example, if we have a semicolon in the middle of a class, then
|
||||
// we really don't want to assume the class is over and we're on a statement in the
|
||||
// outer module. We just want to consume and move on.
|
||||
return !inErrorRecovery;
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
case SyntaxKind.SemicolonToken:
|
||||
case SyntaxKind.IfKeyword:
|
||||
case SyntaxKind.DoKeyword:
|
||||
case SyntaxKind.WhileKeyword:
|
||||
@ -2103,8 +2114,8 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isStatementOrFunction(): boolean {
|
||||
return token === SyntaxKind.FunctionKeyword || isStatement();
|
||||
function isStatementOrFunction(inErrorRecovery: boolean): boolean {
|
||||
return token === SyntaxKind.FunctionKeyword || isStatement(inErrorRecovery);
|
||||
}
|
||||
|
||||
function parseStatement(): Statement {
|
||||
@ -2813,8 +2824,8 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function isSourceElement(): boolean {
|
||||
return isDeclaration() || isStatement();
|
||||
function isSourceElement(inErrorRecovery: boolean): boolean {
|
||||
return isDeclaration() || isStatement(inErrorRecovery);
|
||||
}
|
||||
|
||||
function parseSourceElement() {
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
==== tests/cases/compiler/ambientGetters.ts (3 errors) ====
|
||||
==== tests/cases/compiler/ambientGetters.ts (2 errors) ====
|
||||
|
||||
declare class A {
|
||||
get length() : number;
|
||||
~
|
||||
!!! '{' expected.
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
|
||||
declare class B {
|
||||
get length() { return 0; }
|
||||
|
||||
@ -1,45 +1,19 @@
|
||||
==== tests/cases/compiler/es6ClassTest3.ts (15 errors) ====
|
||||
==== tests/cases/compiler/es6ClassTest3.ts (2 errors) ====
|
||||
module M {
|
||||
class Visibility {
|
||||
public foo() { };
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
private bar() { };
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'bar'.
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
private x: number;
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'number'.
|
||||
public y: number;
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'number'.
|
||||
public z: number;
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'number'.
|
||||
|
||||
constructor() {
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~~~~~~~~~
|
||||
!!! Cannot find name 'constructor'.
|
||||
this.x = 1;
|
||||
~~~~
|
||||
!!! 'this' cannot be referenced in a module body.
|
||||
this.y = 2;
|
||||
~~~~
|
||||
!!! 'this' cannot be referenced in a module body.
|
||||
}
|
||||
}
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/compiler/exportDeclareClass1.ts (9 errors) ====
|
||||
==== tests/cases/compiler/exportDeclareClass1.ts (4 errors) ====
|
||||
export declare class eaC {
|
||||
static tF() { };
|
||||
~
|
||||
@ -6,21 +6,11 @@
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
static tsF(param:any) { };
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ',' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'tsF'.
|
||||
~~~~~
|
||||
!!! Cannot find name 'param'.
|
||||
~~~
|
||||
!!! Cannot find name 'any'.
|
||||
!!! A function implementation cannot be declared in an ambient context.
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
};
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
|
||||
export declare class eaC2 {
|
||||
static tF();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts (38 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts (34 errors) ====
|
||||
export class Game {
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
private position = new DisplayPosition([), 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0], NoMove, 0);
|
||||
@ -40,8 +40,7 @@
|
||||
!!! ';' expected.
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! Cannot compile external modules unless the '--module' flag is provided.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! Cannot find name 'DisplayPosition'.
|
||||
~
|
||||
@ -69,14 +68,9 @@
|
||||
~
|
||||
!!! Duplicate identifier '0'.
|
||||
private prevConfig: SeedCoords[][];
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! Expression expected.
|
||||
~
|
||||
!!! Expression expected.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~
|
||||
!!! Cannot find name 'SeedCoords'.
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
!!! Cannot compile external modules unless the '--module' flag is provided.
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserEqualsGreaterThanAfterFunction2.ts (4 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserEqualsGreaterThanAfterFunction2.ts (5 errors) ====
|
||||
function (a => b;
|
||||
~
|
||||
!!! Identifier expected.
|
||||
@ -6,5 +6,7 @@
|
||||
!!! ',' expected.
|
||||
~
|
||||
!!! ',' expected.
|
||||
|
||||
!!! ')' expected.
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! Function implementation expected.
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserErrantSemicolonInClass1.ts (56 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserErrantSemicolonInClass1.ts (5 errors) ====
|
||||
class a {
|
||||
//constructor ();
|
||||
constructor (n: number);
|
||||
@ -12,137 +12,35 @@
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
|
||||
public pv;
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~
|
||||
!!! Cannot find name 'pv'.
|
||||
public get d() {
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'get'.
|
||||
~
|
||||
!!! Cannot find name 'd'.
|
||||
!!! Accessors are only available when targeting ECMAScript 5 and higher.
|
||||
return 30;
|
||||
~~~~~~~~~~
|
||||
!!! 'return' statement has no containing function.
|
||||
}
|
||||
public set d() {
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'set'.
|
||||
~
|
||||
!!! Cannot find name 'd'.
|
||||
!!! Accessors are only available when targeting ECMAScript 5 and higher.
|
||||
}
|
||||
|
||||
public static get p2() {
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~
|
||||
!!! ';' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'get'.
|
||||
~~
|
||||
!!! Cannot find name 'p2'.
|
||||
!!! Accessors are only available when targeting ECMAScript 5 and higher.
|
||||
return { x: 30, y: 40 };
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! 'return' statement has no containing function.
|
||||
}
|
||||
|
||||
private static d2() {
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~
|
||||
!!! Cannot find name 'd2'.
|
||||
}
|
||||
private static get p3() {
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~
|
||||
!!! ';' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'get'.
|
||||
~~
|
||||
!!! Cannot find name 'p3'.
|
||||
!!! Accessors are only available when targeting ECMAScript 5 and higher.
|
||||
return "string";
|
||||
~~~~~~~~~~~~~~~~
|
||||
!!! 'return' statement has no containing function.
|
||||
}
|
||||
private pv3;
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~~~
|
||||
!!! Cannot find name 'pv3'.
|
||||
|
||||
private foo(n: number): string;
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ',' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'foo'.
|
||||
~
|
||||
!!! Cannot find name 'n'.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'number'.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'string'.
|
||||
private foo(s: string): string;
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ',' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'foo'.
|
||||
~
|
||||
!!! Cannot find name 's'.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'string'.
|
||||
~~~~~~
|
||||
!!! Cannot find name 'string'.
|
||||
private foo(ns: any) {
|
||||
~~~~~~~
|
||||
!!! Declaration or statement expected.
|
||||
~
|
||||
!!! ',' expected.
|
||||
~
|
||||
!!! ';' expected.
|
||||
~~~
|
||||
!!! Cannot find name 'foo'.
|
||||
~~
|
||||
!!! Cannot find name 'ns'.
|
||||
~~~
|
||||
!!! Cannot find name 'any'.
|
||||
return ns.toString();
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! 'return' statement has no containing function.
|
||||
}
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts (10 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts (9 errors) ====
|
||||
class C {
|
||||
where(filter: Iterator<T, boolean>): Query<T> {
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
@ -22,8 +22,6 @@
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
}
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
@ -0,0 +1,8 @@
|
||||
==== tests/cases/compiler/parsingClassRecoversWhenHittingUnexpectedSemicolon.ts (1 errors) ====
|
||||
class C {
|
||||
public f() { };
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
private m;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
==== tests/cases/compiler/primitiveMembers.ts (6 errors) ====
|
||||
==== tests/cases/compiler/primitiveMembers.ts (4 errors) ====
|
||||
var x = 5;
|
||||
var r = /yo/;
|
||||
r.source;
|
||||
@ -29,13 +29,9 @@
|
||||
class baz { public bar(): void { }; }
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
class foo extends baz { public bar(){ return undefined}; }
|
||||
~
|
||||
!!! Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
~
|
||||
!!! Declaration or statement expected.
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
class C {
|
||||
public f() { };
|
||||
private m;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user