Skip to content

Commit ed42947

Browse files
committed
add support for optional JavaKit wrapped parameters
1 parent 528cbab commit ed42947

File tree

7 files changed

+109
-108
lines changed

7 files changed

+109
-108
lines changed

Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import JavaKit
16+
1517
public func optionalBool(input: Optional<Bool>) -> Bool? {
1618
return input
1719
}
@@ -52,6 +54,14 @@ public func optionalClass(input: Optional<MySwiftClass>) -> MySwiftClass? {
5254
return input
5355
}
5456

57+
public func optionalJavaKitLong(input: Optional<JavaLong>) -> Int64? {
58+
if let input {
59+
return input.longValue()
60+
} else {
61+
return nil
62+
}
63+
}
64+
5565
public func multipleOptionals(
5666
input1: Optional<Int8>,
5767
input2: Optional<Int16>,

Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ void optionalClass() {
9191
}
9292
}
9393

94+
@Test
95+
void optionalJavaKitLong() {
96+
assertEquals(OptionalLong.empty(), MySwiftLibrary.optionalJavaKitLong(Optional.empty()));
97+
assertEquals(OptionalLong.of(99L), MySwiftLibrary.optionalJavaKitLong(Optional.of(99L)));
98+
}
99+
94100
@Test
95101
void multipleOptionals() {
96102
try (var arena = new ConfinedSwiftMemorySession()) {

Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,29 @@ extension JavaType {
8686
case .void: nil
8787
}
8888
}
89+
90+
var jniCallMethodAName: String {
91+
switch self {
92+
case .boolean: "CallBooleanMethodA"
93+
case .byte: "CallByteMethodA"
94+
case .char: "CallCharMethodA"
95+
case .short: "CallShortMethodA"
96+
case .int: "CallIntMethodA"
97+
case .long: "CallLongMethodA"
98+
case .float: "CallFloatMethodA"
99+
case .double: "CallDoubleMethodA"
100+
case .void: "CallVoidMethodA"
101+
default: "CallObjectMethodA"
102+
}
103+
}
104+
105+
/// Returns whether this type returns `JavaValue` from JavaKit
106+
var implementsJavaValue: Bool {
107+
return switch self {
108+
case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString:
109+
true
110+
default:
111+
false
112+
}
113+
}
89114
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,23 @@ extension JNISwift2JavaGenerator {
306306
)
307307
}
308308

309-
guard !nominalType.isJavaKitWrapper else {
310-
throw JavaTranslationError.unsupportedSwiftType(swiftType)
309+
if nominalType.isJavaKitWrapper {
310+
guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else {
311+
throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType)
312+
}
313+
314+
return TranslatedParameter(
315+
parameter: JavaParameter(
316+
name: parameterName,
317+
type: .class(package: nil, name: "Optional<\(javaType)>"),
318+
annotations: parameterAnnotations
319+
),
320+
conversion: .method(
321+
.placeholder,
322+
function: "orElse",
323+
arguments: [.constant("null")]
324+
)
325+
)
311326
}
312327

313328
// Assume JExtract imported class

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,14 @@ extension JNISwift2JavaGenerator {
107107
parameters: [
108108
JavaParameter(name: parameterName, type: javaType)
109109
],
110-
conversion: .initializeJavaKitWrapper(wrapperName: nominalTypeName)
110+
conversion: .initializeJavaKitWrapper(
111+
.unwrapOptional(
112+
.placeholder,
113+
name: parameterName,
114+
fatalErrorMessage: "\(parameterName) was null in call to \\(#function), but Swift requires non-optional!"
115+
),
116+
wrapperName: nominalTypeName
117+
)
111118
)
112119
}
113120

