@@ -277,14 +277,11 @@ public class ExportSwift {
277277
278278 switch state {
279279 case . topLevel:
280- abiName = " bjs_ \( name) "
281280 staticContext = nil
282281 case . classBody( let className, _) :
283282 if isStatic {
284- abiName = " bjs_ \( className) _static_ \( name) "
285283 staticContext = . className( className)
286284 } else {
287- abiName = " bjs_ \( className) _ \( name) "
288285 staticContext = nil
289286 }
290287 case . enumBody( let enumName, let enumKey) :
@@ -295,16 +292,21 @@ public class ExportSwift {
295292
296293 let isNamespaceEnum = exportedEnumByName [ enumKey] ? . cases. isEmpty ?? true
297294 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- }
307295 }
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+ )
308310
309311 guard let effects = collectEffects ( signature: node. signature, isStatic: isStatic) else {
310312 return nil
@@ -316,7 +318,7 @@ public class ExportSwift {
316318 parameters: parameters,
317319 returnType: returnType,
318320 effects: effects,
319- namespace: finalNamespace, // UPDATED: Use resolved namespace
321+ namespace: finalNamespace,
320322 staticContext: staticContext
321323 )
322324 }
@@ -991,50 +993,7 @@ public class ExportSwift {
991993 }
992994
993995 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) ) )
1038997 }
1039998 }
1040999
@@ -1141,7 +1100,7 @@ public class ExportSwift {
11411100
11421101 func callStaticProperty( name: String , returnType: BridgeType ) {
11431102 if returnType == . void {
1144- append ( " let ret = \( raw: name) " )
1103+ append ( " \( raw: name) " )
11451104 } else {
11461105 append ( " let ret = \( raw: name) " )
11471106 }
@@ -1450,6 +1409,83 @@ public class ExportSwift {
14501409 return cases
14511410 }
14521411 }
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+ 14531489
14541490 func renderSingleExportedFunction( function: ExportedFunction ) throws -> DeclSyntax {
14551491 let builder = ExportedThunkBuilder ( effects: function. effects)
@@ -1460,16 +1496,12 @@ public class ExportSwift {
14601496 if function. effects. isStatic, let staticContext = function. staticContext {
14611497 let callName : String
14621498 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) "
14671501 case . namespaceEnum:
1468- // For namespace enums and explicit namespace, use the namespace property
14691502 if let namespace = function. namespace, !namespace. isEmpty {
14701503 callName = " \( namespace. joined ( separator: " . " ) ) . \( function. name) "
14711504 } else {
1472- // Fallback to just the function name for functions without namespace
14731505 callName = function. name
14741506 }
14751507 }
@@ -1569,60 +1601,9 @@ public class ExportSwift {
15691601 // Generate property getters and setters
15701602 for property in klass. properties {
15711603 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) ) )
15961605 } 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) ) )
16261607 }
16271608 }
16281609
0 commit comments