@@ -277,14 +277,11 @@ public class ExportSwift {
277
277
278
278
switch state {
279
279
case . topLevel:
280
- abiName = " bjs_ \( name) "
281
280
staticContext = nil
282
281
case . classBody( let className, _) :
283
282
if isStatic {
284
- abiName = " bjs_ \( className) _static_ \( name) "
285
283
staticContext = . className( className)
286
284
} else {
287
- abiName = " bjs_ \( className) _ \( name) "
288
285
staticContext = nil
289
286
}
290
287
case . enumBody( let enumName, let enumKey) :
@@ -295,16 +292,21 @@ public class ExportSwift {
295
292
296
293
let isNamespaceEnum = exportedEnumByName [ enumKey] ? . cases. isEmpty ?? true
297
294
staticContext = isNamespaceEnum ? . namespaceEnum : . enumName( enumName)
298
-
299
- if isNamespaceEnum, let namespace = finalNamespace, !namespace. isEmpty {
300
- // For namespace enums, use ONLY the resolved namespace to avoid duplication
301
- // The finalNamespace already contains the correct namespace path
302
- let abiNamespace = namespace. joined ( separator: " _ " )
303
- abiName = " bjs_ \( abiNamespace) _static_ \( name) "
304
- } else {
305
- abiName = " bjs_ \( enumName) _static_ \( name) "
306
- }
307
295
}
296
+
297
+ let classNameForABI : String ?
298
+ if case . classBody( let className, _) = state {
299
+ classNameForABI = className
300
+ } else {
301
+ classNameForABI = nil
302
+ }
303
+ abiName = ABINameGenerator . generateABIName (
304
+ baseName: name,
305
+ namespace: finalNamespace,
306
+ staticContext: isStatic ? staticContext : nil ,
307
+ operation: nil ,
308
+ className: classNameForABI
309
+ )
308
310
309
311
guard let effects = collectEffects ( signature: node. signature, isStatic: isStatic) else {
310
312
return nil
@@ -316,7 +318,7 @@ public class ExportSwift {
316
318
parameters: parameters,
317
319
returnType: returnType,
318
320
effects: effects,
319
- namespace: finalNamespace, // UPDATED: Use resolved namespace
321
+ namespace: finalNamespace,
320
322
staticContext: staticContext
321
323
)
322
324
}
@@ -991,50 +993,7 @@ public class ExportSwift {
991
993
}
992
994
993
995
for staticProperty in enumDef. staticProperties {
994
- let getterBuilder = ExportedThunkBuilder (
995
- effects: Effects ( isAsync: false , isThrows: false , isStatic: true )
996
- )
997
-
998
- // Use context-aware call name based on static context and namespace
999
- let staticCallName : String
1000
- if let staticContext = staticProperty. staticContext {
1001
- switch staticContext {
1002
- case . className( let className) :
1003
- staticCallName = " \( className) . \( staticProperty. name) "
1004
- case . enumName( let enumName) :
1005
- staticCallName = " \( enumName) . \( staticProperty. name) "
1006
- case . namespaceEnum:
1007
- // For namespace enums and explicit namespace, use the namespace property
1008
- if let namespace = staticProperty. namespace, !namespace. isEmpty {
1009
- let namespacePath = namespace. joined ( separator: " . " )
1010
- staticCallName = " \( namespacePath) . \( staticProperty. name) "
1011
- } else {
1012
- // Fallback to using the enum's swift call name
1013
- staticCallName = " \( enumDef. swiftCallName) . \( staticProperty. name) "
1014
- }
1015
- }
1016
- } else {
1017
- staticCallName = " \( enumDef. swiftCallName) . \( staticProperty. name) "
1018
- }
1019
-
1020
- getterBuilder. callStaticProperty ( name: staticCallName, returnType: staticProperty. type)
1021
- try getterBuilder. lowerReturnValue ( returnType: staticProperty. type)
1022
- decls. append ( getterBuilder. render ( abiName: staticProperty. getterAbiName ( className: enumDef. name) ) )
1023
-
1024
- if !staticProperty. isReadonly {
1025
- let setterBuilder = ExportedThunkBuilder (
1026
- effects: Effects ( isAsync: false , isThrows: false , isStatic: true )
1027
- )
1028
- try setterBuilder. liftParameter (
1029
- param: Parameter ( label: " value " , name: " value " , type: staticProperty. type)
1030
- )
1031
- setterBuilder. callStaticPropertySetter (
1032
- klassName: staticCallName. components ( separatedBy: " . " ) . dropLast ( ) . joined ( separator: " . " ) ,
1033
- propertyName: staticProperty. name
1034
- )
1035
- try setterBuilder. lowerReturnValue ( returnType: . void)
1036
- decls. append ( setterBuilder. render ( abiName: staticProperty. setterAbiName ( className: enumDef. name) ) )
1037
- }
996
+ decls. append ( contentsOf: try renderSingleExportedProperty ( property: staticProperty, context: . enumStatic( enumDef: enumDef) ) )
1038
997
}
1039
998
}
1040
999
@@ -1141,7 +1100,7 @@ public class ExportSwift {
1141
1100
1142
1101
func callStaticProperty( name: String , returnType: BridgeType ) {
1143
1102
if returnType == . void {
1144
- append ( " let ret = \( raw: name) " )
1103
+ append ( " \( raw: name) " )
1145
1104
} else {
1146
1105
append ( " let ret = \( raw: name) " )
1147
1106
}
@@ -1450,6 +1409,83 @@ public class ExportSwift {
1450
1409
return cases
1451
1410
}
1452
1411
}
1412
+
1413
+ /// Context for property rendering that determines call behavior and ABI generation
1414
+ private enum PropertyRenderingContext {
1415
+ case enumStatic( enumDef: ExportedEnum )
1416
+ case classStatic( klass: ExportedClass )
1417
+ case classInstance( klass: ExportedClass )
1418
+ }
1419
+
1420
+ /// Renders getter and setter Swift thunk code for a property in any context
1421
+ /// This unified function eliminates duplication between enum static, class static, and class instance property rendering
1422
+ private func renderSingleExportedProperty( property: ExportedProperty , context: PropertyRenderingContext ) throws -> [ DeclSyntax ] {
1423
+ var decls : [ DeclSyntax ] = [ ]
1424
+
1425
+ let ( callName, className, isStatic) : ( String , String , Bool )
1426
+ switch context {
1427
+ case . enumStatic( let enumDef) :
1428
+ callName = property. callName ( prefix: enumDef. swiftCallName)
1429
+ className = enumDef. name
1430
+ isStatic = true
1431
+ case . classStatic( let klass) :
1432
+ callName = property. callName ( )
1433
+ className = klass. name
1434
+ isStatic = true
1435
+
1436
+ case . classInstance( let klass) :
1437
+ callName = property. callName ( )
1438
+ className = klass. name
1439
+ isStatic = false
1440
+ }
1441
+
1442
+ let getterBuilder = ExportedThunkBuilder ( effects: Effects ( isAsync: false , isThrows: false , isStatic: isStatic) )
1443
+
1444
+ if !isStatic {
1445
+ try getterBuilder. liftParameter (
1446
+ param: Parameter ( label: nil , name: " _self " , type: . swiftHeapObject( className) )
1447
+ )
1448
+ }
1449
+
1450
+ if isStatic {
1451
+ getterBuilder. callStaticProperty ( name: callName, returnType: property. type)
1452
+ } else {
1453
+ getterBuilder. callPropertyGetter ( klassName: className, propertyName: callName, returnType: property. type)
1454
+ }
1455
+
1456
+ try getterBuilder. lowerReturnValue ( returnType: property. type)
1457
+ decls. append ( getterBuilder. render ( abiName: property. getterAbiName ( className: className) ) )
1458
+
1459
+ // Generate property setter if not readonly
1460
+ if !property. isReadonly {
1461
+ let setterBuilder = ExportedThunkBuilder ( effects: Effects ( isAsync: false , isThrows: false , isStatic: isStatic) )
1462
+
1463
+ // Lift parameters based on property type
1464
+ if !isStatic {
1465
+ // Instance properties need _self parameter
1466
+ try setterBuilder. liftParameter (
1467
+ param: Parameter ( label: nil , name: " _self " , type: . swiftHeapObject( className) )
1468
+ )
1469
+ }
1470
+
1471
+ try setterBuilder. liftParameter (
1472
+ param: Parameter ( label: " value " , name: " value " , type: property. type)
1473
+ )
1474
+
1475
+ if isStatic {
1476
+ let klassName = callName. components ( separatedBy: " . " ) . dropLast ( ) . joined ( separator: " . " )
1477
+ setterBuilder. callStaticPropertySetter ( klassName: klassName, propertyName: property. name)
1478
+ } else {
1479
+ setterBuilder. callPropertySetter ( klassName: className, propertyName: callName)
1480
+ }
1481
+
1482
+ try setterBuilder. lowerReturnValue ( returnType: . void)
1483
+ decls. append ( setterBuilder. render ( abiName: property. setterAbiName ( className: className) ) )
1484
+ }
1485
+
1486
+ return decls
1487
+ }
1488
+
1453
1489
1454
1490
func renderSingleExportedFunction( function: ExportedFunction ) throws -> DeclSyntax {
1455
1491
let builder = ExportedThunkBuilder ( effects: function. effects)
@@ -1460,16 +1496,12 @@ public class ExportSwift {
1460
1496
if function. effects. isStatic, let staticContext = function. staticContext {
1461
1497
let callName : String
1462
1498
switch staticContext {
1463
- case . className( let className) :
1464
- callName = " \( className) . \( function. name) "
1465
- case . enumName( let enumName) :
1466
- callName = " \( enumName) . \( function. name) "
1499
+ case . className( let baseName) , . enumName( let baseName) :
1500
+ callName = " \( baseName) . \( function. name) "
1467
1501
case . namespaceEnum:
1468
- // For namespace enums and explicit namespace, use the namespace property
1469
1502
if let namespace = function. namespace, !namespace. isEmpty {
1470
1503
callName = " \( namespace. joined ( separator: " . " ) ) . \( function. name) "
1471
1504
} else {
1472
- // Fallback to just the function name for functions without namespace
1473
1505
callName = function. name
1474
1506
}
1475
1507
}
@@ -1569,60 +1601,9 @@ public class ExportSwift {
1569
1601
// Generate property getters and setters
1570
1602
for property in klass. properties {
1571
1603
if property. isStatic {
1572
- // Generate static property getter
1573
- let getterBuilder = ExportedThunkBuilder (
1574
- effects: Effects ( isAsync: false , isThrows: false , isStatic: true )
1575
- )
1576
- let staticCallName = " \( klass. swiftCallName) . \( property. name) "
1577
- getterBuilder. callStaticProperty ( name: staticCallName, returnType: property. type)
1578
- try getterBuilder. lowerReturnValue ( returnType: property. type)
1579
- decls. append ( getterBuilder. render ( abiName: property. getterAbiName ( className: klass. name) ) )
1580
-
1581
- // Generate static property setter if not readonly
1582
- if !property. isReadonly {
1583
- let setterBuilder = ExportedThunkBuilder (
1584
- effects: Effects ( isAsync: false , isThrows: false , isStatic: true )
1585
- )
1586
- try setterBuilder. liftParameter (
1587
- param: Parameter ( label: " value " , name: " value " , type: property. type)
1588
- )
1589
- setterBuilder. callStaticPropertySetter (
1590
- klassName: klass. swiftCallName,
1591
- propertyName: property. name
1592
- )
1593
- try setterBuilder. lowerReturnValue ( returnType: . void)
1594
- decls. append ( setterBuilder. render ( abiName: property. setterAbiName ( className: klass. name) ) )
1595
- }
1604
+ decls. append ( contentsOf: try renderSingleExportedProperty ( property: property, context: . classStatic( klass: klass) ) )
1596
1605
} else {
1597
- // Generate instance property getter
1598
- let getterBuilder = ExportedThunkBuilder ( effects: Effects ( isAsync: false , isThrows: false ) )
1599
- try getterBuilder. liftParameter (
1600
- param: Parameter ( label: nil , name: " _self " , type: . swiftHeapObject( klass. name) )
1601
- )
1602
- getterBuilder. callPropertyGetter (
1603
- klassName: klass. name,
1604
- propertyName: property. name,
1605
- returnType: property. type
1606
- )
1607
- try getterBuilder. lowerReturnValue ( returnType: property. type)
1608
- decls. append ( getterBuilder. render ( abiName: property. getterAbiName ( className: klass. name) ) )
1609
-
1610
- // Generate instance property setter if not readonly
1611
- if !property. isReadonly {
1612
- let setterBuilder = ExportedThunkBuilder ( effects: Effects ( isAsync: false , isThrows: false ) )
1613
- try setterBuilder. liftParameter (
1614
- param: Parameter ( label: nil , name: " _self " , type: . swiftHeapObject( klass. name) )
1615
- )
1616
- try setterBuilder. liftParameter (
1617
- param: Parameter ( label: " value " , name: " value " , type: property. type)
1618
- )
1619
- setterBuilder. callPropertySetter (
1620
- klassName: klass. name,
1621
- propertyName: property. name
1622
- )
1623
- try setterBuilder. lowerReturnValue ( returnType: . void)
1624
- decls. append ( setterBuilder. render ( abiName: property. setterAbiName ( className: klass. name) ) )
1625
- }
1606
+ decls. append ( contentsOf: try renderSingleExportedProperty ( property: property, context: . classInstance( klass: klass) ) )
1626
1607
}
1627
1608
}
1628
1609
0 commit comments