@@ -170,6 +177,8 @@ extension JNISwift2JavaGenerator {
170177

171178
switch swiftType {
172179
case .nominal(let nominalType):
180+
let nominalTypeName = nominalType.nominalTypeDecl.name
181+
173182
if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
174183
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config),
175184
javaType.implementsJavaValue else {
@@ -189,8 +198,17 @@ extension JNISwift2JavaGenerator {
189198
)
190199
}
191200

192-
guard !nominalType.isJavaKitWrapper else {
193-
throw JavaTranslationError.unsupportedSwiftType(swiftType)
201+
if nominalType.isJavaKitWrapper {
202+
guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else {
203+
throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType)
204+
}
205+
206+
return NativeParameter(
207+
parameters: [
208+
JavaParameter(name: parameterName, type: javaType)
209+
],
210+
conversion: .optionalMap(.initializeJavaKitWrapper(.placeholder, wrapperName: nominalTypeName))
211+
)
194212
}
195213

196214
// Assume JExtract wrapped class
@@ -456,7 +474,7 @@ extension JNISwift2JavaGenerator {
456474

457475
indirect case closureLowering(parameters: [NativeParameter], result: NativeResult)
458476

459-
case initializeJavaKitWrapper(wrapperName: String)
477+
indirect case initializeJavaKitWrapper(NativeSwiftConversionStep, wrapperName: String)
460478

461479
indirect case optionalLowering(NativeSwiftConversionStep, discriminatorName: String, valueName: String)
462480

@@ -470,6 +488,10 @@ extension JNISwift2JavaGenerator {
470488

471489
indirect case member(NativeSwiftConversionStep, member: String)
472490

491+
indirect case optionalMap(NativeSwiftConversionStep)
492+
493+
indirect case unwrapOptional(NativeSwiftConversionStep, name: String, fatalErrorMessage: String)
494+
473495
/// Returns the conversion string applied to the placeholder.
474496
func render(_ printer: inout CodePrinter, _ placeholder: String) -> String {
475497
// NOTE: 'printer' is used if the conversion wants to cause side-effects.
@@ -558,7 +580,7 @@ extension JNISwift2JavaGenerator {
558580
"""
559581
)
560582

561-
let upcall = "environment!.interface.\(nativeResult.javaType.jniType.callMethodAName)(environment, \(placeholder), methodID$, arguments$)"
583+
let upcall = "environment!.interface.\(nativeResult.javaType.jniCallMethodAName)(environment, \(placeholder), methodID$, arguments$)"
562584
let result = nativeResult.conversion.render(&printer, upcall)
563585

564586
if nativeResult.javaType.isVoid {
@@ -572,8 +594,9 @@ extension JNISwift2JavaGenerator {
572594

573595
return printer.finalize()
574596

575-
case .initializeJavaKitWrapper(let wrapperName):
576-
return "\(wrapperName)(javaThis: \(placeholder), environment: environment!)"
597+
case .initializeJavaKitWrapper(let inner, let wrapperName):
598+
let inner = inner.render(&printer, placeholder)
599+
return "\(wrapperName)(javaThis: \(inner), environment: environment!)"
577600

578601
case .optionalLowering(let valueConversion, let discriminatorName, let valueName):
579602
let value = valueConversion.render(&printer, valueName)
@@ -637,6 +660,26 @@ extension JNISwift2JavaGenerator {
637660
case .member(let inner, let member):
638661
let inner = inner.render(&printer, placeholder)
639662
return "\(inner).\(member)"
663+
664+
case .optionalMap(let inner):
665+
var printer = CodePrinter()
666+
printer.printBraceBlock("\(placeholder).map") { printer in
667+
let inner = inner.render(&printer, "$0")
668+
printer.print("return \(inner)")
669+
}
670+
return printer.finalize()
671+
672+
case .unwrapOptional(let inner, let name, let fatalErrorMessage):
673+
let unwrappedName = "\(name)_unwrapped$"
674+
let inner = inner.render(&printer, placeholder)
675+
printer.print(
676+
"""
677+
guard let \(unwrappedName) = \(inner) else {
678+
fatalError("\(fatalErrorMessage)")
679+
}
680+
"""
681+
)
682+
return unwrappedName
640683
}
641684
}
642685
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ extension JNISwift2JavaGenerator {
249249
+ jniSignature.escapedJNIIdentifier
250250

251251
let translatedParameters = parameters.map {
252-
"\($0.name): \($0.type.jniType)"
252+
"\($0.name): \($0.type.jniTypeName)"
253253
}
254254

255255
let thunkParameters =

Sources/JExtractSwiftLib/JNI/JNIType.swift

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)