@@ -433,12 +433,14 @@ export class LuaTransformer {
433433 instanceFields ,
434434 statement
435435 ) ) ;
436- } else if ( instanceFields . length > 0 ) {
436+ } else if ( instanceFields . length > 0
437+ || statement . members . some ( m => tsHelper . isGetAccessorOverride ( m , statement , this . checker ) ) )
438+ {
437439 // Generate a constructor if none was defined in a class with instance fields that need initialization
438440 // className.prototype.____constructor = function(self, ...)
439441 // baseClassName.prototype.____constructor(self, ...)
440442 // ...
441- const constructorBody = this . transformClassInstanceFields ( instanceFields ) ;
443+ const constructorBody = this . transformClassInstanceFields ( statement , instanceFields ) ;
442444 const superCall = tstl . createExpressionStatement (
443445 tstl . createCallExpression (
444446 tstl . createTableIndexExpression (
@@ -534,13 +536,61 @@ export class LuaTransformer {
534536 const assignClassPrototype = tstl . createAssignmentStatement ( createClassPrototype ( ) , classPrototypeTable ) ;
535537 result . push ( assignClassPrototype ) ;
536538
537- // className.prototype.__index = className.prototype
538539 const classPrototypeIndex = tstl . createTableIndexExpression (
539540 createClassPrototype ( ) ,
540541 tstl . createStringLiteral ( "__index" )
541542 ) ;
542- const assignClassPrototypeIndex = tstl . createAssignmentStatement ( classPrototypeIndex , createClassPrototype ( ) ) ;
543- result . push ( assignClassPrototypeIndex ) ;
543+ if ( statement . members . some ( ts . isGetAccessor ) ) {
544+ // className.prototype.____getters = {}
545+ const classPrototypeGetters = tstl . createTableIndexExpression (
546+ createClassPrototype ( ) ,
547+ tstl . createStringLiteral ( "____getters" )
548+ ) ;
549+ const assignClassPrototypeGetters = tstl . createAssignmentStatement (
550+ classPrototypeGetters ,
551+ tstl . createTableExpression ( )
552+ ) ;
553+ result . push ( assignClassPrototypeGetters ) ;
554+
555+ // className.prototype.__index = __TS_Index(className.prototype)
556+ const assignClassPrototypeIndex = tstl . createAssignmentStatement (
557+ classPrototypeIndex ,
558+ this . transformLuaLibFunction ( LuaLibFeature . Index , undefined , createClassPrototype ( ) )
559+ ) ;
560+ result . push ( assignClassPrototypeIndex ) ;
561+
562+ } else {
563+ // className.prototype.__index = className.prototype
564+ const assignClassPrototypeIndex = tstl . createAssignmentStatement (
565+ classPrototypeIndex ,
566+ createClassPrototype ( )
567+ ) ;
568+ result . push ( assignClassPrototypeIndex ) ;
569+ }
570+
571+ if ( tsHelper . hasSetAccessorInClassOrAncestor ( statement , this . checker ) ) {
572+ // className.prototype.____setters = {}
573+ const classPrototypeSetters = tstl . createTableIndexExpression (
574+ createClassPrototype ( ) ,
575+ tstl . createStringLiteral ( "____setters" )
576+ ) ;
577+ const assignClassPrototypeSetters = tstl . createAssignmentStatement (
578+ classPrototypeSetters ,
579+ tstl . createTableExpression ( )
580+ ) ;
581+ result . push ( assignClassPrototypeSetters ) ;
582+
583+ // className.prototype.__newindex = __TS_NewIndex(className.prototype)
584+ const classPrototypeNewIndex = tstl . createTableIndexExpression (
585+ createClassPrototype ( ) ,
586+ tstl . createStringLiteral ( "__newindex" )
587+ ) ;
588+ const assignClassPrototypeIndex = tstl . createAssignmentStatement (
589+ classPrototypeNewIndex ,
590+ this . transformLuaLibFunction ( LuaLibFeature . NewIndex , undefined , createClassPrototype ( ) )
591+ ) ;
592+ result . push ( assignClassPrototypeIndex ) ;
593+ }
544594
545595 // className.prototype.constructor = className
546596 const classPrototypeConstructor = tstl . createTableIndexExpression (
@@ -634,7 +684,11 @@ export class LuaTransformer {
634684 return result ;
635685 }
636686
637- public transformClassInstanceFields ( instanceFields : ts . PropertyDeclaration [ ] ) : tstl . Statement [ ] {
687+ public transformClassInstanceFields (
688+ classDeclarataion : ts . ClassLikeDeclaration ,
689+ instanceFields : ts . PropertyDeclaration [ ]
690+ ) : tstl . Statement [ ]
691+ {
638692 const statements : tstl . Statement [ ] = [ ] ;
639693
640694 for ( const f of instanceFields ) {
@@ -652,6 +706,19 @@ export class LuaTransformer {
652706 statements . push ( assignClassField ) ;
653707 }
654708
709+ const getOverrides = classDeclarataion . members . filter (
710+ m => tsHelper . isGetAccessorOverride ( m , classDeclarataion , this . checker )
711+ ) ;
712+ for ( const getter of getOverrides ) {
713+ const resetGetter = tstl . createExpressionStatement (
714+ tstl . createCallExpression (
715+ tstl . createIdentifier ( "rawset" ) ,
716+ [ this . createSelfIdentifier ( ) , this . transformPropertyName ( getter . name ) , tstl . createNilLiteral ( ) ]
717+ )
718+ ) ;
719+ statements . push ( resetGetter ) ;
720+ }
721+
655722 return statements ;
656723 }
657724
@@ -677,7 +744,7 @@ export class LuaTransformer {
677744 return undefined ;
678745 }
679746
680- const bodyStatements : tstl . Statement [ ] = this . transformClassInstanceFields ( instanceFields ) ;
747+ const bodyStatements : tstl . Statement [ ] = this . transformClassInstanceFields ( classDeclaration , instanceFields ) ;
681748
682749 // Check for field declarations in constructor
683750 const constructorFieldsDeclarations = statement . parameters . filter ( p => p . modifiers !== undefined ) ;
@@ -745,15 +812,20 @@ export class LuaTransformer {
745812 [ this . createSelfIdentifier ( ) ]
746813 ) ;
747814
748- return tstl . createAssignmentStatement (
749- tstl . createTableIndexExpression (
750- tstl . createTableIndexExpression (
751- this . addExportToIdentifier ( tstl . cloneIdentifier ( className ) ) ,
752- tstl . createStringLiteral ( "prototype" )
753- ) ,
754- tstl . createStringLiteral ( "get__" + name . text ) ) ,
755- accessorFunction
815+ const classPrototype = tstl . createTableIndexExpression (
816+ this . addExportToIdentifier ( tstl . cloneIdentifier ( className ) ) ,
817+ tstl . createStringLiteral ( "prototype" )
818+ ) ;
819+ const classGetters = tstl . createTableIndexExpression (
820+ classPrototype ,
821+ tstl . createStringLiteral ( "____getters" )
756822 ) ;
823+ const getter = tstl . createTableIndexExpression (
824+ classGetters ,
825+ tstl . createStringLiteral ( name . text )
826+ ) ;
827+ const assignGetter = tstl . createAssignmentStatement ( getter , accessorFunction ) ;
828+ return assignGetter ;
757829 }
758830
759831 public transformSetAccessorDeclaration (
@@ -774,15 +846,20 @@ export class LuaTransformer {
774846 restParam
775847 ) ;
776848
777- return tstl . createAssignmentStatement (
778- tstl . createTableIndexExpression (
779- tstl . createTableIndexExpression (
780- this . addExportToIdentifier ( tstl . cloneIdentifier ( className ) ) ,
781- tstl . createStringLiteral ( "prototype" )
782- ) ,
783- tstl . createStringLiteral ( "set__" + name . text ) ) ,
784- accessorFunction
849+ const classPrototype = tstl . createTableIndexExpression (
850+ this . addExportToIdentifier ( tstl . cloneIdentifier ( className ) ) ,
851+ tstl . createStringLiteral ( "prototype" )
852+ ) ;
853+ const classSetters = tstl . createTableIndexExpression (
854+ classPrototype ,
855+ tstl . createStringLiteral ( "____setters" )
785856 ) ;
857+ const setter = tstl . createTableIndexExpression (
858+ classSetters ,
859+ tstl . createStringLiteral ( name . text )
860+ ) ;
861+ const assignSetter = tstl . createAssignmentStatement ( setter , accessorFunction ) ;
862+ return assignSetter ;
786863 }
787864
788865 public transformMethodDeclaration (
@@ -2155,16 +2232,6 @@ export class LuaTransformer {
21552232 }
21562233
21572234 public transformAssignment ( lhs : ts . Expression , right : tstl . Expression ) : tstl . Statement {
2158- if ( ts . isPropertyAccessExpression ( lhs ) ) {
2159- const hasSetAccessor = tsHelper . hasSetAccessor ( lhs , this . checker ) ;
2160- if ( hasSetAccessor ) {
2161- return tstl . createExpressionStatement ( this . transformSetAccessor ( lhs , right ) , lhs . parent ) ;
2162- } else if ( hasSetAccessor === undefined ) {
2163- // Undefined hasSetAccessor indicates a union with both set accessors and no accessors
2164- // on the same field.
2165- throw TSTLErrors . UnsupportedUnionAccessor ( lhs ) ;
2166- }
2167- }
21682235 return tstl . createAssignmentStatement (
21692236 this . transformExpression ( lhs ) as tstl . IdentifierOrTableIndexExpression ,
21702237 right ,
@@ -2232,10 +2299,7 @@ export class LuaTransformer {
22322299 ) ;
22332300 }
22342301
2235- if (
2236- ( ts . isPropertyAccessExpression ( expression . left ) && ! tsHelper . hasSetAccessor ( expression . left , this . checker ) )
2237- || ts . isElementAccessExpression ( expression . left )
2238- ) {
2302+ if ( ts . isPropertyAccessExpression ( expression . left ) || ts . isElementAccessExpression ( expression . left ) ) {
22392303 // Left is property/element access: cache result while maintaining order of evaluation
22402304 // (function(o, i, v) o[i] = v; return v end)(${objExpression}, ${indexExpression}, ${right})
22412305 const objParameter = tstl . createIdentifier ( "o" ) ;
@@ -3009,14 +3073,6 @@ export class LuaTransformer {
30093073 public transformPropertyAccessExpression ( node : ts . PropertyAccessExpression ) : tstl . Expression {
30103074 const property = node . name . text ;
30113075
3012- const hasGetAccessor = tsHelper . hasGetAccessor ( node , this . checker ) ;
3013- if ( hasGetAccessor ) {
3014- return this . transformGetAccessor ( node ) ;
3015- } else if ( hasGetAccessor === undefined ) {
3016- // Undefined hasGetAccessor indicates a union with both get accessors and no accessors on the same field.
3017- throw TSTLErrors . UnsupportedUnionAccessor ( node ) ;
3018- }
3019-
30203076 // Check for primitive types to override
30213077 const type = this . checker . getTypeAtLocation ( node . expression ) ;
30223078 if ( tsHelper . isStringType ( type ) ) {
@@ -3054,18 +3110,6 @@ export class LuaTransformer {
30543110 return tstl . createTableIndexExpression ( callPath , tstl . createStringLiteral ( property ) , node ) ;
30553111 }
30563112
3057- public transformGetAccessor ( node : ts . PropertyAccessExpression ) : tstl . MethodCallExpression {
3058- const name = tstl . createIdentifier ( `get__${ node . name . escapedText } ` ) ;
3059- const expression = this . transformExpression ( node . expression ) ;
3060- return tstl . createMethodCallExpression ( expression , name , [ ] , node ) ;
3061- }
3062-
3063- public transformSetAccessor ( node : ts . PropertyAccessExpression , value : tstl . Expression ) : tstl . MethodCallExpression {
3064- const name = tstl . createIdentifier ( `set__${ node . name . escapedText } ` ) ;
3065- const expression = this . transformExpression ( node . expression ) ;
3066- return tstl . createMethodCallExpression ( expression , name , [ value ] , node ) ;
3067- }
3068-
30693113 // Transpile a Math._ property
30703114 public transformMathExpression ( identifier : ts . Identifier ) : tstl . TableIndexExpression {
30713115 const translation = {
0 commit comments