Skip to content

Commit de257ec

Browse files
authored
jextract/jni: Add nativeJavaType to TranslatedResult for explicit type handling (#722)
* Add nativeJavaType to TranslatedResult * Rename and unuse SwiftResult # Conflicts: # Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift * Remove unused conversion * More accurate direct result comversion
1 parent d43959d commit de257ec

5 files changed

Lines changed: 78 additions & 71 deletions

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ extension JNISwift2JavaGenerator {
660660
}
661661

662662
let translatedSignature = translatedDecl.translatedFunctionSignature
663-
let resultType = translatedSignature.resultType.javaType
663+
let resultType = translatedSignature.result.javaType
664664
var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() }
665665
let throwsClause = translatedDecl.throwsClause()
666666

@@ -714,7 +714,7 @@ extension JNISwift2JavaGenerator {
714714
let globalArenaName = "SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA"
715715
let arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.name) + [globalArenaName]
716716
let call = "\(translatedDecl.name)(\(arguments.joined(separator: ", ")))"
717-
if translatedDecl.translatedFunctionSignature.resultType.javaType.isVoid {
717+
if translatedDecl.translatedFunctionSignature.result.javaType.isVoid {
718718
printer.print("\(call);")
719719
} else {
720720
printer.print("return \(call);")
@@ -792,7 +792,7 @@ extension JNISwift2JavaGenerator {
792792
}
793793

794794
// Indirect return receivers
795-
for outParameter in translatedFunctionSignature.resultType.outParameters {
795+
for outParameter in translatedFunctionSignature.result.outParameters {
796796
printer.print(
797797
"\(outParameter.type) \(outParameter.name) = \(outParameter.allocation.render(type: outParameter.type));"
798798
)
@@ -807,15 +807,15 @@ extension JNISwift2JavaGenerator {
807807
"\(effectiveParentName.fullName).\(translatedDecl.nativeFunctionName)(\(arguments.joined(separator: ", ")))"
808808

809809
//=== Part 4: Convert the return value.
810-
if translatedFunctionSignature.resultType.javaType.isVoid {
810+
if translatedFunctionSignature.result.javaType.isVoid {
811811
printer.print("\(downcall);")
812812
} else {
813813
let result: String
814814
if translatedDecl.nativeFunctionSignature.result.javaType.isVoid {
815815
printer.print("\(downcall);")
816-
result = translatedFunctionSignature.resultType.conversion.render(&printer, "")
816+
result = translatedFunctionSignature.result.conversion.render(&printer, "")
817817
} else {
818-
result = translatedFunctionSignature.resultType.conversion.render(&printer, downcall)
818+
result = translatedFunctionSignature.result.conversion.render(&printer, downcall)
819819
}
820820
printer.print("return \(result);")
821821
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,20 @@ extension JNISwift2JavaGenerator {
117117

118118
let conversions = try enumCase.parameters.enumerated().map { idx, parameter in
119119
let resultName = parameter.name ?? "arg\(idx)"
120-
let result = SwiftResult(convention: .direct, type: parameter.type)
121-
var translatedResult = try self.translate(swiftResult: result, methodName: methodName, resultName: resultName)
120+
var translatedResult = try self.translateResult(
121+
swiftType: parameter.type,
122+
methodName: methodName,
123+
resultName: resultName
124+
)
122125
translatedResult.conversion = .replacingPlaceholder(
123126
translatedResult.conversion,
124127
placeholder: "$nativeParameters.\(resultName)",
125128
)
126-
let nativeResult = try nativeTranslation.translate(swiftResult: result, methodName: methodName, resultName: resultName)
129+
let nativeResult = try nativeTranslation.translateResult(
130+
swiftType: parameter.type,
131+
methodName: methodName,
132+
resultName: resultName
133+
)
127134
return (translated: translatedResult, native: nativeResult)
128135
}
129136

@@ -179,8 +186,9 @@ extension JNISwift2JavaGenerator {
179186
conversion: .typeMetadataAddress(.placeholder),
180187
),
181188
parameters: [],
182-
resultType: TranslatedResult(
189+
result: TranslatedResult(
183190
javaType: .optional(caseType),
191+
nativeJavaType: nativeParametersType,
184192
outParameters: conversions.flatMap(\.translated.outParameters),
185193
conversion: enumCase.parameters.isEmpty
186194
? constructRecordConversion
@@ -323,7 +331,7 @@ extension JNISwift2JavaGenerator {
323331
)
324332
}
325333

326-
let translatedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType), methodName: name)
334+
let translatedResult = try translateResult(swiftType: swiftType.resultType, methodName: name)
327335

328336
return TranslatedFunctionType(
329337
name: name,
@@ -369,8 +377,8 @@ extension JNISwift2JavaGenerator {
369377
exceptions.append(.integerOverflow)
370378
}
371379

372-
let resultType = try translate(
373-
swiftResult: functionSignature.result,
380+
let resultType = try translateResult(
381+
swiftType: functionSignature.result.type,
374382
methodName: methodName,
375383
genericParameters: functionSignature.genericParameters,
376384
genericRequirements: functionSignature.genericRequirements,
@@ -380,7 +388,7 @@ extension JNISwift2JavaGenerator {
380388
selfParameter: selfParameter,
381389
selfTypeParameter: selfTypeParameter,
382390
parameters: parameters,
383-
resultType: resultType,
391+
result: resultType,
384392
exceptions: exceptions,
385393
)
386394
}
@@ -699,13 +707,13 @@ extension JNISwift2JavaGenerator {
699707
switch mode {
700708
case .completableFuture:
701709
nativeFutureType = .completableFuture(nativeFunctionSignature.result.javaType)
702-
translatedFutureType = .completableFuture(translatedFunctionSignature.resultType.javaType)
710+
translatedFutureType = .completableFuture(translatedFunctionSignature.result.javaType)
703711
completeMethodID = "_JNIMethodIDCache.CompletableFuture.complete"
704712
completeExceptionallyMethodID = "_JNIMethodIDCache.CompletableFuture.completeExceptionally"
705713

706714
case .legacyFuture:
707715
nativeFutureType = .simpleCompletableFuture(nativeFunctionSignature.result.javaType)
708-
translatedFutureType = .future(translatedFunctionSignature.resultType.javaType)
716+
translatedFutureType = .future(translatedFunctionSignature.result.javaType)
709717
completeMethodID = "_JNIMethodIDCache.SimpleCompletableFuture.complete"
710718
completeExceptionallyMethodID = "_JNIMethodIDCache.SimpleCompletableFuture.completeExceptionally"
711719
}
@@ -716,9 +724,10 @@ extension JNISwift2JavaGenerator {
716724
allocation: .new,
717725
)
718726

719-
let result = translatedFunctionSignature.resultType
720-
translatedFunctionSignature.resultType = TranslatedResult(
727+
let result = translatedFunctionSignature.result
728+
translatedFunctionSignature.result = TranslatedResult(
721729
javaType: translatedFutureType,
730+
nativeJavaType: .void,
722731
annotations: result.annotations,
723732
outParameters: result.outParameters + [futureOutParameter],
724733
conversion: .method(
@@ -890,15 +899,13 @@ extension JNISwift2JavaGenerator {
890899
}
891900
}
892901

893-
func translate(
894-
swiftResult: SwiftResult,
902+
func translateResult(
903+
swiftType: SwiftType,
895904
methodName: String,
896905
resultName: String = "result",
897906
genericParameters: [SwiftGenericParameterDeclaration] = [],
898907
genericRequirements: [SwiftGenericRequirement] = [],
899908
) throws -> TranslatedResult {
900-
let swiftType = swiftResult.type
901-
902909
// If the result type should cause any annotations on the method, include them here.
903910
let resultAnnotations: [JavaAnnotation] = getJavaTypeAnnotations(swiftType: swiftType, config: config)
904911

@@ -948,6 +955,7 @@ extension JNISwift2JavaGenerator {
948955
case .foundationUUID, .essentialsUUID:
949956
return TranslatedResult(
950957
javaType: .javaUtilUUID,
958+
nativeJavaType: .javaLangString,
951959
outParameters: [],
952960
conversion: .method(
953961
.constant("java.util.UUID"),
@@ -963,6 +971,7 @@ extension JNISwift2JavaGenerator {
963971

964972
return TranslatedResult(
965973
javaType: javaType,
974+
nativeJavaType: javaType,
966975
annotations: resultAnnotations,
967976
outParameters: [],
968977
conversion: .placeholder,
@@ -990,6 +999,7 @@ extension JNISwift2JavaGenerator {
990999
if nominalType.nominalTypeDecl.isGeneric {
9911000
return TranslatedResult(
9921001
javaType: javaType,
1002+
nativeJavaType: .void,
9931003
annotations: resultAnnotations,
9941004
outParameters: [.init(name: resultName, type: ._OutSwiftGenericInstance, allocation: .new)],
9951005
conversion: .wrapMemoryAddressUnsafe(
@@ -1003,14 +1013,15 @@ extension JNISwift2JavaGenerator {
10031013
} else {
10041014
return TranslatedResult(
10051015
javaType: javaType,
1016+
nativeJavaType: .long,
10061017
annotations: resultAnnotations,
10071018
outParameters: [],
10081019
conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
10091020
)
10101021
}
10111022

10121023
case .tuple([]):
1013-
return TranslatedResult(javaType: .void, outParameters: [], conversion: .placeholder)
1024+
return TranslatedResult(javaType: .void, nativeJavaType: .void, outParameters: [], conversion: .placeholder)
10141025

10151026
case .tuple(let elements) where !elements.isEmpty:
10161027
return try translateTupleResult(
@@ -1152,8 +1163,8 @@ extension JNISwift2JavaGenerator {
11521163
let outParamName = "\(resultName)_\(idx)$"
11531164

11541165
// Determine the Java type for this element
1155-
let elementResult = try translate(
1156-
swiftResult: .init(convention: .indirect, type: element.type),
1166+
let elementResult = try translateResult(
1167+
swiftType: element.type,
11571168
methodName: methodName,
11581169
resultName: outParamName,
11591170
genericParameters: genericParameters,
@@ -1162,9 +1173,9 @@ extension JNISwift2JavaGenerator {
11621173

11631174
// out names are always ...$N, no need to use real named tuple names here, this is just for the thunk
11641175
elementOutParamNames.append(outParamName)
1176+
outParameters.append(contentsOf: elementResult.outParameters)
11651177

1166-
// FIXME: More accurate determination of whether the result is direct or indirect
1167-
if elementResult.outParameters.isEmpty {
1178+
if !elementResult.nativeJavaType.isVoid {
11681179
// Convert direct result to indirect result.
11691180
// For most class types (Swift wrapper classes), the JNI native representation
11701181
// is 'long' (a memory address). However, String is a native JNI reference
@@ -1184,7 +1195,6 @@ extension JNISwift2JavaGenerator {
11841195
)
11851196
elementConversions.append(elementResult.conversion)
11861197
} else {
1187-
outParameters.append(contentsOf: elementResult.outParameters)
11881198
elementConversions.append(.placeToVar(elementResult.conversion, name: "\(resultName)_\(idx)"))
11891199
}
11901200
elementJavaTypes.append(elementResult.javaType)
@@ -1228,6 +1238,7 @@ extension JNISwift2JavaGenerator {
12281238

12291239
return TranslatedResult(
12301240
javaType: javaResultType,
1241+
nativeJavaType: .void,
12311242
annotations: tupleAnnotations,
12321243
outParameters: outParameters,
12331244
conversion: javaNativeConversionStep
@@ -1271,6 +1282,7 @@ extension JNISwift2JavaGenerator {
12711282
if let nextIntergralTypeWithSpaceForByte = javaType.nextIntergralTypeWithSpaceForByte {
12721283
return TranslatedResult(
12731284
javaType: .class(package: nil, name: returnType),
1285+
nativeJavaType: nextIntergralTypeWithSpaceForByte.javaType,
12741286
annotations: parameterAnnotations,
12751287
outParameters: [],
12761288
conversion: .combinedValueToOptional(
@@ -1287,6 +1299,7 @@ extension JNISwift2JavaGenerator {
12871299
// use an indirect return for the discriminator.
12881300
return TranslatedResult(
12891301
javaType: .class(package: nil, name: returnType),
1302+
nativeJavaType: javaType,
12901303
annotations: parameterAnnotations,
12911304
outParameters: [
12921305
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
@@ -1314,33 +1327,26 @@ extension JNISwift2JavaGenerator {
13141327
genericRequirements: genericRequirements,
13151328
)
13161329

1317-
let wrappedValueResult = try translate(
1318-
swiftResult: SwiftResult(convention: .direct, type: swiftType),
1330+
let wrappedValueResult = try translateResult(
1331+
swiftType: swiftType,
13191332
methodName: methodName,
13201333
resultName: resultName + "Wrapped$",
13211334
genericParameters: genericParameters,
13221335
genericRequirements: genericRequirements,
13231336
)
13241337

1325-
// FIXME: More accurate JavaType using NativeJavaTranslation results directly
1326-
let nativeResultJavaType: JavaType =
1327-
if wrappedValueResult.outParameters.isEmpty {
1328-
.long
1329-
} else {
1330-
.void
1331-
}
1332-
13331338
let returnType = JavaType.optional(javaType)
13341339
return TranslatedResult(
13351340
javaType: returnType,
1341+
nativeJavaType: wrappedValueResult.nativeJavaType,
13361342
annotations: parameterAnnotations,
13371343
outParameters: [
13381344
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
13391345
] + wrappedValueResult.outParameters,
13401346
conversion: .toOptionalFromIndirectReturn(
13411347
discriminatorName: .constant(discriminatorName),
13421348
optionalClass: "Optional",
1343-
nativeResultJavaType: nativeResultJavaType,
1349+
nativeResultJavaType: wrappedValueResult.nativeJavaType,
13441350
toValue: wrappedValueResult.conversion,
13451351
resultName: resultName
13461352
)
@@ -1449,6 +1455,7 @@ extension JNISwift2JavaGenerator {
14491455
)
14501456
return TranslatedResult(
14511457
javaType: .array(innerResult.javaType),
1458+
nativeJavaType: .array(innerResult.javaType),
14521459
annotations: annotations,
14531460
outParameters: [],
14541461
conversion: .placeholder
@@ -1462,6 +1469,7 @@ extension JNISwift2JavaGenerator {
14621469

14631470
return TranslatedResult(
14641471
javaType: .array(javaType),
1472+
nativeJavaType: .array(javaType),
14651473
annotations: annotations,
14661474
outParameters: [],
14671475
conversion: .placeholder,
@@ -1480,6 +1488,7 @@ extension JNISwift2JavaGenerator {
14801488
// We assume this is a JExtract class.
14811489
return TranslatedResult(
14821490
javaType: .array(javaType),
1491+
nativeJavaType: .array(.long),
14831492
annotations: annotations,
14841493
outParameters: [],
14851494
conversion: .method(
@@ -1564,6 +1573,7 @@ extension JNISwift2JavaGenerator {
15641573

15651574
return TranslatedResult(
15661575
javaType: dictType,
1576+
nativeJavaType: .long,
15671577
outParameters: [],
15681578
conversion: .wrapMemoryAddressUnsafe(.placeholder, dictType),
15691579
)
@@ -1606,6 +1616,7 @@ extension JNISwift2JavaGenerator {
16061616

16071617
return TranslatedResult(
16081618
javaType: setType,
1619+
nativeJavaType: .long,
16091620
outParameters: [],
16101621
conversion: .wrapMemoryAddressUnsafe(.placeholder, setType),
16111622
)
@@ -1682,17 +1693,17 @@ extension JNISwift2JavaGenerator {
16821693
var selfParameter: TranslatedParameter?
16831694
var selfTypeParameter: TranslatedParameter?
16841695
var parameters: [TranslatedParameter]
1685-
var resultType: TranslatedResult
1696+
var result: TranslatedResult
16861697
var exceptions: [JavaExceptionType]
16871698

16881699
// if the result type implied any annotations,
16891700
// propagate them onto the function the result is returned from
16901701
var annotations: [JavaAnnotation] {
1691-
self.resultType.annotations
1702+
self.result.annotations
16921703
}
16931704

16941705
var requiresSwiftArena: Bool {
1695-
self.resultType.conversion.requiresSwiftArena
1706+
self.result.conversion.requiresSwiftArena
16961707
}
16971708
}
16981709

@@ -1704,12 +1715,15 @@ extension JNISwift2JavaGenerator {
17041715

17051716
/// Represent a Swift API result translated to Java.
17061717
struct TranslatedResult {
1707-
let javaType: JavaType
1718+
var javaType: JavaType
1719+
1720+
/// result type of native function
1721+
var nativeJavaType: JavaType
17081722

17091723
/// Java annotations that should be propagated from the result type onto the method
17101724
var annotations: [JavaAnnotation] = []
17111725

1712-
let outParameters: [OutParameter]
1726+
var outParameters: [OutParameter]
17131727

17141728
/// Represents how to convert the Java native result into a user-facing result.
17151729
var conversion: JavaNativeConversionStep
@@ -1742,10 +1756,6 @@ extension JNISwift2JavaGenerator {
17421756
let name: String
17431757
let type: JavaType
17441758
let allocation: Allocation
1745-
1746-
var javaParameter: JavaParameter {
1747-
JavaParameter(name: self.name, type: self.type)
1748-
}
17491759
}
17501760

17511761
/// Represent a Swift closure type in the user facing Java API.

0 commit comments

Comments
 (0)