1313//===----------------------------------------------------------------------===//
1414
1515import JavaTypes
16+ import JavaKitConfigurationShared
1617
1718extension FFMSwift2JavaGenerator {
1819 func translatedDecl(
@@ -24,7 +25,7 @@ extension FFMSwift2JavaGenerator {
2425
2526 let translated : TranslatedFunctionDecl ?
2627 do {
27- let translation = JavaTranslation ( symbolTable: self . symbolTable)
28+ let translation = JavaTranslation ( config : self . config , symbolTable: self . symbolTable)
2829 translated = try translation. translate ( decl)
2930 } catch {
3031 self . log. info ( " Failed to translate: ' \( decl. swiftDecl. qualifiedNameForDebug) '; \( error) " )
@@ -52,6 +53,9 @@ extension FFMSwift2JavaGenerator {
5253 /// Java type that represents the Swift result type.
5354 var javaResultType : JavaType
5455
56+ /// Java annotations that should be propagated from the result type onto the method
57+ var annotations : [ JavaAnnotation ] = [ ]
58+
5559 /// Required indirect return receivers for receiving the result.
5660 ///
5761 /// 'JavaParameter.name' is the suffix for the receiver variable names. For example
@@ -85,15 +89,32 @@ extension FFMSwift2JavaGenerator {
8589 /// Function signature.
8690 let translatedSignature : TranslatedFunctionSignature
8791
88- /// Cdecl lowerd signature.
92+ /// Cdecl lowered signature.
8993 let loweredSignature : LoweredFunctionSignature
94+
95+ /// Annotations to include on the Java function declaration
96+ var annotations : [ JavaAnnotation ] {
97+ self . translatedSignature. annotations
98+ }
9099 }
91100
92101 /// Function signature for a Java API.
93102 struct TranslatedFunctionSignature {
94103 var selfParameter : TranslatedParameter ?
104+ var annotations : [ JavaAnnotation ] = [ ]
95105 var parameters : [ TranslatedParameter ]
96106 var result : TranslatedResult
107+
108+ init ( selfParameter: TranslatedParameter ? ,
109+ parameters: [ TranslatedParameter ] ,
110+ result: TranslatedResult ) {
111+ self . selfParameter = selfParameter
112+ // if the result type implied any annotations,
113+ // propagate them onto the function the result is returned from
114+ self . annotations = result. annotations
115+ self . parameters = parameters
116+ self . result = result
117+ }
97118 }
98119
99120 /// Represent a Swift closure type in the user facing Java API.
@@ -113,9 +134,11 @@ extension FFMSwift2JavaGenerator {
113134 }
114135
115136 struct JavaTranslation {
137+ let config : Configuration
116138 var knownTypes : SwiftKnownTypes
117139
118- init ( symbolTable: SwiftSymbolTable ) {
140+ init ( config: Configuration , symbolTable: SwiftSymbolTable ) {
141+ self . config = config
119142 self . knownTypes = SwiftKnownTypes ( symbolTable: symbolTable)
120143 }
121144
@@ -299,21 +322,27 @@ extension FFMSwift2JavaGenerator {
299322 ) throws -> TranslatedParameter {
300323
301324 // If we need to handle unsigned integers "safely" do so here
302- if let unsignedWrapperType = JavaType . unsignedWrapper ( for: swiftType) /* and we're in safe wrapper mode */ {
303- return TranslatedParameter (
304- javaParameters: [
305- JavaParameter ( name: parameterName, type: unsignedWrapperType)
306- ] , conversion: . call( . placeholder, function: " UnsignedNumbers.toPrimitive " , withArena: false ) )
325+ if config. unsignedNumbersMode. needsConversion {
326+ if let unsignedWrapperType = JavaType . unsignedWrapper ( for: swiftType) /* and we're in safe wrapper mode */ {
327+ return TranslatedParameter (
328+ javaParameters: [
329+ JavaParameter ( name: parameterName, type: unsignedWrapperType)
330+ ] , conversion: . call( . placeholder, function: " UnsignedNumbers.toPrimitive " , withArena: false ) )
331+ }
307332 }
308333
334+ // If the result type should cause any annotations on the method, include them here.
335+ let parameterAnnotations : [ JavaAnnotation ] = getTypeAnnotations ( swiftType: swiftType)
336+
309337 // If there is a 1:1 mapping between this Swift type and a C type, that can
310338 // be expressed as a Java primitive type.
311339 if let cType = try ? CType ( cdeclType: swiftType) {
312340 let javaType = cType. javaType
313341 return TranslatedParameter (
314342 javaParameters: [
315343 JavaParameter (
316- name: parameterName, type: javaType
344+ name: parameterName, type: javaType,
345+ annotations: parameterAnnotations
317346 )
318347 ] ,
319348 conversion: . placeholder
@@ -326,7 +355,10 @@ extension FFMSwift2JavaGenerator {
326355 return TranslatedParameter (
327356 javaParameters: [
328357 JavaParameter (
329- name: parameterName, type: JavaType . class ( package : " org.swift.swiftkit.ffm " , name: " SwiftAnyType " ) )
358+ name: parameterName,
359+ type: JavaType . class ( package : " org.swift.swiftkit.ffm " , name: " SwiftAnyType " ) ,
360+ annotations: parameterAnnotations
361+ )
330362 ] ,
331363 conversion: . swiftValueSelfSegment( . placeholder)
332364 )
@@ -505,7 +537,22 @@ extension FFMSwift2JavaGenerator {
505537 }
506538 }
507539
508- func unsignedResultConversion( _ from: SwiftType , to javaType: JavaType ) -> JavaConversionStep {
540+ /// Determine if the given type needs any extra annotations that should be included
541+ /// in Java sources when the corresponding Java type is rendered.
542+ func getTypeAnnotations( swiftType: SwiftType ) -> [ JavaAnnotation ] {
543+ if swiftType. isUnsignedInteger, config. unsignedNumbersMode == . annotate {
544+ return [ JavaAnnotation . unsigned]
545+ }
546+
547+ return [ ]
548+ }
549+
550+ func unsignedResultConversion( _ from: SwiftType , to javaType: JavaType ,
551+ mode: JExtractUnsignedIntegerMode ) -> JavaConversionStep {
552+ guard mode == . wrap else {
553+ return . placeholder
554+ }
555+
509556 guard let className = javaType. className else {
510557 fatalError ( " Missing target class name for result conversion step from \( from) to \( javaType) " )
511558 }
@@ -537,20 +584,28 @@ extension FFMSwift2JavaGenerator {
537584 let swiftType = swiftResult. type
538585
539586 // If we need to handle unsigned integers "safely" do so here
540- if let unsignedWrapperType = JavaType . unsignedWrapper ( for: swiftType) /* and we're in safe wrapper mode */ {
541- return TranslatedResult (
542- javaResultType: unsignedWrapperType,
543- outParameters: [ ] ,
544- conversion: unsignedResultConversion ( swiftType, to: unsignedWrapperType)
545- )
587+ if config. unsignedNumbersMode. needsConversion {
588+ if let unsignedWrapperType = JavaType . unsignedWrapper ( for: swiftType) /* and we're in safe wrapper mode */ {
589+ return TranslatedResult (
590+ javaResultType: unsignedWrapperType,
591+ outParameters: [ ] ,
592+ conversion: unsignedResultConversion (
593+ swiftType, to: unsignedWrapperType,
594+ mode: self . config. unsignedNumbersMode)
595+ )
596+ }
546597 }
547598
599+ // If the result type should cause any annotations on the method, include them here.
600+ let resultAnnotations : [ JavaAnnotation ] = getTypeAnnotations ( swiftType: swiftType)
601+
548602 // If there is a 1:1 mapping between this Swift type and a C type, that can
549603 // be expressed as a Java primitive type.
550604 if let cType = try ? CType ( cdeclType: swiftType) {
551605 let javaType = cType. javaType
552606 return TranslatedResult (
553607 javaResultType: javaType,
608+ annotations: resultAnnotations,
554609 outParameters: [ ] ,
555610 conversion: . placeholder
556611 )
@@ -562,6 +617,7 @@ extension FFMSwift2JavaGenerator {
562617 let javaType = JavaType . class ( package : " org.swift.swiftkit.ffm " , name: " SwiftAnyType " )
563618 return TranslatedResult (
564619 javaResultType: javaType,
620+ annotations: resultAnnotations,
565621 outParameters: [ ] ,
566622 conversion: . construct( . placeholder, javaType)
567623 )
@@ -572,6 +628,7 @@ extension FFMSwift2JavaGenerator {
572628 case . unsafeRawBufferPointer, . unsafeMutableRawBufferPointer:
573629 return TranslatedResult (
574630 javaResultType: . javaForeignMemorySegment,
631+ annotations: resultAnnotations,
575632 outParameters: [
576633 JavaParameter ( name: " pointer " , type: . javaForeignMemorySegment) ,
577634 JavaParameter ( name: " count " , type: . long) ,
@@ -611,6 +668,7 @@ extension FFMSwift2JavaGenerator {
611668 let javaType : JavaType = . class( package : nil , name: swiftNominalType. nominalTypeDecl. name)
612669 return TranslatedResult (
613670 javaResultType: javaType,
671+ annotations: resultAnnotations,
614672 outParameters: [
615673 JavaParameter ( name: " " , type: javaType)
616674 ] ,
@@ -716,7 +774,7 @@ extension CType {
716774 case . integral( . signed( bits: 32 ) ) : return . int
717775 case . integral( . signed( bits: 64 ) ) : return . long
718776 case . integral( . unsigned( bits: 8 ) ) : return . byte
719- case . integral( . unsigned( bits: 16 ) ) : return . short
777+ case . integral( . unsigned( bits: 16 ) ) : return . char // char is Java's only unsigned primitive, we can use it!
720778 case . integral( . unsigned( bits: 32 ) ) : return . int
721779 case . integral( . unsigned( bits: 64 ) ) : return . long
722780
0 commit comments