Merge pull request #4921 from Microsoft/implementsAsIdentifier

disambiguate: 'implements' starts heritage clause vs 'implements' is …
This commit is contained in:
Vladimir Matveev
2015-09-22 09:13:37 -07:00
5 changed files with 71 additions and 2 deletions

View File

@@ -4809,7 +4809,7 @@ namespace ts {
node.decorators = decorators;
setModifiers(node, modifiers);
parseExpected(SyntaxKind.ClassKeyword);
node.name = parseOptionalIdentifier();
node.name = parseNameOfClassDeclarationOrExpression();
node.typeParameters = parseTypeParameters();
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ true);
@@ -4825,7 +4825,22 @@ namespace ts {
return finishNode(node);
}
function parseNameOfClassDeclarationOrExpression(): Identifier {
// implements is a future reserved word so
// 'class implements' might mean either
// - class expression with omitted name, 'implements' starts heritage clause
// - class with name 'implements'
// 'isImplementsClause' helps to disambiguate between these two cases
return isIdentifier() && !isImplementsClause()
? parseIdentifier()
: undefined;
}
function isImplementsClause() {
return token === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword)
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
// ClassTail[Yield,Await] : (Modified) See 14.5
// ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }

View File

@@ -0,0 +1,16 @@
//// [implementsInClassExpression.ts]
interface Foo {
doThing(): void;
}
let cls = class implements Foo {
doThing() { }
}
//// [implementsInClassExpression.js]
var cls = (function () {
function class_1() {
}
class_1.prototype.doThing = function () { };
return class_1;
})();

View File

@@ -0,0 +1,15 @@
=== tests/cases/compiler/implementsInClassExpression.ts ===
interface Foo {
>Foo : Symbol(Foo, Decl(implementsInClassExpression.ts, 0, 0))
doThing(): void;
>doThing : Symbol(doThing, Decl(implementsInClassExpression.ts, 0, 15))
}
let cls = class implements Foo {
>cls : Symbol(cls, Decl(implementsInClassExpression.ts, 4, 3))
>Foo : Symbol(Foo, Decl(implementsInClassExpression.ts, 0, 0))
doThing() { }
>doThing : Symbol((Anonymous class).doThing, Decl(implementsInClassExpression.ts, 4, 32))
}

View File

@@ -0,0 +1,16 @@
=== tests/cases/compiler/implementsInClassExpression.ts ===
interface Foo {
>Foo : Foo
doThing(): void;
>doThing : () => void
}
let cls = class implements Foo {
>cls : typeof (Anonymous class)
>class implements Foo { doThing() { }} : typeof (Anonymous class)
>Foo : Foo
doThing() { }
>doThing : () => void
}

View File

@@ -0,0 +1,7 @@
interface Foo {
doThing(): void;
}
let cls = class implements Foo {
doThing() { }
}