@@ -1727,115 +1727,77 @@ export class LuaTransformer {
17271727 return result ;
17281728 }
17291729
1730- public transformEnumDeclaration ( enumDeclaration : ts . EnumDeclaration ) : StatementVisitResult {
1731- const type = this . checker . getTypeAtLocation ( enumDeclaration ) ;
1732-
1733- // Const enums should never appear in the resulting code
1734- if ( type . symbol . getFlags ( ) & ts . SymbolFlags . ConstEnum ) {
1730+ public transformEnumDeclaration ( node : ts . EnumDeclaration ) : StatementVisitResult {
1731+ if ( ts . getCombinedModifierFlags ( node ) & ts . ModifierFlags . Const && ! this . options . preserveConstEnums ) {
17351732 return undefined ;
17361733 }
17371734
1735+ const type = this . checker . getTypeAtLocation ( node ) ;
17381736 const membersOnly = tsHelper . getCustomDecorators ( type , this . checker ) . has ( DecoratorKind . CompileMembersOnly ) ;
1739-
17401737 const result : tstl . Statement [ ] = [ ] ;
17411738
17421739 if ( ! membersOnly ) {
1743- const name = this . transformIdentifier ( enumDeclaration . name ) ;
1740+ const name = this . transformIdentifier ( node . name ) ;
17441741 const table = tstl . createTableExpression ( ) ;
1745- result . push ( ...this . createLocalOrExportedOrGlobalDeclaration ( name , table , enumDeclaration ) ) ;
1742+ result . push ( ...this . createLocalOrExportedOrGlobalDeclaration ( name , table , node ) ) ;
17461743 }
17471744
1748- for ( const enumMember of this . computeEnumMembers ( enumDeclaration ) ) {
1749- const memberName = this . transformPropertyName ( enumMember . name ) ;
1750- if ( membersOnly ) {
1751- const enumSymbol = this . checker . getSymbolAtLocation ( enumDeclaration . name ) ;
1752- const exportScope = enumSymbol ? this . getSymbolExportScope ( enumSymbol ) : undefined ;
1745+ const enumReference = this . transformExpression ( node . name ) ;
1746+ for ( const member of node . members ) {
1747+ const memberName = this . transformPropertyName ( member . name ) ;
17531748
1754- if ( tstl . isIdentifier ( memberName ) ) {
1755- result . push (
1756- ...this . createLocalOrExportedOrGlobalDeclaration (
1757- memberName ,
1758- enumMember . value ,
1759- enumDeclaration ,
1760- undefined ,
1761- exportScope
1762- )
1763- ) ;
1764- } else {
1765- result . push (
1766- ...this . createLocalOrExportedOrGlobalDeclaration (
1767- tstl . createIdentifier ( enumMember . name . getText ( ) , enumMember . name ) ,
1768- enumMember . value ,
1769- enumDeclaration ,
1770- undefined ,
1771- exportScope
1772- )
1773- ) ;
1749+ let valueExpression : tstl . Expression | undefined ;
1750+ const constEnumValue = this . tryGetConstEnumValue ( member ) ;
1751+ if ( constEnumValue ) {
1752+ valueExpression = constEnumValue ;
1753+ } else if ( member . initializer ) {
1754+ if ( ts . isIdentifier ( member . initializer ) ) {
1755+ const symbol = this . checker . getSymbolAtLocation ( member . initializer ) ;
1756+ if (
1757+ symbol &&
1758+ symbol . valueDeclaration &&
1759+ ts . isEnumMember ( symbol . valueDeclaration ) &&
1760+ symbol . valueDeclaration . parent === node
1761+ ) {
1762+ const otherMemberName = this . transformPropertyName ( symbol . valueDeclaration . name ) ;
1763+ valueExpression = tstl . createTableIndexExpression ( enumReference , otherMemberName ) ;
1764+ }
17741765 }
1775- } else {
1776- const enumTable = this . transformIdentifierExpression ( enumDeclaration . name ) ;
1777- const property = tstl . createTableIndexExpression ( enumTable , memberName ) ;
1778- result . push ( tstl . createAssignmentStatement ( property , enumMember . value , enumMember . original ) ) ;
17791766
1780- const valueIndex = tstl . createTableIndexExpression ( enumTable , enumMember . value ) ;
1781- result . push ( tstl . createAssignmentStatement ( valueIndex , memberName , enumMember . original ) ) ;
1782- }
1783- }
1784-
1785- return result ;
1786- }
1787-
1788- protected computeEnumMembers (
1789- node : ts . EnumDeclaration
1790- ) : Array < { name : ts . PropertyName ; value : tstl . Expression ; original : ts . Node } > {
1791- let numericValue = 0 ;
1792- let hasStringInitializers = false ;
1793-
1794- const valueMap = new Map < ts . PropertyName , ExpressionVisitResult > ( ) ;
1795-
1796- return node . members . map ( member => {
1797- let valueExpression : ExpressionVisitResult ;
1798- if ( member . initializer ) {
1799- if ( ts . isNumericLiteral ( member . initializer ) ) {
1800- numericValue = Number ( member . initializer . text ) ;
1801- valueExpression = this . transformNumericLiteral ( member . initializer ) ;
1802- numericValue ++ ;
1803- } else if ( ts . isStringLiteral ( member . initializer ) ) {
1804- hasStringInitializers = true ;
1805- valueExpression = this . transformStringLiteral ( member . initializer ) ;
1806- } else {
1807- if ( ts . isIdentifier ( member . initializer ) ) {
1808- const [ isEnumMember , originalName ] = tsHelper . isEnumMember ( node , member . initializer ) ;
1809- if ( isEnumMember === true && originalName !== undefined ) {
1810- if ( valueMap . has ( originalName ) ) {
1811- valueExpression = valueMap . get ( originalName ) ! ;
1812- } else {
1813- throw new Error ( `Expected valueMap to contain ${ originalName } ` ) ;
1814- }
1815- } else {
1816- valueExpression = this . transformExpression ( member . initializer ) ;
1817- }
1818- } else {
1819- valueExpression = this . transformExpression ( member . initializer ) ;
1820- }
1767+ if ( ! valueExpression ) {
1768+ valueExpression = this . transformExpression ( member . initializer ) ;
18211769 }
1822- } else if ( hasStringInitializers ) {
1823- throw TSTLErrors . HeterogeneousEnum ( node ) ;
18241770 } else {
1825- valueExpression = tstl . createNumericLiteral ( numericValue ) ;
1826- numericValue ++ ;
1771+ valueExpression = tstl . createNilLiteral ( ) ;
18271772 }
18281773
1829- valueMap . set ( member . name , valueExpression ) ;
1774+ if ( membersOnly ) {
1775+ const enumSymbol = this . checker . getSymbolAtLocation ( node . name ) ;
1776+ const exportScope = enumSymbol ? this . getSymbolExportScope ( enumSymbol ) : undefined ;
18301777
1831- const enumMember = {
1832- name : member . name ,
1833- original : member ,
1834- value : valueExpression ,
1835- } ;
1778+ result . push (
1779+ ...this . createLocalOrExportedOrGlobalDeclaration (
1780+ tstl . isIdentifier ( memberName )
1781+ ? memberName
1782+ : tstl . createIdentifier ( member . name . getText ( ) , member . name ) ,
1783+ valueExpression ,
1784+ node ,
1785+ undefined ,
1786+ exportScope
1787+ )
1788+ ) ;
1789+ } else {
1790+ const memberAccessor = tstl . createTableIndexExpression ( enumReference , memberName ) ;
1791+ result . push ( tstl . createAssignmentStatement ( memberAccessor , valueExpression , member ) ) ;
18361792
1837- return enumMember ;
1838- } ) ;
1793+ if ( ! tstl . isStringLiteral ( valueExpression ) && ! tstl . isNilLiteral ( valueExpression ) ) {
1794+ const reverseMemberAccessor = tstl . createTableIndexExpression ( enumReference , memberAccessor ) ;
1795+ result . push ( tstl . createAssignmentStatement ( reverseMemberAccessor , memberName , member ) ) ;
1796+ }
1797+ }
1798+ }
1799+
1800+ return result ;
18391801 }
18401802
18411803 protected transformGeneratorFunction (
@@ -4707,7 +4669,7 @@ export class LuaTransformer {
47074669 }
47084670
47094671 private tryGetConstEnumValue (
4710- node : ts . PropertyAccessExpression | ts . ElementAccessExpression
4672+ node : ts . EnumMember | ts . PropertyAccessExpression | ts . ElementAccessExpression
47114673 ) : tstl . Expression | undefined {
47124674 const value = this . checker . getConstantValue ( node ) ;
47134675 if ( typeof value === "string" ) {
0 commit comments