@@ -142,7 +142,7 @@ public class ExportSwift {
142142 hint: " Only primitive types and types defined in the same module are allowed "
143143 )
144144 }
145-
145+
146146 private func diagnoseNestedOptional( node: some SyntaxProtocol , type: String ) {
147147 diagnose (
148148 node: node,
@@ -192,30 +192,30 @@ public class ExportSwift {
192192 var parameters : [ Parameter ] = [ ]
193193 for param in node. signature. parameterClause. parameters {
194194 let resolvedType = self . parent. lookupType ( for: param. type)
195-
195+
196196 if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
197197 diagnoseNestedOptional ( node: param. type, type: param. type. trimmedDescription)
198198 continue
199199 }
200-
200+
201201 guard let type = resolvedType else {
202202 diagnoseUnsupportedType ( node: param. type, type: param. type. trimmedDescription)
203203 continue
204204 }
205-
205+
206206 let name = param. secondName? . text ?? param. firstName. text
207207 let label = param. firstName. text
208208 parameters. append ( Parameter ( label: label, name: name, type: type) )
209209 }
210210 let returnType : BridgeType
211211 if let returnClause = node. signature. returnClause {
212212 let resolvedType = self . parent. lookupType ( for: returnClause. type)
213-
213+
214214 if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
215215 diagnoseNestedOptional ( node: returnClause. type, type: returnClause. type. trimmedDescription)
216216 return nil
217217 }
218-
218+
219219 guard let type = resolvedType else {
220220 diagnoseUnsupportedType ( node: returnClause. type, type: returnClause. type. trimmedDescription)
221221 return nil
@@ -561,12 +561,24 @@ public class ExportSwift {
561561 switch associatedValue. type {
562562 case . string, . int, . float, . double, . bool:
563563 break
564+ case . optional( let wrappedType) :
565+ switch wrappedType {
566+ case . string, . int, . float, . double, . bool:
567+ break
568+ default :
569+ diagnose (
570+ node: node,
571+ message: " Unsupported associated value type: \( associatedValue. type. swiftType) " ,
572+ hint:
573+ " Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums "
574+ )
575+ }
564576 default :
565577 diagnose (
566578 node: node,
567579 message: " Unsupported associated value type: \( associatedValue. type. swiftType) " ,
568580 hint:
569- " Only primitive types (String, Int, Float, Double, Bool) are supported in associated-value enums "
581+ " Only primitive types and optional primitives (String? , Int? , Float? , Double? , Bool? ) are supported in associated-value enums "
570582 )
571583 }
572584 }
@@ -744,22 +756,24 @@ public class ExportSwift {
744756 }
745757 // Optional<T>
746758 if let identifierType = type. as ( IdentifierTypeSyntax . self) ,
747- identifierType. name. text == " Optional " ,
748- let genericArgs = identifierType. genericArgumentClause? . arguments,
749- genericArgs. count == 1 ,
750- let argType = genericArgs. first? . argument {
759+ identifierType. name. text == " Optional " ,
760+ let genericArgs = identifierType. genericArgumentClause? . arguments,
761+ genericArgs. count == 1 ,
762+ let argType = genericArgs. first? . argument
763+ {
751764 if let baseType = lookupType ( for: argType) {
752765 return . optional( baseType)
753766 }
754767 }
755768 // Swift.Optional<T>
756769 if let memberType = type. as ( MemberTypeSyntax . self) ,
757- let baseType = memberType. baseType. as ( IdentifierTypeSyntax . self) ,
758- baseType. name. text == " Swift " ,
759- memberType. name. text == " Optional " ,
760- let genericArgs = memberType. genericArgumentClause? . arguments,
761- genericArgs. count == 1 ,
762- let argType = genericArgs. first? . argument {
770+ let baseType = memberType. baseType. as ( IdentifierTypeSyntax . self) ,
771+ baseType. name. text == " Swift " ,
772+ memberType. name. text == " Optional " ,
773+ let genericArgs = memberType. genericArgumentClause? . arguments,
774+ genericArgs. count == 1 ,
775+ let argType = genericArgs. first? . argument
776+ {
763777 if let wrappedType = lookupType ( for: argType) {
764778 return . optional( wrappedType)
765779 }
@@ -771,7 +785,7 @@ public class ExportSwift {
771785 }
772786
773787 let typeName = type. trimmedDescription
774- if let primitiveType = BridgeType . primitive ( swiftType: typeName) {
788+ if let primitiveType = BridgeType ( swiftType: typeName) {
775789 return primitiveType
776790 }
777791
@@ -890,15 +904,15 @@ public class ExportSwift {
890904 } else {
891905 argumentsToLift = liftingInfo. parameters. map { ( name, _) in param. name + name. capitalizedFirstLetter }
892906 }
893-
907+
894908 let typeNameForIntrinsic : String
895909 switch param. type {
896910 case . optional( let wrappedType) :
897911 typeNameForIntrinsic = " Optional< \( wrappedType. swiftType) > "
898912 default :
899913 typeNameForIntrinsic = param. type. swiftType
900914 }
901-
915+
902916 liftedParameterExprs. append (
903917 ExprSyntax (
904918 " \( raw: typeNameForIntrinsic) .bridgeJSLiftParameter( \( raw: argumentsToLift. joined ( separator: " , " ) ) ) "
@@ -996,11 +1010,6 @@ public class ExportSwift {
9961010 return
9971011 }
9981012
999- if case . optional( _) = returnType {
1000- append ( " return ret.bridgeJSLowerReturn() " )
1001- return
1002- }
1003-
10041013 append ( " return ret.bridgeJSLowerReturn() " )
10051014 }
10061015
@@ -1158,8 +1167,26 @@ public class ExportSwift {
11581167 return " \( paramName) Float.bridgeJSLiftParameter(_swift_js_pop_param_f32()) "
11591168 case . double:
11601169 return " \( paramName) Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) "
1161- case . optional( _) :
1162- return " nil "
1170+ case . optional( let wrappedType) :
1171+ switch wrappedType {
1172+ case . string:
1173+ return
1174+ " \( paramName) Optional<String>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32()) "
1175+ case . int:
1176+ return
1177+ " \( paramName) Optional<Int>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) "
1178+ case . bool:
1179+ return
1180+ " \( paramName) Optional<Bool>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()) "
1181+ case . float:
1182+ return
1183+ " \( paramName) Optional<Float>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f32()) "
1184+ case . double:
1185+ return
1186+ " \( paramName) Optional<Double>.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f64()) "
1187+ default :
1188+ return " "
1189+ }
11631190 default :
11641191 return " \( paramName) Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) "
11651192 }
@@ -1196,6 +1223,30 @@ public class ExportSwift {
11961223 bodyLines. append ( " _swift_js_push_f32( \( paramName) ) " )
11971224 case . double:
11981225 bodyLines. append ( " _swift_js_push_f64( \( paramName) ) " )
1226+ case . optional( let wrappedType) :
1227+ bodyLines. append ( " let __bjs_isSome_ \( paramName) = \( paramName) != nil " )
1228+ bodyLines. append ( " if let __bjs_unwrapped_ \( paramName) = \( paramName) { " )
1229+ switch wrappedType {
1230+ case . string:
1231+ bodyLines. append ( " var __bjs_str_ \( paramName) = __bjs_unwrapped_ \( paramName) " )
1232+ bodyLines. append ( " __bjs_str_ \( paramName) .withUTF8 { ptr in " )
1233+ bodyLines. append ( " _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) " )
1234+ bodyLines. append ( " } " )
1235+ case . int:
1236+ bodyLines. append ( " _swift_js_push_int(Int32(__bjs_unwrapped_ \( paramName) )) " )
1237+ case . bool:
1238+ bodyLines. append ( " _swift_js_push_int(__bjs_unwrapped_ \( paramName) ? 1 : 0) " )
1239+ case . float:
1240+ bodyLines. append ( " _swift_js_push_f32(__bjs_unwrapped_ \( paramName) ) " )
1241+ case . double:
1242+ bodyLines. append ( " _swift_js_push_f64(__bjs_unwrapped_ \( paramName) ) " )
1243+ default :
1244+ bodyLines. append (
1245+ " preconditionFailure( \" BridgeJS: unsupported optional wrapped type in generated code \" ) "
1246+ )
1247+ }
1248+ bodyLines. append ( " } " )
1249+ bodyLines. append ( " _swift_js_push_int(__bjs_isSome_ \( paramName) ? 1 : 0) " )
11991250 default :
12001251 bodyLines. append (
12011252 " preconditionFailure( \" BridgeJS: unsupported associated value type in generated code \" ) "
@@ -1406,55 +1457,24 @@ extension AttributeListSyntax {
14061457}
14071458
14081459extension BridgeType {
1409- // This initializer is primarily for string-based type descriptions,
1410- // especially for internal and raw type lookups.
1411- // For full SwiftSyntax based parsing, `ExportSwift.lookupType(for:)` should be used.
14121460 init ? ( swiftType: String ) {
1413- // Use SwiftSyntax to parse the string into a TypeSyntax for robust optional detection
1414- let typeSyntax = TypeSyntax ( stringLiteral: swiftType)
1415-
1416- // 1. Handle T? syntax (OptionalTypeSyntax)
1417- if let optionalType = typeSyntax. as ( OptionalTypeSyntax . self) {
1418- let wrappedTypeString = optionalType. wrappedType. trimmedDescription
1419- if let baseType = BridgeType ( swiftType: wrappedTypeString) {
1420- self = . optional( baseType)
1421- return
1422- }
1423- }
1424-
1425- // 2. Handle Optional<T> syntax (IdentifierTypeSyntax with generic arguments)
1426- if let identifierType = typeSyntax. as ( IdentifierTypeSyntax . self) ,
1427- identifierType. name. text == " Optional " ,
1428- let genericArgs = identifierType. genericArgumentClause? . arguments,
1429- genericArgs. count == 1 ,
1430- let argType = genericArgs. first? . argument {
1431- let innerTypeString = argType. trimmedDescription
1432- if let baseType = BridgeType ( swiftType: innerTypeString) {
1433- self = . optional( baseType)
1434- return
1435- }
1436- }
1437-
1438- // Fallback to primitive type handling if not an optional
1439- if let primitive = BridgeType . primitive ( swiftType: swiftType) {
1440- self = primitive
1441- return
1442- }
1443-
1444- return nil
1445- }
1446-
1447- // Helper for direct primitive type mapping (used by init? and elsewhere)
1448- fileprivate static func primitive( swiftType: String ) -> BridgeType ? {
14491461 switch swiftType {
1450- case " Int " : return . int
1451- case " Float " : return . float
1452- case " Double " : return . double
1453- case " String " : return . string
1454- case " Bool " : return . bool
1455- case " Void " : return . void
1456- case " JSObject " : return . jsObject( nil )
1457- default : return nil
1462+ case " Int " :
1463+ self = . int
1464+ case " Float " :
1465+ self = . float
1466+ case " Double " :
1467+ self = . double
1468+ case " String " :
1469+ self = . string
1470+ case " Bool " :
1471+ self = . bool
1472+ case " Void " :
1473+ self = . void
1474+ case " JSObject " :
1475+ self = . jsObject( nil )
1476+ default :
1477+ return nil
14581478 }
14591479 }
14601480}
@@ -1507,7 +1527,6 @@ extension BridgeType {
15071527 ( " caseId " , . i32)
15081528 ] )
15091529 }
1510-
15111530
15121531 func liftParameterInfo( ) throws -> LiftingIntrinsicInfo {
15131532 switch self {
@@ -1589,7 +1608,7 @@ extension BridgeType {
15891608 case . associatedValueEnum:
15901609 return . associatedValueEnum
15911610 case . namespaceEnum:
1592- throw BridgeJSCoreError ( " Namespace enums are not supported as return types " )
1611+ throw BridgeJSCoreError ( " Namespace enums are not supported to pass as parameters " )
15931612 }
15941613 }
15951614}
0 commit comments