@@ -142,7 +142,7 @@ public class ExportSwift {
142
142
hint: " Only primitive types and types defined in the same module are allowed "
143
143
)
144
144
}
145
-
145
+
146
146
private func diagnoseNestedOptional( node: some SyntaxProtocol , type: String ) {
147
147
diagnose (
148
148
node: node,
@@ -192,30 +192,30 @@ public class ExportSwift {
192
192
var parameters : [ Parameter ] = [ ]
193
193
for param in node. signature. parameterClause. parameters {
194
194
let resolvedType = self . parent. lookupType ( for: param. type)
195
-
195
+
196
196
if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
197
197
diagnoseNestedOptional ( node: param. type, type: param. type. trimmedDescription)
198
198
continue
199
199
}
200
-
200
+
201
201
guard let type = resolvedType else {
202
202
diagnoseUnsupportedType ( node: param. type, type: param. type. trimmedDescription)
203
203
continue
204
204
}
205
-
205
+
206
206
let name = param. secondName? . text ?? param. firstName. text
207
207
let label = param. firstName. text
208
208
parameters. append ( Parameter ( label: label, name: name, type: type) )
209
209
}
210
210
let returnType : BridgeType
211
211
if let returnClause = node. signature. returnClause {
212
212
let resolvedType = self . parent. lookupType ( for: returnClause. type)
213
-
213
+
214
214
if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
215
215
diagnoseNestedOptional ( node: returnClause. type, type: returnClause. type. trimmedDescription)
216
216
return nil
217
217
}
218
-
218
+
219
219
guard let type = resolvedType else {
220
220
diagnoseUnsupportedType ( node: returnClause. type, type: returnClause. type. trimmedDescription)
221
221
return nil
@@ -561,12 +561,24 @@ public class ExportSwift {
561
561
switch associatedValue. type {
562
562
case . string, . int, . float, . double, . bool:
563
563
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
+ }
564
576
default :
565
577
diagnose (
566
578
node: node,
567
579
message: " Unsupported associated value type: \( associatedValue. type. swiftType) " ,
568
580
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 "
570
582
)
571
583
}
572
584
}
@@ -744,22 +756,24 @@ public class ExportSwift {
744
756
}
745
757
// Optional<T>
746
758
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
+ {
751
764
if let baseType = lookupType ( for: argType) {
752
765
return . optional( baseType)
753
766
}
754
767
}
755
768
// Swift.Optional<T>
756
769
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
+ {
763
777
if let wrappedType = lookupType ( for: argType) {
764
778
return . optional( wrappedType)
765
779
}
@@ -771,7 +785,7 @@ public class ExportSwift {
771
785
}
772
786
773
787
let typeName = type. trimmedDescription
774
- if let primitiveType = BridgeType . primitive ( swiftType: typeName) {
788
+ if let primitiveType = BridgeType ( swiftType: typeName) {
775
789
return primitiveType
776
790
}
777
791
@@ -890,15 +904,15 @@ public class ExportSwift {
890
904
} else {
891
905
argumentsToLift = liftingInfo. parameters. map { ( name, _) in param. name + name. capitalizedFirstLetter }
892
906
}
893
-
907
+
894
908
let typeNameForIntrinsic : String
895
909
switch param. type {
896
910
case . optional( let wrappedType) :
897
911
typeNameForIntrinsic = " Optional< \( wrappedType. swiftType) > "
898
912
default :
899
913
typeNameForIntrinsic = param. type. swiftType
900
914
}
901
-
915
+
902
916
liftedParameterExprs. append (
903
917
ExprSyntax (
904
918
" \( raw: typeNameForIntrinsic) .bridgeJSLiftParameter( \( raw: argumentsToLift. joined ( separator: " , " ) ) ) "
@@ -996,11 +1010,6 @@ public class ExportSwift {
996
1010
return
997
1011
}
998
1012
999
- if case . optional( _) = returnType {
1000
- append ( " return ret.bridgeJSLowerReturn() " )
1001
- return
1002
- }
1003
-
1004
1013
append ( " return ret.bridgeJSLowerReturn() " )
1005
1014
}
1006
1015
@@ -1158,8 +1167,26 @@ public class ExportSwift {
1158
1167
return " \( paramName) Float.bridgeJSLiftParameter(_swift_js_pop_param_f32()) "
1159
1168
case . double:
1160
1169
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
+ }
1163
1190
default :
1164
1191
return " \( paramName) Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) "
1165
1192
}
@@ -1196,6 +1223,30 @@ public class ExportSwift {
1196
1223
bodyLines. append ( " _swift_js_push_f32( \( paramName) ) " )
1197
1224
case . double:
1198
1225
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) " )
1199
1250
default :
1200
1251
bodyLines. append (
1201
1252
" preconditionFailure( \" BridgeJS: unsupported associated value type in generated code \" ) "
@@ -1406,55 +1457,24 @@ extension AttributeListSyntax {
1406
1457
}
1407
1458
1408
1459
extension 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.
1412
1460
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 ? {
1449
1461
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
1458
1478
}
1459
1479
}
1460
1480
}
@@ -1507,7 +1527,6 @@ extension BridgeType {
1507
1527
( " caseId " , . i32)
1508
1528
] )
1509
1529
}
1510
-
1511
1530
1512
1531
func liftParameterInfo( ) throws -> LiftingIntrinsicInfo {
1513
1532
switch self {
@@ -1589,7 +1608,7 @@ extension BridgeType {
1589
1608
case . associatedValueEnum:
1590
1609
return . associatedValueEnum
1591
1610
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 " )
1593
1612
}
1594
1613
}
1595
1614
}
0 commit comments