@@ -346,6 +346,8 @@ export class LuaTranspiler {
346346 return this . transpileFunctionExpression ( < ts . FunctionExpression > node ) ;
347347 case ts . SyntaxKind . NewExpression :
348348 return this . transpileNewExpression ( < ts . NewExpression > node ) ;
349+ case ts . SyntaxKind . SuperKeyword :
350+ return "self.__base.constructor" ;
349351 case ts . SyntaxKind . TypeAssertionExpression :
350352 // Simply ignore the type assertion
351353 return this . transpileExpression ( ( < ts . TypeAssertion > node ) . expression ) ;
@@ -445,7 +447,7 @@ export class LuaTranspiler {
445447 const name = this . transpileExpression ( node . expression ) ;
446448 const params = this . transpileArguments ( node . arguments ) ;
447449
448- return `${ name } (${ params } )` ;
450+ return `${ name } .new (${ params } )` ;
449451 }
450452
451453 transpileCallExpression ( node : ts . CallExpression ) : string {
@@ -467,6 +469,13 @@ export class LuaTranspiler {
467469 return `${ callPath } (${ params } )` ;
468470 }
469471
472+ // Handle super calls properly
473+ if ( node . expression . kind == ts . SyntaxKind . SuperKeyword ) {
474+ let callPath = this . transpileExpression ( node . expression ) ;
475+ const params = this . transpileArguments ( node . arguments , < ts . Expression > ts . createNode ( ts . SyntaxKind . ThisKeyword ) ) ;
476+ return `${ callPath } (${ params } )` ;
477+ }
478+
470479 let callPath = this . transpileExpression ( node . expression ) ;
471480 const params = this . transpileArguments ( node . arguments ) ;
472481 return `${ callPath } (${ params } )` ;
@@ -642,51 +651,42 @@ export class LuaTranspiler {
642651
643652 // Transpile a class declaration
644653 transpileClass ( node : ts . ClassDeclaration ) : string {
645- // Write class declaration
646- const className = < string > node . name . escapedText ;
647- let result = this . indent + `${ className } = ${ className } or class({})\n` ;
648-
649- // Get all properties
650- const properties = tsEx . getChildrenOfType < ts . PropertyDeclaration > ( node , ts . isPropertyDeclaration ) ;
651-
652- let staticFields : ts . PropertyDeclaration [ ] = [ ] ;
653- let instanceFields : ts . PropertyDeclaration [ ] = [ ] ;
654+ // Figure out inheritance
655+ const isExtension = node . heritageClauses && node . heritageClauses . length > 0 ;
656+ let baseName = "" ;
654657
655- // Divide properties in static and instance fields
656- for ( const p of properties ) {
657- // Check if property is static
658- const isStatic = tsEx . getChildrenOfType ( p , child => child . kind == ts . SyntaxKind . StaticKeyword ) . length > 0 ;
658+ if ( isExtension )
659+ baseName = < string > ( < ts . Identifier > node . heritageClauses [ 0 ] . types [ 0 ] . expression ) . escapedText ;
659660
660- // Find value assignment
661- const assignments = tsEx . getChildrenOfType ( p , tsEx . isValueType ) ;
662-
663- // Ignore fields with no assigned value
664- if ( ! p . initializer )
665- continue ;
666-
667- if ( isStatic ) {
668- staticFields . push ( p ) ;
669- } else {
670- instanceFields . push ( p ) ;
671- }
672- }
661+ // Write class declaration
662+ const className = < string > node . name . escapedText ;
663+ let result = this . indent + `${ className } = ${ className } or {}\n` ;
664+ result += this . indent + `${ className } .__index = ${ className } \n` ;
665+ if ( isExtension ) result += this . indent + `${ className } .__base = ${ baseName } \n`
666+ result += this . indent + `function ${ className } .new(...)\n` ;
667+ result += this . indent + ` local instance = setmetatable({}, ${ className } )\n` ;
668+ result += this . indent + ` if ${ className } .constructor then ${ className } .constructor(instance, ...) end\n` ;
669+ result += this . indent + ` return instance\n` ;
670+ result += this . indent + `end\n` ;
671+
672+ // Get all properties with value
673+ const properties = node . members . filter ( ts . isPropertyDeclaration )
674+ . filter ( _ => _ . initializer ) ;
675+
676+ // Divide properties into static and non-static
677+ const isStatic = _ => _ . modifiers && _ . modifiers . some ( _ => _ . kind == ts . SyntaxKind . StaticKeyword ) ;
678+ const staticFields = properties . filter ( isStatic ) ;
679+ const instanceFields = properties . filter ( _ => ! isStatic ( _ ) ) ;
673680
674681 // Add static declarations
675- for ( const f of staticFields ) {
676- // Get identifier
677- const fieldIdentifier = tsEx . getFirstChildOfType < ts . Identifier > ( f , ts . isIdentifier ) ;
678- const fieldName = fieldIdentifier . escapedText ;
679-
680- // Get value at index 1 (index 0 is field name)
681- const valueNode = tsEx . getChildrenOfType < ts . Node > ( f , tsEx . isValueType ) [ 1 ] ;
682- let value = this . transpileExpression ( valueNode ) ;
683-
684- // Build lua assignment string
682+ for ( const field of staticFields ) {
683+ const fieldName = ( < ts . Identifier > field . name ) . escapedText ;
684+ let value = this . transpileExpression ( field . initializer ) ;
685685 result += this . indent + `${ className } .${ fieldName } = ${ value } \n` ;
686686 }
687687
688688 // Try to find constructor
689- const constructor = tsEx . getFirstChildOfType < ts . ConstructorDeclaration > ( node , ts . isConstructorDeclaration ) ;
689+ const constructor = node . members . filter ( ts . isConstructorDeclaration ) [ 0 ] ;
690690 if ( constructor ) {
691691 // Add constructor plus initialisation of instance fields
692692 result += this . transpileConstructor ( constructor , className , instanceFields ) ;
@@ -698,17 +698,19 @@ export class LuaTranspiler {
698698 }
699699 }
700700
701- // Find all methods
702- const methods = tsEx . getChildrenOfType < ts . MethodDeclaration > ( node , ts . isMethodDeclaration ) ;
703- methods . forEach ( method => {
701+ // Transpile methods
702+ node . members . filter ( ts . isMethodDeclaration ) . forEach ( method => {
704703 result += this . transpileMethodDeclaration ( method , `${ className } .` ) ;
705704 } ) ;
706705
707706 return result ;
708707 }
709708
710709 transpileConstructor ( node : ts . ConstructorDeclaration , className : string , instanceFields : ts . PropertyDeclaration [ ] ) : string {
711- let result = this . indent + `function ${ className } :constructor()\n` ;
710+ let parameters = [ "self" ] ;
711+ node . parameters . forEach ( param => parameters . push ( < string > ( < ts . Identifier > param . name ) . escapedText ) ) ;
712+
713+ let result = this . indent + `function ${ className } .constructor(${ parameters . join ( "," ) } )\n` ;
712714
713715 // Add in instance field declarations
714716 for ( const f of instanceFields ) {
@@ -764,7 +766,7 @@ export class LuaTranspiler {
764766
765767 let result = `function(${ paramNames . join ( "," ) } )\n` ;
766768 this . pushIndent ( ) ;
767- result += this . transpileNode ( node . body ) ;
769+ result += this . transpileBlock ( node . body ) ;
768770 this . popIndent ( ) ;
769771 return result + this . indent + "end " ;
770772 }
0 commit comments