Skip to content
Draft
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
@@ -0,0 +1,17 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

public enum EnumWithValueCases {
case firstCase(UInt)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

public final class ObjectWithInts {
public var normalInt: Int
public var unsignedInt: UInt

public init(normalInt: Int, unsignedInt: UInt) {
self.normalInt = normalInt
self.unsignedInt = unsignedInt
}

public func callMe(arg: UInt) -> UInt {
return arg
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

package com.example.swift;

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.ConfinedSwiftMemorySession;
import org.swift.swiftkit.core.SwiftArena;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

public class EnumWithValueCasesTest {
@Test
void fn() {
try (var arena = SwiftArena.ofConfined()) {
EnumWithValueCases e = EnumWithValueCases.firstCase(48, arena);
EnumWithValueCases.FirstCase c = (EnumWithValueCases.FirstCase) e.getCase();
assertNotNull(c);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

package com.example.swift;

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.ConfinedSwiftMemorySession;
import org.swift.swiftkit.core.SwiftArena;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

public class ObjectWithIntsTest {
@Test
void init() {
try (var arena = SwiftArena.ofConfined()) {
ObjectWithInts obj = ObjectWithInts.init(-45, 45, arena);
assertEquals(-45, obj.getNormalInt());
assertEquals(45, obj.getUnsignedInt());
}
}

@Test
void callMe() {
try (var arena = SwiftArena.ofConfined()) {
ObjectWithInts obj = ObjectWithInts.init(-45, 45, arena);
assertEquals(66, obj.callMe(66));
}
}
}
39 changes: 37 additions & 2 deletions Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,55 @@ enum JNIJavaTypeTranslator {

case .int64: return .long
case .uint64: return .long

case .int, .uint: return .long

case .float: return .float
case .double: return .double
case .void: return .void

case .string: return .javaLangString

case .int, .uint, // FIXME: why not supported int/uint?
.unsafeRawPointer, .unsafeMutableRawPointer,
case .unsafeRawPointer, .unsafeMutableRawPointer,
.unsafePointer, .unsafeMutablePointer,
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
.unsafeBufferPointer, .unsafeMutableBufferPointer,
.optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol, .array:
return nil
}
}

static func indirectConversionStepSwiftType(for knownKind: SwiftKnownTypeDeclKind, from knownTypes: SwiftKnownTypes) -> SwiftType? {
switch knownKind {
case .int: knownTypes.int64
case .uint: knownTypes.uint64

case .bool, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64,
.float, .double, .void, .string,
.unsafeRawPointer, .unsafeMutableRawPointer,
.unsafePointer, .unsafeMutablePointer,
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
.unsafeBufferPointer, .unsafeMutableBufferPointer,
.optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol,
.array:
nil
}
}

static func checkStep(for knownKind: SwiftKnownTypeDeclKind, from knownTypes: SwiftKnownTypes) -> JNISwift2JavaGenerator.NativeSwiftConversionCheck? {
switch knownKind {
case .int: .check32BitIntOverflow(typeWithMinAndMax: knownTypes.int32)
case .uint: .check32BitIntOverflow(typeWithMinAndMax: knownTypes.uint32)

case .bool, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64,
.float, .double, .void, .string,
.unsafeRawPointer, .unsafeMutableRawPointer,
.unsafePointer, .unsafeMutablePointer,
.unsafeRawBufferPointer, .unsafeMutableRawBufferPointer,
.unsafeBufferPointer, .unsafeMutableBufferPointer,
.optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol,
.array:
nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ extension JNISwift2JavaGenerator {
let translatedSignature = translatedDecl.translatedFunctionSignature
let resultType = translatedSignature.resultType.javaType
var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() }
let throwsClause = translatedDecl.isThrowing && !translatedDecl.isAsync ? " throws Exception" : ""
let throwsClause = translatedDecl.throwsClause()

let generics = translatedDecl.translatedFunctionSignature.parameters.reduce(into: [(String, [JavaType])]()) { generics, parameter in
guard case .generic(let name, let extends) = parameter.parameter.type else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ extension JNISwift2JavaGenerator {
.class(package: nil,name: caseName)
)
])
var exceptions: [JavaExceptionType] = []

if enumCase.parameters.contains(where: \.type.isArchDependingInteger) {
exceptions.append(.integerOverflow)
}

let getAsCaseFunction = TranslatedFunctionDecl(
name: getAsCaseName,
isStatic: false,
Expand All @@ -137,12 +143,15 @@ extension JNISwift2JavaGenerator {
javaType: .class(package: nil, name: "Optional<\(caseName)>"),
outParameters: conversions.flatMap(\.translated.outParameters),
conversion: enumCase.parameters.isEmpty ? constructRecordConversion : .aggregate(variable: ("$nativeParameters", nativeParametersType), [constructRecordConversion])
)
),
exceptions: exceptions
),
nativeFunctionSignature: NativeFunctionSignature(
selfParameter: NativeParameter(
parameters: [JavaParameter(name: "self", type: .long)],
conversion: .extractSwiftValue(.placeholder, swiftType: .nominal(enumCase.enumType), allowNil: false)
conversion: .extractSwiftValue(.placeholder, swiftType: .nominal(enumCase.enumType), allowNil: false),
indirectConversion: nil,
conversionCheck: nil
),
parameters: [],
result: NativeResult(
Expand Down Expand Up @@ -291,12 +300,19 @@ extension JNISwift2JavaGenerator {
genericRequirements: functionSignature.genericRequirements
)

var exceptions: [JavaExceptionType] = []

if functionSignature.parameters.contains(where: \.type.isArchDependingInteger) {
exceptions.append(.integerOverflow)
}

let resultType = try translate(swiftResult: functionSignature.result)

return TranslatedFunctionSignature(
selfParameter: selfParameter,
parameters: parameters,
resultType: resultType
resultType: resultType,
exceptions: exceptions
)
}

Expand Down Expand Up @@ -955,12 +971,22 @@ extension JNISwift2JavaGenerator {
var annotations: [JavaAnnotation] {
self.translatedFunctionSignature.annotations
}

func throwsClause() -> String {
guard !translatedFunctionSignature.exceptions.isEmpty else {
return isThrowing && !isAsync ? " throws Exception" : ""
}

let signatureExceptions = translatedFunctionSignature.exceptions.compactMap(\.type.className).joined(separator: ", ")
return " throws \(signatureExceptions)\(isThrowing ? ", Exception" : "")"
}
}

struct TranslatedFunctionSignature {
var selfParameter: TranslatedParameter?
var parameters: [TranslatedParameter]
var resultType: TranslatedResult
var exceptions: [JavaExceptionType]

// if the result type implied any annotations,
// propagate them onto the function the result is returned from
Expand Down
Loading
Loading