@@ -554,232 +554,118 @@ struct BridgeJSLink {
554554 func renderExportedEnum( _ enumDefinition: ExportedEnum ) throws -> ( js: [ String ] , dts: [ String ] ) {
555555 var jsLines : [ String ] = [ ]
556556 var dtsLines : [ String ] = [ ]
557- let style : EnumEmitStyle = enumDefinition. emitStyle
557+ let scope = JSGlueVariableScope ( )
558+ let cleanup = CodeFragmentPrinter ( )
559+ let printer = CodeFragmentPrinter ( )
558560
559561 switch enumDefinition. enumType {
560562 case . simple:
561- jsLines. append ( " const \( enumDefinition. name) = { " )
562- for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
563- let caseName = enumCase. name. capitalizedFirstLetter
564- jsLines. append ( " \( caseName) : \( index) , " . indent ( count: 4 ) )
565- }
566- jsLines. append ( " }; " )
567- jsLines. append ( " " )
568-
569- if enumDefinition. namespace == nil {
570- switch style {
571- case . tsEnum:
572- dtsLines. append ( " export enum \( enumDefinition. name) { " )
573- for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
574- let caseName = enumCase. name. capitalizedFirstLetter
575- dtsLines. append ( " \( caseName) = \( index) , " . indent ( count: 4 ) )
576- }
577- dtsLines. append ( " } " )
578- dtsLines. append ( " " )
579- case . const:
580- dtsLines. append ( " export const \( enumDefinition. name) : { " )
581- for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
582- let caseName = enumCase. name. capitalizedFirstLetter
583- dtsLines. append ( " readonly \( caseName) : \( index) ; " . indent ( count: 4 ) )
584- }
585- dtsLines. append ( " }; " )
586- dtsLines. append (
587- " export type \( enumDefinition. name) = typeof \( enumDefinition. name) [keyof typeof \( enumDefinition. name) ]; "
588- )
589- dtsLines. append ( " " )
590- }
591- }
563+ let fragment = IntrinsicJSFragment . simpleEnumHelper ( enumDefinition: enumDefinition)
564+ _ = fragment. printCode ( [ enumDefinition. name] , scope, printer, cleanup)
565+
566+ jsLines. append ( contentsOf: printer. lines)
592567 case . rawValue:
593- guard let rawType = enumDefinition . rawType else {
568+ guard enumDefinition . rawType != nil else {
594569 throw BridgeJSLinkError ( message: " Raw value enum \( enumDefinition. name) is missing rawType " )
595570 }
596571
597- jsLines. append ( " const \( enumDefinition. name) = { " )
598- for enumCase in enumDefinition. cases {
599- let caseName = enumCase. name. capitalizedFirstLetter
600- let rawValue = enumCase. rawValue ?? enumCase. name
601- let formattedValue : String
602-
603- if let rawTypeEnum = SwiftEnumRawType . from ( rawType) {
604- switch rawTypeEnum {
605- case . string:
606- formattedValue = " \" \( rawValue) \" "
607- case . bool:
608- formattedValue = rawValue. lowercased ( ) == " true " ? " true " : " false "
609- case . float, . double:
610- formattedValue = rawValue
611- default :
612- formattedValue = rawValue
613- }
614- } else {
615- formattedValue = rawValue
616- }
572+ let fragment = IntrinsicJSFragment . rawValueEnumHelper ( enumDefinition: enumDefinition)
573+ _ = fragment. printCode ( [ enumDefinition. name] , scope, printer, cleanup)
617574
618- jsLines. append ( " \( caseName) : \( formattedValue) , " . indent ( count: 4 ) )
619- }
620- jsLines. append ( " }; " )
621- jsLines. append ( " " )
622-
623- if enumDefinition. namespace == nil {
624- switch style {
625- case . tsEnum:
626- dtsLines. append ( " export enum \( enumDefinition. name) { " )
627- for enumCase in enumDefinition. cases {
628- let caseName = enumCase. name. capitalizedFirstLetter
575+ jsLines. append ( contentsOf: printer. lines)
576+ case . associatedValue:
577+ let fragment = IntrinsicJSFragment . associatedValueEnumHelper ( enumDefinition: enumDefinition)
578+ _ = fragment. printCode ( [ enumDefinition. name] , scope, printer, cleanup)
579+
580+ jsLines. append ( contentsOf: printer. lines)
581+ case . namespace:
582+ break
583+ }
584+
585+ if enumDefinition. namespace == nil {
586+ dtsLines. append ( contentsOf: generateDeclarations ( enumDefinition: enumDefinition) )
587+ }
588+
589+ return ( jsLines, dtsLines)
590+ }
591+
592+ private func generateDeclarations( enumDefinition: ExportedEnum ) -> [ String ] {
593+ let printer = CodeFragmentPrinter ( )
594+
595+ switch enumDefinition. emitStyle {
596+ case . tsEnum:
597+ switch enumDefinition. enumType {
598+ case . simple, . rawValue:
599+ printer. write ( " export enum \( enumDefinition. name) { " )
600+ printer. indent ( )
601+ for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
602+ let caseName = enumCase. name. capitalizedFirstLetter
603+ let value : String
604+
605+ switch enumDefinition. enumType {
606+ case . simple:
607+ value = " \( index) "
608+ case . rawValue:
629609 let rawValue = enumCase. rawValue ?? enumCase. name
630- let formattedValue : String
631- switch rawType {
632- case " String " : formattedValue = " \" \( rawValue) \" "
633- case " Bool " : formattedValue = rawValue. lowercased ( ) == " true " ? " true " : " false "
634- case " Float " , " Double " : formattedValue = rawValue
635- default : formattedValue = rawValue
636- }
637- dtsLines. append ( " \( caseName) = \( formattedValue) , " . indent ( count: 4 ) )
610+ value = SwiftEnumRawType . formatValue ( rawValue, rawType: enumDefinition. rawType ?? " " )
611+ case . associatedValue, . namespace:
612+ continue
638613 }
639- dtsLines. append ( " } " )
640- dtsLines. append ( " " )
641- case . const:
642- dtsLines. append ( " export const \( enumDefinition. name) : { " )
643- for enumCase in enumDefinition. cases {
644- let caseName = enumCase. name. capitalizedFirstLetter
645- let rawValue = enumCase. rawValue ?? enumCase. name
646- let formattedValue : String
647-
648- switch rawType {
649- case " String " :
650- formattedValue = " \" \( rawValue) \" "
651- case " Bool " :
652- formattedValue = rawValue. lowercased ( ) == " true " ? " true " : " false "
653- case " Float " , " Double " :
654- formattedValue = rawValue
655- default :
656- formattedValue = rawValue
657- }
658614
659- dtsLines. append ( " readonly \( caseName) : \( formattedValue) ; " . indent ( count: 4 ) )
660- }
661- dtsLines. append ( " }; " )
662- dtsLines. append (
663- " export type \( enumDefinition. name) = typeof \( enumDefinition. name) [keyof typeof \( enumDefinition. name) ]; "
664- )
665- dtsLines. append ( " " )
615+ printer. write ( " \( caseName) = \( value) , " )
666616 }
617+ printer. unindent ( )
618+ printer. write ( " } " )
619+ printer. write ( " " )
620+ case . associatedValue, . namespace:
621+ break
667622 }
668- case . associatedValue:
669- // Use the new IntrinsicJSFragment for associated value payload handling
670- jsLines. append ( " const \( enumDefinition. name) = { " )
671- jsLines. append ( " Tag: { " . indent ( count: 4 ) )
672- for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
673- let caseName = enumCase. name. capitalizedFirstLetter
674- jsLines. append ( " \( caseName) : \( index) , " . indent ( count: 8 ) )
675- }
676- jsLines. append ( " } " . indent ( count: 4 ) )
677- jsLines. append ( " }; " )
678- jsLines. append ( " " )
679- jsLines. append ( " const __bjs_create \( enumDefinition. name) Helpers = () => { " )
680- jsLines. append (
681- " return ( \( JSGlueVariableScope . reservedTmpParamInts) , \( JSGlueVariableScope . reservedTmpParamF32s) , \( JSGlueVariableScope . reservedTmpParamF64s) , textEncoder, \( JSGlueVariableScope . reservedSwift) ) => ({ "
682- . indent (
683- count: 4
684- )
685- )
686623
687- jsLines. append ( " lower: (value) => { " . indent ( count: 8 ) )
688- jsLines. append ( " const enumTag = value.tag; " . indent ( count: 12 ) )
689- jsLines. append ( " switch (enumTag) { " . indent ( count: 12 ) )
690- enumDefinition. cases. forEach { enumCase in
691- let caseName = enumCase. name. capitalizedFirstLetter
692- if enumCase. associatedValues. isEmpty {
693- jsLines. append ( " case \( enumDefinition. name) .Tag. \( caseName) : { " . indent ( count: 16 ) )
694- jsLines. append ( " const cleanup = undefined; " . indent ( count: 20 ) )
695- jsLines. append (
696- " return { caseId: \( enumDefinition. name) .Tag. \( caseName) , cleanup }; "
697- . indent ( count: 20 )
698- )
699- jsLines. append ( " } " . indent ( count: 16 ) )
700- } else {
701- let scope = JSGlueVariableScope ( )
702- let cleanup = CodeFragmentPrinter ( )
703- let printer = CodeFragmentPrinter ( )
704- cleanup. indent ( )
705-
706- let fragment = IntrinsicJSFragment . associatedValuePushPayload ( enumCase: enumCase)
707- _ = fragment. printCode ( [ " value " , enumDefinition. name, caseName] , scope, printer, cleanup)
708-
709- jsLines. append ( " case \( enumDefinition. name) .Tag. \( caseName) : { " . indent ( count: 16 ) )
710- jsLines. append ( contentsOf: printer. lines. map { $0. indent ( count: 20 ) } )
711- jsLines. append ( " } " . indent ( count: 16 ) )
624+ case . const:
625+ switch enumDefinition. enumType {
626+ case . simple:
627+ printer. write ( " export const \( enumDefinition. name) : { " )
628+ printer. indent ( )
629+ for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
630+ let caseName = enumCase. name. capitalizedFirstLetter
631+ printer. write ( " readonly \( caseName) : \( index) ; " )
712632 }
713- }
714- jsLines . append (
715- " default: throw new Error( \" Unknown \( enumDefinition . name ) tag: \" + String(enumTag)); " . indent (
716- count : 16
633+ printer . unindent ( )
634+ printer . write ( " }; " )
635+ printer . write (
636+ " export type \( enumDefinition . name ) = typeof \( enumDefinition . name ) [keyof typeof \( enumDefinition . name ) ]; "
717637 )
718- )
719- jsLines. append ( " } " . indent ( count: 12 ) )
720- jsLines. append ( " }, " . indent ( count: 8 ) )
721-
722- jsLines. append (
723- " raise: ( \( JSGlueVariableScope . reservedTmpRetTag) , \( JSGlueVariableScope . reservedTmpRetStrings) , \( JSGlueVariableScope . reservedTmpRetInts) , \( JSGlueVariableScope . reservedTmpRetF32s) , \( JSGlueVariableScope . reservedTmpRetF64s) ) => { "
724- . indent (
725- count: 8
726- )
727- )
728- jsLines. append ( " const tag = tmpRetTag | 0; " . indent ( count: 12 ) )
729- jsLines. append ( " switch (tag) { " . indent ( count: 12 ) )
730- enumDefinition. cases. forEach { enumCase in
731- let caseName = enumCase. name. capitalizedFirstLetter
732- if enumCase. associatedValues. isEmpty {
733- jsLines. append (
734- " case \( enumDefinition. name) .Tag. \( caseName) : return { tag: \( enumDefinition. name) .Tag. \( caseName) }; "
735- . indent ( count: 16 )
736- )
737- } else {
738- var fieldPairs : [ String ] = [ ]
739- let scope = JSGlueVariableScope ( )
740- let printer = CodeFragmentPrinter ( )
741- let cleanup = CodeFragmentPrinter ( )
742- // Use the new IntrinsicJSFragment for associated value payload handling
743- for (associatedValueIndex, associatedValue) in enumCase. associatedValues. enumerated ( ) . reversed ( ) {
744- let prop = associatedValue. label ?? " param \( associatedValueIndex) "
745- let fragment = IntrinsicJSFragment . associatedValuePopPayload ( type: associatedValue. type)
746-
747- let result = fragment. printCode ( [ ] , scope, printer, cleanup)
748- let varName = result. first ?? " value_ \( associatedValueIndex) "
749-
750- fieldPairs. append ( " \( prop) : \( varName) " )
751- }
752-
753- jsLines. append ( " case \( enumDefinition. name) .Tag. \( caseName) : { " . indent ( count: 16 ) )
754- jsLines. append ( contentsOf: printer. lines. map { $0. indent ( count: 20 ) } )
755- jsLines. append (
756- " return { tag: \( enumDefinition. name) .Tag. \( caseName) , \( fieldPairs. reversed ( ) . joined ( separator: " , " ) ) }; "
757- . indent ( count: 20 )
758- )
759- jsLines. append ( " } " . indent ( count: 16 ) )
638+ printer. write ( " " )
639+ case . rawValue:
640+ printer. write ( " export const \( enumDefinition. name) : { " )
641+ printer. indent ( )
642+ for enumCase in enumDefinition. cases {
643+ let caseName = enumCase. name. capitalizedFirstLetter
644+ let rawValue = enumCase. rawValue ?? enumCase. name
645+ let formattedValue = SwiftEnumRawType . formatValue ( rawValue, rawType: enumDefinition. rawType ?? " " )
646+ printer. write ( " readonly \( caseName) : \( formattedValue) ; " )
760647 }
761- }
762- jsLines. append (
763- " default: throw new Error( \" Unknown \( enumDefinition. name) tag returned from Swift: \" + String(tag)); "
764- . indent (
765- count: 16
766- )
767- )
768- jsLines. append ( " } " . indent ( count: 12 ) )
769- jsLines. append ( " } " . indent ( count: 8 ) )
770- jsLines. append ( " }); " . indent ( count: 4 ) )
771- jsLines. append ( " }; " )
772-
773- if enumDefinition. namespace == nil {
774- dtsLines. append ( " export const \( enumDefinition. name) : { " )
775- dtsLines. append ( " readonly Tag: { " . indent ( count: 4 ) )
648+ printer. unindent ( )
649+ printer. write ( " }; " )
650+ printer. write (
651+ " export type \( enumDefinition. name) = typeof \( enumDefinition. name) [keyof typeof \( enumDefinition. name) ]; "
652+ )
653+ printer. write ( " " )
654+ case . associatedValue:
655+ printer. write ( " export const \( enumDefinition. name) : { " )
656+ printer. indent ( )
657+ printer. write ( " readonly Tag: { " )
658+ printer. indent ( )
776659 for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
777660 let caseName = enumCase. name. capitalizedFirstLetter
778- dtsLines . append ( " readonly \( caseName) : \( index) ; " . indent ( count : 8 ) )
661+ printer . write ( " readonly \( caseName) : \( index) ; " )
779662 }
780- dtsLines. append ( " }; " . indent ( count: 4 ) )
781- dtsLines. append ( " }; " )
782- dtsLines. append ( " " )
663+ printer. unindent ( )
664+ printer. write ( " }; " )
665+ printer. unindent ( )
666+ printer. write ( " }; " )
667+ printer. write ( " " )
668+
783669 var unionParts : [ String ] = [ ]
784670 for enumCase in enumDefinition. cases {
785671 if enumCase. associatedValues. isEmpty {
@@ -790,32 +676,26 @@ struct BridgeJSLink {
790676 var fields : [ String ] = [
791677 " tag: typeof \( enumDefinition. name) .Tag. \( enumCase. name. capitalizedFirstLetter) "
792678 ]
793- for (associatedValueIndex, associatedValue) in enumCase. associatedValues
794- . enumerated ( )
795- {
679+ for (associatedValueIndex, associatedValue) in enumCase. associatedValues. enumerated ( ) {
796680 let prop = associatedValue. label ?? " param \( associatedValueIndex) "
797- let ts : String
798- switch associatedValue. type {
799- case . string: ts = " string "
800- case . bool: ts = " boolean "
801- case . int, . float, . double: ts = " number "
802- default : ts = " never "
803- }
804- fields. append ( " \( prop) : \( ts) " )
681+ fields. append ( " \( prop) : \( associatedValue. type. tsType) " )
805682 }
806683 unionParts. append ( " { \( fields. joined ( separator: " ; " ) ) } " )
807684 }
808685 }
809- dtsLines. append ( " export type \( enumDefinition. name) = " )
810- dtsLines. append ( " " + unionParts. joined ( separator: " | " ) )
811- dtsLines. append ( " " )
686+
687+ printer. write ( " export type \( enumDefinition. name) = " )
688+ printer. write ( " " + unionParts. joined ( separator: " | " ) )
689+ printer. write ( " " )
690+ case . namespace:
691+ break
812692 }
813- case . namespace:
814- break
815693 }
816-
817- return ( jsLines, dtsLines)
694+ return printer. lines
818695 }
696+ }
697+
698+ extension BridgeJSLink {
819699
820700 func renderExportedFunction( function: ExportedFunction ) throws -> ( js: [ String ] , dts: [ String ] ) {
821701 let thunkBuilder = ExportedThunkBuilder ( effects: function. effects)
@@ -1502,14 +1382,7 @@ struct BridgeJSLink {
15021382 . enumerated ( )
15031383 {
15041384 let prop = associatedValue. label ?? " param \( associatedValueIndex) "
1505- let ts : String
1506- switch associatedValue. type {
1507- case . string: ts = " string "
1508- case . bool: ts = " boolean "
1509- case . int, . float, . double: ts = " number "
1510- default : ts = " never "
1511- }
1512- fields. append ( " \( prop) : \( ts) " )
1385+ fields. append ( " \( prop) : \( associatedValue. type. tsType) " )
15131386 }
15141387 unionParts. append ( " { \( fields. joined ( separator: " ; " ) ) } " )
15151388 }
0 commit comments