@@ -1654,115 +1654,77 @@ export class LuaTransformer {
16541654 return result ;
16551655 }
16561656
1657- public transformEnumDeclaration ( enumDeclaration : ts . EnumDeclaration ) : StatementVisitResult {
1658- const type = this . checker . getTypeAtLocation ( enumDeclaration ) ;
1659-
1660- // Const enums should never appear in the resulting code
1661- if ( type . symbol . getFlags ( ) & ts . SymbolFlags . ConstEnum ) {
1657+ public transformEnumDeclaration ( node : ts . EnumDeclaration ) : StatementVisitResult {
1658+ if ( ts . getCombinedModifierFlags ( node ) & ts . ModifierFlags . Const && ! this . options . preserveConstEnums ) {
16621659 return undefined ;
16631660 }
16641661
1662+ const type = this . checker . getTypeAtLocation ( node ) ;
16651663 const membersOnly = tsHelper . getCustomDecorators ( type , this . checker ) . has ( DecoratorKind . CompileMembersOnly ) ;
1666-
16671664 const result : tstl . Statement [ ] = [ ] ;
16681665
16691666 if ( ! membersOnly ) {
1670- const name = this . transformIdentifier ( enumDeclaration . name ) ;
1667+ const name = this . transformIdentifier ( node . name ) ;
16711668 const table = tstl . createTableExpression ( ) ;
1672- result . push ( ...this . createLocalOrExportedOrGlobalDeclaration ( name , table , enumDeclaration ) ) ;
1669+ result . push ( ...this . createLocalOrExportedOrGlobalDeclaration ( name , table , node ) ) ;
16731670 }
16741671
1675- for ( const enumMember of this . computeEnumMembers ( enumDeclaration ) ) {
1676- const memberName = this . transformPropertyName ( enumMember . name ) ;
1677- if ( membersOnly ) {
1678- const enumSymbol = this . checker . getSymbolAtLocation ( enumDeclaration . name ) ;
1679- const exportScope = enumSymbol ? this . getSymbolExportScope ( enumSymbol ) : undefined ;
1672+ const enumReference = this . transformExpression ( node . name ) ;
1673+ for ( const member of node . members ) {
1674+ const memberName = this . transformPropertyName ( member . name ) ;
16801675
1681- if ( tstl . isIdentifier ( memberName ) ) {
1682- result . push (
1683- ...this . createLocalOrExportedOrGlobalDeclaration (
1684- memberName ,
1685- enumMember . value ,
1686- enumDeclaration ,
1687- undefined ,
1688- exportScope
1689- )
1690- ) ;
1691- } else {
1692- result . push (
1693- ...this . createLocalOrExportedOrGlobalDeclaration (
1694- tstl . createIdentifier ( enumMember . name . getText ( ) , enumMember . name ) ,
1695- enumMember . value ,
1696- enumDeclaration ,
1697- undefined ,
1698- exportScope
1699- )
1700- ) ;
1676+ let valueExpression : tstl . Expression | undefined ;
1677+ const constEnumValue = this . tryGetConstEnumValue ( member ) ;
1678+ if ( constEnumValue ) {
1679+ valueExpression = constEnumValue ;
1680+ } else if ( member . initializer ) {
1681+ if ( ts . isIdentifier ( member . initializer ) ) {
1682+ const symbol = this . checker . getSymbolAtLocation ( member . initializer ) ;
1683+ if (
1684+ symbol &&
1685+ symbol . valueDeclaration &&
1686+ ts . isEnumMember ( symbol . valueDeclaration ) &&
1687+ symbol . valueDeclaration . parent === node
1688+ ) {
1689+ const otherMemberName = this . transformPropertyName ( symbol . valueDeclaration . name ) ;
1690+ valueExpression = tstl . createTableIndexExpression ( enumReference , otherMemberName ) ;
1691+ }
17011692 }
1702- } else {
1703- const enumTable = this . transformIdentifierExpression ( enumDeclaration . name ) ;
1704- const property = tstl . createTableIndexExpression ( enumTable , memberName ) ;
1705- result . push ( tstl . createAssignmentStatement ( property , enumMember . value , enumMember . original ) ) ;
17061693
1707- const valueIndex = tstl . createTableIndexExpression ( enumTable , enumMember . value ) ;
1708- result . push ( tstl . createAssignmentStatement ( valueIndex , memberName , enumMember . original ) ) ;
1709- }
1710- }
1711-
1712- return result ;
1713- }
1714-
1715- protected computeEnumMembers (
1716- node : ts . EnumDeclaration
1717- ) : Array < { name : ts . PropertyName ; value : tstl . Expression ; original : ts . Node } > {
1718- let numericValue = 0 ;
1719- let hasStringInitializers = false ;
1720-
1721- const valueMap = new Map < ts . PropertyName , ExpressionVisitResult > ( ) ;
1722-
1723- return node . members . map ( member => {
1724- let valueExpression : ExpressionVisitResult ;
1725- if ( member . initializer ) {
1726- if ( ts . isNumericLiteral ( member . initializer ) ) {
1727- numericValue = Number ( member . initializer . text ) ;
1728- valueExpression = this . transformNumericLiteral ( member . initializer ) ;
1729- numericValue ++ ;
1730- } else if ( ts . isStringLiteral ( member . initializer ) ) {
1731- hasStringInitializers = true ;
1732- valueExpression = this . transformStringLiteral ( member . initializer ) ;
1733- } else {
1734- if ( ts . isIdentifier ( member . initializer ) ) {
1735- const [ isEnumMember , originalName ] = tsHelper . isEnumMember ( node , member . initializer ) ;
1736- if ( isEnumMember === true && originalName !== undefined ) {
1737- if ( valueMap . has ( originalName ) ) {
1738- valueExpression = valueMap . get ( originalName ) ! ;
1739- } else {
1740- throw new Error ( `Expected valueMap to contain ${ originalName } ` ) ;
1741- }
1742- } else {
1743- valueExpression = this . transformExpression ( member . initializer ) ;
1744- }
1745- } else {
1746- valueExpression = this . transformExpression ( member . initializer ) ;
1747- }
1694+ if ( ! valueExpression ) {
1695+ valueExpression = this . transformExpression ( member . initializer ) ;
17481696 }
1749- } else if ( hasStringInitializers ) {
1750- throw TSTLErrors . HeterogeneousEnum ( node ) ;
17511697 } else {
1752- valueExpression = tstl . createNumericLiteral ( numericValue ) ;
1753- numericValue ++ ;
1698+ valueExpression = tstl . createNilLiteral ( ) ;
17541699 }
17551700
1756- valueMap . set ( member . name , valueExpression ) ;
1701+ if ( membersOnly ) {
1702+ const enumSymbol = this . checker . getSymbolAtLocation ( node . name ) ;
1703+ const exportScope = enumSymbol ? this . getSymbolExportScope ( enumSymbol ) : undefined ;
17571704
1758- const enumMember = {
1759- name : member . name ,
1760- original : member ,
1761- value : valueExpression ,
1762- } ;
1705+ result . push (
1706+ ...this . createLocalOrExportedOrGlobalDeclaration (
1707+ tstl . isIdentifier ( memberName )
1708+ ? memberName
1709+ : tstl . createIdentifier ( member . name . getText ( ) , member . name ) ,
1710+ valueExpression ,
1711+ node ,
1712+ undefined ,
1713+ exportScope
1714+ )
1715+ ) ;
1716+ } else {
1717+ const memberAccessor = tstl . createTableIndexExpression ( enumReference , memberName ) ;
1718+ result . push ( tstl . createAssignmentStatement ( memberAccessor , valueExpression , member ) ) ;
17631719
1764- return enumMember ;
1765- } ) ;
1720+ if ( ! tstl . isStringLiteral ( valueExpression ) ) {
1721+ const reverseMemberAccessor = tstl . createTableIndexExpression ( enumReference , memberAccessor ) ;
1722+ result . push ( tstl . createAssignmentStatement ( reverseMemberAccessor , memberName , member ) ) ;
1723+ }
1724+ }
1725+ }
1726+
1727+ return result ;
17661728 }
17671729
17681730 protected transformGeneratorFunction (
@@ -4327,7 +4289,7 @@ export class LuaTransformer {
43274289 }
43284290
43294291 private tryGetConstEnumValue (
4330- node : ts . PropertyAccessExpression | ts . ElementAccessExpression
4292+ node : ts . EnumMember | ts . PropertyAccessExpression | ts . ElementAccessExpression
43314293 ) : tstl . Expression | undefined {
43324294 const value = this . checker . getConstantValue ( node ) ;
43334295 if ( typeof value === "string" ) {
0 commit comments