@@ -1075,47 +1075,71 @@ export class LuaTransformer {
10751075 ) ) ;
10761076 }
10771077 } else {
1078- const table : tstl . IdentifierOrTableIndexExpression =
1079- this . transformIdentifierExpression ( enumDeclaration . name ) ;
1080- const property = tstl . createTableIndexExpression ( table , memberName , undefined ) ;
1078+ const enumTable = this . transformIdentifierExpression ( enumDeclaration . name ) ;
1079+ const property = tstl . createTableIndexExpression ( enumTable , memberName ) ;
10811080 result . push ( tstl . createAssignmentStatement ( property , enumMember . value , enumMember . original ) ) ;
1081+
1082+ const valueIndex = tstl . createTableIndexExpression ( enumTable , enumMember . value ) ;
1083+ result . push ( tstl . createAssignmentStatement ( valueIndex , memberName , enumMember . original ) ) ;
10821084 }
10831085 }
10841086
10851087 return result ;
10861088 }
10871089
10881090 public computeEnumMembers ( node : ts . EnumDeclaration ) :
1089- Array < { name : ts . PropertyName , value : tstl . NumericLiteral | tstl . StringLiteral , original : ts . Node } > {
1091+ Array < { name : ts . PropertyName , value : tstl . Expression , original : ts . Node } > {
10901092 let numericValue = 0 ;
10911093 let hasStringInitializers = false ;
10921094
1095+ const valueMap = new Map < ts . PropertyName , tstl . Expression > ( ) ;
1096+
10931097 return node . members . map ( member => {
1094- let valueLiteral : tstl . NumericLiteral | tstl . StringLiteral ;
1098+ let valueExpression : tstl . Expression ;
10951099 if ( member . initializer ) {
1096- if ( ts . isNumericLiteral ( member . initializer ) ) {
1100+ if ( ts . isNumericLiteral ( member . initializer ) )
1101+ {
10971102 numericValue = Number ( member . initializer . text ) ;
1098- valueLiteral = tstl . createNumericLiteral ( numericValue ) ;
1099- } else if ( ts . isStringLiteral ( member . initializer ) ) {
1103+ valueExpression = this . transformNumericLiteral ( member . initializer ) ;
1104+ numericValue ++ ;
1105+ }
1106+ else if ( ts . isStringLiteral ( member . initializer ) )
1107+ {
11001108 hasStringInitializers = true ;
1101- valueLiteral = tstl . createStringLiteral ( member . initializer . text ) ;
1102- } else {
1103- throw TSTLErrors . InvalidEnumMember ( member . initializer ) ;
1109+ valueExpression = this . transformStringLiteral ( member . initializer ) ;
11041110 }
1105- } else if ( hasStringInitializers ) {
1111+ else
1112+ {
1113+ if ( ts . isIdentifier ( member . initializer ) ) {
1114+ const [ isEnumMember , originalName ] = tsHelper . isEnumMember ( node , member . initializer ) ;
1115+ if ( isEnumMember ) {
1116+ valueExpression = valueMap . get ( originalName ) ;
1117+ } else {
1118+ valueExpression = this . transformExpression ( member . initializer ) ;
1119+ }
1120+ } else {
1121+ valueExpression = this . transformExpression ( member . initializer ) ;
1122+ }
1123+ }
1124+ }
1125+ else if ( hasStringInitializers )
1126+ {
11061127 throw TSTLErrors . HeterogeneousEnum ( node ) ;
1107- } else {
1108- valueLiteral = tstl . createNumericLiteral ( numericValue ) ;
11091128 }
1129+ else
1130+ {
1131+ valueExpression = tstl . createNumericLiteral ( numericValue ) ;
1132+ numericValue ++ ;
1133+ }
1134+
1135+ valueMap . set ( member . name , valueExpression ) ;
11101136
11111137 const enumMember = {
11121138 name : member . name ,
11131139 original : member ,
1114- value : valueLiteral ,
1140+ value : valueExpression ,
11151141 } ;
11161142
1117- numericValue ++ ;
1118-
11191143 return enumMember ;
11201144 } ) ;
11211145 }
@@ -2980,26 +3004,7 @@ export class LuaTransformer {
29803004 }
29813005
29823006 if ( type . symbol && ( type . symbol . flags & ts . SymbolFlags . ConstEnum ) ) {
2983- const propertyValueDeclaration = this . checker . getTypeAtLocation ( node ) . symbol . valueDeclaration ;
2984-
2985- if ( propertyValueDeclaration && propertyValueDeclaration . kind === ts . SyntaxKind . EnumMember ) {
2986- const enumMember = propertyValueDeclaration as ts . EnumMember ;
2987-
2988- if ( enumMember . initializer ) {
2989- return this . transformExpression ( enumMember . initializer ) ;
2990- } else {
2991- const enumMembers = this . computeEnumMembers ( enumMember . parent ) ;
2992- const memberPosition = enumMember . parent . members . indexOf ( enumMember ) ;
2993-
2994- if ( memberPosition === - 1 ) {
2995- throw TSTLErrors . UnsupportedProperty ( type . symbol . name , property , node ) ;
2996- }
2997-
2998- const value = tstl . cloneNode ( enumMembers [ memberPosition ] . value ) ;
2999- tstl . setNodeOriginal ( value , enumMember ) ;
3000- return value ;
3001- }
3002- }
3007+ return this . transformConstEnumValue ( type , property , node ) ;
30033008 }
30043009
30053010 this . checkForLuaLibType ( type ) ;
@@ -3095,6 +3100,13 @@ export class LuaTransformer {
30953100 const index = this . transformExpression ( node . argumentExpression ) ;
30963101
30973102 const type = this . checker . getTypeAtLocation ( node . expression ) ;
3103+
3104+ if ( type . symbol && ( type . symbol . flags & ts . SymbolFlags . ConstEnum )
3105+ && ts . isStringLiteral ( node . argumentExpression ) )
3106+ {
3107+ return this . transformConstEnumValue ( type , node . argumentExpression . text , node ) ;
3108+ }
3109+
30983110 if ( tsHelper . isArrayType ( type , this . checker ) ) {
30993111 return tstl . createTableIndexExpression ( table , this . expressionPlusOne ( index ) , node ) ;
31003112 } else if ( tsHelper . isStringType ( type ) ) {
@@ -3108,6 +3120,45 @@ export class LuaTransformer {
31083120 }
31093121 }
31103122
3123+ private transformConstEnumValue ( enumType : ts . EnumType , memberName : string , tsOriginal : ts . Node ) : tstl . Expression {
3124+ // Assumption: the enum only has one declaration
3125+ const enumDeclaration = enumType . symbol . declarations . find ( d => ts . isEnumDeclaration ( d ) ) as ts . EnumDeclaration ;
3126+ const enumMember = enumDeclaration . members
3127+ . find ( m => ts . isIdentifier ( m . name ) && m . name . text === memberName ) ;
3128+
3129+ if ( enumMember ) {
3130+ if ( enumMember . initializer ) {
3131+ if ( ts . isIdentifier ( enumMember . initializer ) ) {
3132+ const [ isEnumMember , valueName ] = tsHelper . isEnumMember ( enumDeclaration , enumMember . initializer ) ;
3133+ if ( isEnumMember ) {
3134+ if ( ts . isIdentifier ( valueName ) ) {
3135+ return this . transformConstEnumValue ( enumType , valueName . text , tsOriginal ) ;
3136+ }
3137+ } else {
3138+ return tstl . setNodeOriginal ( this . transformExpression ( enumMember . initializer ) , tsOriginal ) ;
3139+ }
3140+ } else {
3141+ return tstl . setNodeOriginal ( this . transformExpression ( enumMember . initializer ) , tsOriginal ) ;
3142+ }
3143+ } else {
3144+ let enumValue = 0 ;
3145+ for ( const member of enumDeclaration . members ) {
3146+ if ( member === enumMember ) {
3147+ return tstl . createNumericLiteral ( enumValue , tsOriginal ) ;
3148+ }
3149+ if ( member . initializer === undefined ) {
3150+ enumValue ++ ;
3151+ } else if ( ts . isNumericLiteral ( member . initializer ) ) {
3152+ enumValue = Number ( member . initializer . text ) + 1 ;
3153+ }
3154+ }
3155+
3156+ throw TSTLErrors . CouldNotFindEnumMember ( enumDeclaration , memberName , tsOriginal ) ;
3157+ }
3158+ }
3159+ throw TSTLErrors . CouldNotFindEnumMember ( enumDeclaration , memberName , tsOriginal ) ;
3160+ }
3161+
31113162 public transformStringCallExpression ( node : ts . CallExpression ) : tstl . Expression {
31123163 const expression = node . expression as ts . PropertyAccessExpression ;
31133164 const params = this . transformArguments ( node . arguments ) ;
0 commit comments