Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1c170d0
SwiftKit: prepare Unsigned Java types for interop with UInt etc
ktoso Jul 13, 2025
32ef064
NOTICE so we can base out unsigned numerics on guava (Apache 2.0)
ktoso Jul 14, 2025
8d0177d
docc documentation, first step
ktoso Jul 15, 2025
3b9bcda
some jextract work
ktoso Jul 24, 2025
c649c1f
import Guava primitives
ktoso Jul 29, 2025
778096a
reduce imported Guava primitives surface to bare minimum necessary
ktoso Jul 29, 2025
be10668
Document and cleanup how we import unsigned swift types
ktoso Jul 29, 2025
2a3caf1
add tests and correct char handling for jextractign unsigned params
ktoso Jul 29, 2025
db3b4ef
Revert "docc documentation, first step"
ktoso Jul 29, 2025
313317f
remove unnecessary ??
ktoso Jul 30, 2025
bc82185
Move configuration deeper and allow confifuring unsigned handling mode
ktoso Jul 30, 2025
08c8f6a
correct configuration and some compile issues
ktoso Jul 30, 2025
e5006f7
reduce amount of vendored Guava primitives types
ktoso Jul 30, 2025
d34921a
remove unallowed language wording
ktoso Jul 30, 2025
925196d
also include annotations import
ktoso Jul 30, 2025
220ff31
fix test
ktoso Jul 30, 2025
ca6d81d
ignore NOTICE.txt from language checks; we link specific branch name
ktoso Jul 30, 2025
dfbd9f1
license updates
ktoso Jul 30, 2025
37820c4
more license fixes
ktoso Jul 30, 2025
1894787
remove vendored guava entirely, and instead allow sourcegen to use Guava
ktoso Jul 30, 2025
4653ee5
Implement @Unchecked integer types for jextract-jni
ktoso Jul 31, 2025
efd0907
remove tests for types we did not end up adding after all
ktoso Jul 31, 2025
c407852
correct some type handling and add test for JNI unsigned
ktoso Jul 31, 2025
bc1b0cf
post-rebase fixes
ktoso Jul 31, 2025
ad2e222
add documentation for unsigned types
ktoso Jul 31, 2025
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
3 changes: 2 additions & 1 deletion .unacceptablelanguageignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ Sources/_Subprocess/Platforms/Subprocess+Darwin.swift
Sources/_Subprocess/Platforms/Subprocess+Linux.swift
Sources/_Subprocess/Platforms/Subprocess+Unix.swift
Sources/_Subprocess/Teardown.swift
Sources/_Subprocess/Subprocess.swift
Sources/_Subprocess/Subprocess.swift
NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public func globalTakeIntInt(i: Int64, j: Int64) {
p("i:\(i), j:\(j)")
}

public func echoUnsignedInt(i: UInt32, j: UInt64) -> UInt64 {
p("i:\(i), j:\(j)")
return UInt64(i) + j
}

// ==== Internal helpers

func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,11 @@ void globalVariable() {
MySwiftLibrary.setGlobalVariable(100);
assertEquals(100, MySwiftLibrary.getGlobalVariable());
}

@Test
void globalUnsignedIntEcho() {
int i = 12;
long l = 1200;
assertEquals(1212, MySwiftLibrary.echoUnsignedInt(12, 1200));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,16 @@ public class MySwiftClass {
public func makeRandomIntMethod() -> Int {
return Int.random(in: 1..<256)
}

public func takeUnsignedChar(arg: UInt16) {
p("\(UInt32.self) = \(arg)")
}

public func takeUnsignedInt(arg: UInt32) {
p("\(UInt32.self) = \(arg)")
}

public func takeUnsignedLong(arg: UInt64) {
p("\(UInt64.self) = \(arg)")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

package com.example.swift;

import org.junit.jupiter.api.Test;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;

public class UnsignedNumbersTest {
@Test
void take_uint32() {
try (var arena = AllocatingSwiftArena.ofConfined()) {
var c = MySwiftClass.init(1, 2, arena);
c.takeUnsignedInt(128);
}
}

@Test
void take_uint64() {
try (var arena = AllocatingSwiftArena.ofConfined()) {
var c = MySwiftClass.init(1, 2, arena);
c.takeUnsignedLong(Long.MAX_VALUE);
}
}
}
26 changes: 26 additions & 0 deletions Sources/JExtractSwiftLib/Common/TypeAnnotations.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

import JavaTypes
import JavaKitConfigurationShared

/// Determine if the given type needs any extra annotations that should be included
/// in Java sources when the corresponding Java type is rendered.
func getTypeAnnotations(swiftType: SwiftType, config: Configuration) -> [JavaAnnotation] {
if swiftType.isUnsignedInteger, config.effectiveUnsignedNumbersMode == .annotate {
return [JavaAnnotation.unsigned]
}

return []
}
25 changes: 25 additions & 0 deletions Sources/JExtractSwiftLib/Configuration+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared
import JavaTypes // TODO: this should become SwiftJavaConfigurationShared

extension Configuration {
public var effectiveUnsignedNumericsMode: UnsignedNumericsMode {
switch effectiveUnsignedNumbersMode {
case .annotate: .ignoreSign
case .wrapGuava: .wrapUnsignedGuava
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,16 @@ extension FFMSwift2JavaGenerator {
var params: [String] = []
var args: [String] = []
for param in cFunc.parameters {
// ! unwrapping because cdecl lowering guarantees the parameter named.
params.append("\(param.type.javaType) \(param.name!)")
args.append(param.name!)
let name = param.name! // !-safe, because cdecl lowering guarantees the parameter named.

let annotationsStr =
if param.type.javaType.parameterAnnotations.isEmpty {
""
} else {
param.type.javaType.parameterAnnotations.map({$0.render()}).joined(separator: " ") + " "
}
params.append("\(annotationsStr)\(param.type.javaType) \(name)")
args.append(name)
}
let paramsStr = params.joined(separator: ", ")
let argsStr = args.joined(separator: ", ")
Expand Down Expand Up @@ -316,23 +323,21 @@ extension FFMSwift2JavaGenerator {
let translatedSignature = translated.translatedSignature
let returnTy = translatedSignature.result.javaResultType

var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n")
if !annotationsStr.isEmpty { annotationsStr += "\n" }

var paramDecls = translatedSignature.parameters
.flatMap(\.javaParameters)
.map { "\($0.type) \($0.name)" }
.map { $0.renderParameter() }
if translatedSignature.requiresSwiftArena {
paramDecls.append("AllocatingSwiftArena swiftArena$")
}

// TODO: we could copy the Swift method's documentation over here, that'd be great UX
printDeclDocumentation(&printer, decl)
printer.printBraceBlock(
"""
/**
* Downcall to Swift:
* {@snippet lang=swift :
* \(decl.signatureString)
* }
*/
\(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", ")))
\(annotationsStr)\(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", ")))
"""
) { printer in
if case .instance(_) = decl.functionSignature.selfParameter {
Expand All @@ -344,6 +349,19 @@ extension FFMSwift2JavaGenerator {
}
}

private func printDeclDocumentation(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
printer.print(
"""
/**
* Downcall to Swift:
* {@snippet lang=swift :
* \(decl.signatureString)
* }
*/
"""
)
}

/// Print the actual downcall to the Swift API.
///
/// This assumes that all the parameters are passed-in with appropriate names.
Expand Down
Loading
Loading