Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,11 @@ public func multipleOptionals(
) -> Int64? {
1
}

public func optionalTuple() -> (Int64, String)? {
(42, "hello")
}

public func optionalTuple2() -> (Int64?, Alignment?)? {
(42, .horizontal)
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ public func makeBigTuple() -> (
public func namedByteArrayTuple() -> (name: [UInt8], another: [UInt8]) {
(name: [1, 2, 3], another: [4, 5])
}

public func genericTypeTuple() -> (MyID<Double>, Alignment) {
(MyID(1.23), .horizontal)
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,30 @@ void optionalThrows() {
assertEquals("swiftError", exception.getMessage());
}
}
}

@Test
void optionalTuple() {
var result = MySwiftLibrary.optionalTuple();
assertDoesNotThrow(() -> {
var resultUnwrapped = result.orElseThrow();
assertEquals(42, resultUnwrapped.$0);
assertEquals("hello", resultUnwrapped.$1);
});
}

@Test
void optionalTuple2() {
try (var arena = SwiftArena.ofConfined()) {
var result = MySwiftLibrary.optionalTuple2(arena);
assertDoesNotThrow(() -> {
var resultUnwrapped = result.orElseThrow();
assertDoesNotThrow(() -> {
assertEquals(42, resultUnwrapped.$0.orElseThrow());
});
assertDoesNotThrow(() -> {
assertEquals(Alignment.Discriminator.HORIZONTAL, resultUnwrapped.$1.orElseThrow().getDiscriminator());
});
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.example.swift;

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
import org.swift.swiftkit.core.tuple.Tuple2;
import org.swift.swiftkit.core.tuple.Tuple3;
import org.swift.swiftkit.core.tuple.Tuple16;
Expand Down Expand Up @@ -95,4 +96,13 @@ void namedByteArrayTuple() {
assertArrayEquals(new byte[] { 1, 2, 3 }, (byte[]) result.$0);
assertArrayEquals(new byte[] { 4, 5 }, (byte[]) result.$1);
}

@Test
void genericTypeTuple() {
try (var arena = SwiftArena.ofConfined()) {
var result = MySwiftLibrary.genericTypeTuple(arena);
assertEquals("1.23", result.$0.getDescription());
assertEquals(Alignment.Discriminator.HORIZONTAL, result.$1.getDiscriminator());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ extension JavaType {
}
}

var swiftJniPlaceholderExpr: String {
switch self {
case .boolean, .byte, .char, .short, .int, .long: "0"
case .float, .double: "0.0"
case .array, .class: "nil"
case .void: "()"
}
}

var jniCallMethodAName: String {
switch self {
case .boolean: "CallBooleanMethodA"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,13 @@ extension JNISwift2JavaGenerator {
if let knownType = nominalType.asKnownType {
switch knownType {
case .optional(let wrapped):
if let wrappedKnownKind = wrapped.asNominalTypeDeclaration?.knownTypeKind,
let javaType = JNIJavaTypeTranslator.translate(knownType: wrappedKnownKind, config: self.config),
let optionalType = javaType.optionalType
{
return .class(package: nil, name: optionalType)
}

let wrappedType = try translateGenericTypeParameter(
wrapped,
genericParameters: genericParameters,
Expand Down Expand Up @@ -1141,7 +1148,17 @@ extension JNISwift2JavaGenerator {
}
return .class(package: nil, name: generic.name)

case .metatype, .tuple, .function, .existential, .opaque, .composite:
case .tuple(let elements):
let elementJavaTypes = try elements.map { element in
try translateGenericTypeParameter(
element.type,
genericParameters: genericParameters,
genericRequirements: genericRequirements
)
}
return .tuple(elementTypes: elementJavaTypes)

case .metatype, .function, .existential, .opaque, .composite:
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}
}
Expand Down Expand Up @@ -1259,22 +1276,11 @@ extension JNISwift2JavaGenerator {
switch swiftType {
case .nominal(let nominalType):
if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
switch knownType {
case .foundationDate, .essentialsDate:
// Handled as wrapped struct
break

case .foundationData, .essentialsData:
// Handled as wrapped struct
break

default:
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

if let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config),
javaType.implementsJavaValue
{
guard let returnType = javaType.optionalType, let optionalClass = javaType.optionalWrapperType else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
break
}

// Check if we can fit the value and a discriminator byte in a primitive.
Expand Down Expand Up @@ -1320,41 +1326,44 @@ extension JNISwift2JavaGenerator {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

// We assume this is a JExtract class.
let javaType = try translateGenericTypeParameter(
swiftType,
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)

let wrappedValueResult = try translateResult(
swiftType: swiftType,
methodName: methodName,
resultName: resultName + "Wrapped$",
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)

let returnType = JavaType.optional(javaType)
return TranslatedResult(
javaType: returnType,
nativeJavaType: wrappedValueResult.nativeJavaType,
annotations: parameterAnnotations,
outParameters: [
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
] + wrappedValueResult.outParameters,
conversion: .toOptionalFromIndirectReturn(
discriminatorName: .constant(discriminatorName),
optionalClass: "Optional",
nativeResultJavaType: wrappedValueResult.nativeJavaType,
toValue: wrappedValueResult.conversion,
resultName: resultName
)
)
case .tuple:
break

default:
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

// Common indirect conversion
let javaType = try translateGenericTypeParameter(
swiftType,
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)

let wrappedValueResult = try translateResult(
swiftType: swiftType,
methodName: methodName,
resultName: resultName + "Wrapped$",
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)

let returnType = JavaType.optional(javaType)
return TranslatedResult(
javaType: returnType,
nativeJavaType: wrappedValueResult.nativeJavaType,
annotations: parameterAnnotations,
outParameters: [
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
] + wrappedValueResult.outParameters,
conversion: .toOptionalFromIndirectReturn(
discriminatorName: .constant(discriminatorName),
optionalClass: "Optional",
nativeResultJavaType: wrappedValueResult.nativeJavaType,
toValue: wrappedValueResult.conversion,
resultName: resultName
)
)
}

func translateArrayParameter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,23 +531,9 @@ extension JNISwift2JavaGenerator {
switch swiftType {
case .nominal(let nominalType):
if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
switch knownType {
case .foundationDate, .essentialsDate:
// Handled as wrapped struct
break

case .foundationData, .essentialsData:
// Handled as wrapped struct
break

default:
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config),
javaType.implementsJavaValue
else {
self.logger.debug("Known type \(knownType) is not supported for optional results, skipping.")
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

if let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config),
javaType.implementsJavaValue
{
// Check if we can fit the value and a discriminator byte in a primitive.
// so the return JNI value will be (value, discriminator)
if let nextIntergralTypeWithSpaceForByte = javaType.nextIntergralTypeWithSpaceForByte {
Expand All @@ -571,12 +557,9 @@ extension JNISwift2JavaGenerator {
javaType: javaType,
conversion: .optionalRaisingIndirectReturn(
.getJNIValue(.placeholder),
resultName: "\(resultName)$",
returnType: javaType,
discriminatorParameterName: discriminatorName,
placeholderValue: .member(
.constant("\(swiftType)"),
member: "jniPlaceholderValue"
)
discriminatorParameterName: discriminatorName
),
outParameters: [
JavaParameter(name: discriminatorName, type: .array(.byte))
Expand All @@ -591,29 +574,31 @@ extension JNISwift2JavaGenerator {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

let wrappedValueResult = try translateResult(
swiftType: swiftType,
methodName: methodName,
resultName: resultName + "Wrapped"
)

// Assume JExtract imported class
return NativeResult(
javaType: wrappedValueResult.javaType,
conversion: .optionalRaisingIndirectReturn(
wrappedValueResult.conversion,
returnType: wrappedValueResult.javaType,
discriminatorParameterName: discriminatorName,
placeholderValue: .constant("0")
),
outParameters: [
JavaParameter(name: discriminatorName, type: .array(.byte))
] + wrappedValueResult.outParameters
)
case .tuple:
break

default:
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

// Common indirect conversion
let wrappedValueResult = try translateResult(
swiftType: swiftType,
methodName: methodName,
resultName: resultName + "Wrapped"
)
return NativeResult(
javaType: wrappedValueResult.javaType,
conversion: .optionalRaisingIndirectReturn(
wrappedValueResult.conversion,
resultName: "\(resultName)$",
returnType: wrappedValueResult.javaType,
discriminatorParameterName: discriminatorName
),
outParameters: [
JavaParameter(name: discriminatorName, type: .array(.byte))
] + wrappedValueResult.outParameters
)
}

func translateClosureResult(
Expand Down Expand Up @@ -1162,9 +1147,9 @@ extension JNISwift2JavaGenerator {

indirect case optionalRaisingIndirectReturn(
NativeSwiftConversionStep,
resultName: String,
returnType: JavaType,
discriminatorParameterName: String,
placeholderValue: NativeSwiftConversionStep
discriminatorParameterName: String
)

indirect case genericValueIndirectReturn(
Expand Down Expand Up @@ -1530,17 +1515,17 @@ extension JNISwift2JavaGenerator {

case .optionalRaisingIndirectReturn(
let inner,
let resultName,
let returnType,
let discriminatorParameterName,
let placeholderValue
let discriminatorParameterName
):
if !returnType.isVoid {
printer.print("let result$: \(returnType.jniTypeName)")
printer.print("let \(resultName): \(returnType.jniTypeName)")
}
printer.printBraceBlock("if let innerResult$ = \(placeholder)") { printer in
let inner = inner.render(&printer, "innerResult$")
if !returnType.isVoid {
printer.print("result$ = \(inner)")
printer.print("\(resultName) = \(inner)")
}
printer.print(
"""
Expand All @@ -1550,9 +1535,8 @@ extension JNISwift2JavaGenerator {
)
}
printer.printBraceBlock("else") { printer in
let placeholderValue = placeholderValue.render(&printer, placeholder)
if !returnType.isVoid {
printer.print("result$ = \(placeholderValue)")
printer.print("\(resultName) = \(returnType.swiftJniPlaceholderExpr)")
}
printer.print(
"""
Expand All @@ -1562,7 +1546,7 @@ extension JNISwift2JavaGenerator {
)
}
if !returnType.isVoid {
return "result$"
return resultName
} else {
return ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -751,14 +751,7 @@ extension JNISwift2JavaGenerator {
}

private func dummyReturn(for nativeSignature: NativeFunctionSignature) -> String {
if nativeSignature.result.javaType.isVoid {
"return"
} else if nativeSignature.result.javaType.isString {
"return String.jniPlaceholderValue"
} else {
// We assume it is something that implements JavaValue
"return \(nativeSignature.result.javaType.swiftTypeName(resolver: { _ in "" })).jniPlaceholderValue"
}
"return \(nativeSignature.result.javaType.swiftJniPlaceholderExpr)"
}

private func printCDecl(
Expand Down
Loading
Loading