Skip to content
Merged
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 @@ -14,6 +14,12 @@

import SwiftJava

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

public func optionalBool(input: Bool?) -> Bool? {
input
}
Expand Down Expand Up @@ -54,6 +60,14 @@ public func optionalClass(input: MySwiftClass?) -> MySwiftClass? {
input
}

public func optionalDate(input: Date?) -> Date? {
input
}

public func optionalData(input: Data?) -> Data? {
input
}

public func optionalJavaKitLong(input: JavaLong?) -> Int64? {
if let input {
return input.longValue()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;

import java.time.Instant;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
Expand Down Expand Up @@ -80,6 +81,26 @@ void optionalString() {
assertEquals(Optional.of("Hello Swift!"), MySwiftLibrary.optionalString(Optional.of("Hello Swift!")));
}

@Test
void optionalDate() {
try (var arena = SwiftArena.ofConfined()) {
assertEquals(Optional.empty(), MySwiftLibrary.optionalDate(Optional.empty(), arena));
var date = Date.fromInstant(Instant.now(), arena);
Optional<Date> optionalDate = MySwiftLibrary.optionalDate(Optional.of(date), arena);
assertTrue(optionalDate.isPresent());
}
}

@Test
void optionalData() {
try (var arena = SwiftArena.ofConfined()) {
assertEquals(Optional.empty(), MySwiftLibrary.optionalData(Optional.empty(), arena));
var data = Data.fromByteArray(new byte[] { 1, 2 }, arena);
Optional<Data> optionalData = MySwiftLibrary.optionalData(Optional.of(data), arena);
assertTrue(optionalData.isPresent());
}
}

@Test
void optionalClass() {
try (var arena = SwiftArena.ofConfined()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ extension JNISwift2JavaGenerator {
javaPackage: self.javaPackage,
javaClassLookupTable: self.javaClassLookupTable,
knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable),
protocolWrappers: self.interfaceProtocolWrappers
protocolWrappers: self.interfaceProtocolWrappers,
logger: self.logger
)
}

Expand Down Expand Up @@ -61,7 +62,8 @@ extension JNISwift2JavaGenerator {
javaPackage: self.javaPackage,
javaClassLookupTable: self.javaClassLookupTable,
knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable),
protocolWrappers: self.interfaceProtocolWrappers
protocolWrappers: self.interfaceProtocolWrappers,
logger: self.logger
)
translated = try translation.translate(enumCase: decl)
} catch {
Expand All @@ -80,14 +82,16 @@ extension JNISwift2JavaGenerator {
let javaClassLookupTable: JavaClassLookupTable
var knownTypes: SwiftKnownTypes
let protocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper]
let logger: Logger

func translate(enumCase: ImportedEnumCase) throws -> TranslatedEnumCase {
let nativeTranslation = NativeJavaTranslation(
config: self.config,
javaPackage: self.javaPackage,
javaClassLookupTable: self.javaClassLookupTable,
knownTypes: self.knownTypes,
protocolWrappers: self.protocolWrappers
protocolWrappers: self.protocolWrappers,
logger: self.logger
)

let methodName = "" // TODO: Used for closures, replace with better name?
Expand Down Expand Up @@ -197,7 +201,8 @@ extension JNISwift2JavaGenerator {
javaPackage: self.javaPackage,
javaClassLookupTable: self.javaClassLookupTable,
knownTypes: self.knownTypes,
protocolWrappers: self.protocolWrappers
protocolWrappers: self.protocolWrappers,
logger: self.logger
)

// Types with no parent will be outputted inside a "module" class.
Expand Down Expand Up @@ -651,26 +656,37 @@ extension JNISwift2JavaGenerator {
let nominalTypeName = nominalType.nominalTypeDecl.name

if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}
switch knownType {
case .foundationDate, .essentialsDate:
// Handled as wrapped struct
break

guard let translatedClass = javaType.optionalType, let placeholderValue = javaType.optionalPlaceholderValue
else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}
case .foundationData, .essentialsData:
// Handled as wrapped struct
break

return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
type: JavaType(className: translatedClass),
annotations: parameterAnnotations
),
conversion: .commaSeparated([
.isOptionalPresent,
.method(.placeholder, function: "orElse", arguments: [.constant(placeholderValue)]),
])
)
default:
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

guard let translatedClass = javaType.optionalType, let placeholderValue = javaType.optionalPlaceholderValue
else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
type: JavaType(className: translatedClass),
annotations: parameterAnnotations
),
conversion: .commaSeparated([
.isOptionalPresent,
.method(.placeholder, function: "orElse", arguments: [.constant(placeholderValue)]),
])
)
}
}

if nominalType.isSwiftJavaWrapper {
Expand Down Expand Up @@ -809,47 +825,58 @@ extension JNISwift2JavaGenerator {
let nominalTypeName = nominalType.nominalTypeDecl.name

if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}
switch knownType {
case .foundationDate, .essentialsDate:
// Handled as wrapped struct
break

guard let returnType = javaType.optionalType, let optionalClass = javaType.optionalWrapperType else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}
case .foundationData, .essentialsData:
// Handled as wrapped struct
break

// 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 {
return TranslatedResult(
javaType: .class(package: nil, name: returnType),
annotations: parameterAnnotations,
outParameters: [],
conversion: .combinedValueToOptional(
.placeholder,
nextIntergralTypeWithSpaceForByte.javaType,
resultName: resultName,
valueType: javaType,
valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes,
optionalType: optionalClass
default:
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

guard let returnType = javaType.optionalType, let optionalClass = javaType.optionalWrapperType else {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

// 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 {
return TranslatedResult(
javaType: .class(package: nil, name: returnType),
annotations: parameterAnnotations,
outParameters: [],
conversion: .combinedValueToOptional(
.placeholder,
nextIntergralTypeWithSpaceForByte.javaType,
resultName: resultName,
valueType: javaType,
valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes,
optionalType: optionalClass
)
)
)
} else {
// Otherwise, we return the result as normal, but
// use an indirect return for the discriminator.
return TranslatedResult(
javaType: .class(package: nil, name: returnType),
annotations: parameterAnnotations,
outParameters: [
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
],
conversion: .toOptionalFromIndirectReturn(
discriminatorName: .combinedName(component: "discriminator$"),
optionalClass: optionalClass,
javaType: javaType,
toValue: .placeholder,
resultName: resultName
} else {
// Otherwise, we return the result as normal, but
// use an indirect return for the discriminator.
return TranslatedResult(
javaType: .class(package: nil, name: returnType),
annotations: parameterAnnotations,
outParameters: [
OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1))
],
conversion: .toOptionalFromIndirectReturn(
discriminatorName: .combinedName(component: "discriminator$"),
optionalClass: optionalClass,
javaType: javaType,
toValue: .placeholder,
resultName: resultName
)
)
)
}
}
}

Expand Down
Loading
Loading