From 48903536269f1803d2fc184942266c972be37737 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 13 Oct 2018 13:56:41 +0300 Subject: [PATCH 1/3] -added support for class expressions --- src/TSHelper.ts | 2 +- src/Transpiler.ts | 23 +++++++++++++++-------- test/unit/class.spec.ts | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/TSHelper.ts b/src/TSHelper.ts index 210410d27..967ce9cd6 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -28,7 +28,7 @@ export class TSHelper { return statements.some(statement => statement.kind === kind); } - public static getExtendedType(node: ts.ClassDeclaration, checker: ts.TypeChecker): ts.Type | undefined { + public static getExtendedType(node: ts.ClassLikeDeclarationBase, checker: ts.TypeChecker): ts.Type | undefined { if (node && node.heritageClauses) { for (const clause of node.heritageClauses) { if (clause.token === ts.SyntaxKind.ExtendsKeyword) { diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 94070209e..52ae9af41 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -805,6 +805,11 @@ export abstract class LuaTranspiler { return this.transpileSpreadElement(node as ts.SpreadElement); case ts.SyntaxKind.NonNullExpression: return this.transpileExpression((node as ts.NonNullExpression).expression); + case ts.SyntaxKind.ClassExpression: + this.namespace.push(""); + const classDeclaration = this.transpileClass(node as ts.ClassExpression, "_"); + this.namespace.pop(); + return `(function() ${classDeclaration}; return _ end)()`; case ts.SyntaxKind.Block: this.pushIndent(); const ret = "do \n" + this.transpileBlock(node as ts.Block) + "end\n"; @@ -1596,13 +1601,16 @@ export abstract class LuaTranspiler { } // Transpile a class declaration - public transpileClass(node: ts.ClassDeclaration): string { - if (!node.name) { + public transpileClass(node: ts.ClassLikeDeclarationBase, nameOverride?: string): string { + let className: string; + if (node.name) { + className = this.transpileIdentifier(node.name); + } else if (nameOverride) { + className = nameOverride; + } else { throw TSTLErrors.MissingClassName(node); } - let className = this.transpileIdentifier(node.name); - const decorators = tsHelper.getCustomDecorators(this.checker.getTypeAtLocation(node), this.checker); // Find out if this class is extension of existing class @@ -1648,7 +1656,7 @@ export abstract class LuaTranspiler { } if (!isExtension && !isMetaExtension) { - result += this.transpileClassCreationMethods(node, instanceFields, extendsType); + result += this.transpileClassCreationMethods(node, className, instanceFields, extendsType); } else { for (const f of instanceFields) { // Get identifier @@ -1697,10 +1705,9 @@ export abstract class LuaTranspiler { return result; } - public transpileClassCreationMethods(node: ts.ClassDeclaration, instanceFields: ts.PropertyDeclaration[], + public transpileClassCreationMethods(node: ts.ClassLikeDeclarationBase, className: string, + instanceFields: ts.PropertyDeclaration[], extendsType: ts.Type): string { - const className = this.transpileIdentifier(node.name); - let noClassOr = false; if (extendsType) { const decorators = tsHelper.getCustomDecorators(extendsType, this.checker); diff --git a/test/unit/class.spec.ts b/test/unit/class.spec.ts index 6f0060555..a33af6d54 100644 --- a/test/unit/class.spec.ts +++ b/test/unit/class.spec.ts @@ -429,4 +429,27 @@ export class ClassTests { // Assert Expect(result).toBe(10); } + @Test("classExpression") + public classExpression(): void { + const lua = util.transpileString( + `class a { + public method() { + return "instance of a"; + } + } + b = class extends a { + public method() { + return "instance of b"; + } + } + let inst = new b(6); + return inst.method();` + ); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe("instance of b"); + } } From 3969134d88652601dffac9b3f0267456b2968864 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 13 Oct 2018 15:20:08 +0300 Subject: [PATCH 2/3] -minor refactor --- src/Transpiler.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Transpiler.ts b/src/Transpiler.ts index 52ae9af41..cd97404f6 100644 --- a/src/Transpiler.ts +++ b/src/Transpiler.ts @@ -1602,12 +1602,8 @@ export abstract class LuaTranspiler { // Transpile a class declaration public transpileClass(node: ts.ClassLikeDeclarationBase, nameOverride?: string): string { - let className: string; - if (node.name) { - className = this.transpileIdentifier(node.name); - } else if (nameOverride) { - className = nameOverride; - } else { + let className = node.name ? this.transpileIdentifier(node.name) : nameOverride; + if (!className) { throw TSTLErrors.MissingClassName(node); } From c31c11f0fc7fd9d8ed8448e14bee998220a145e3 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 13 Oct 2018 15:20:24 +0300 Subject: [PATCH 3/3] -test for base class method calling when using class expression --- test/unit/class.spec.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/unit/class.spec.ts b/test/unit/class.spec.ts index a33af6d54..484ab0349 100644 --- a/test/unit/class.spec.ts +++ b/test/unit/class.spec.ts @@ -452,4 +452,24 @@ export class ClassTests { // Assert Expect(result).toBe("instance of b"); } + @Test("classExpressionBaseClassMethod") + public classExpressionBaseClassMethod(): void { + const lua = util.transpileString( + `class a { + public method() { + return 42; + } + } + b = class extends a { + } + let inst = new b(); + return inst.method();` + ); + + // Execute + const result = util.executeLua(lua); + + // Assert + Expect(result).toBe(42); + } }