From 5e41003d8dda85fbf771e3d9cc1777d11bb22af0 Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 18 Jun 2026 15:32:05 +0900 Subject: [PATCH 1/3] Add URL generator support --- .../Sources/MySwiftLibrary/UUID.swift | 9 +++++++++ .../JNI/JNIJavaTypeTranslator.swift | 9 ++++++--- .../JNISwift2JavaGenerator+JavaTranslation.swift | 14 +++++--------- .../JNISwift2JavaGenerator+NativeTranslation.swift | 4 ++-- .../SwiftExtract/SwiftAnalyzer+Foundation.swift | 6 ++++++ .../SwiftTypes/SwiftKnownTypeDecls.swift | 8 ++++++++ .../SwiftExtract/SwiftTypes/SwiftKnownTypes.swift | 2 ++ 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift index 29769f3a0..e0ec68cab 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift @@ -27,3 +27,12 @@ public func echoUUID(_ uuid: UUID) -> UUID { public func makeUUID() -> UUID { UUID() } + +public func echoURL(_ url: URL) -> URL { + url +} + +public func makeURL() -> URL { + URL(string: "http://example.com")! +} + diff --git a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift index 3e7821d48..ea7f68317 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift @@ -53,7 +53,8 @@ enum JNIJavaTypeTranslator { .dictionary, .set, .foundationDate, .essentialsDate, - .foundationUUID, .essentialsUUID: + .foundationUUID, .essentialsUUID, + .foundationURL, .essentialsURL: return nil } } @@ -79,7 +80,8 @@ enum JNIJavaTypeTranslator { .dictionary, .set, .foundationDate, .essentialsDate, - .foundationUUID, .essentialsUUID: + .foundationUUID, .essentialsUUID, + .foundationURL, .essentialsURL: nil } } @@ -105,7 +107,8 @@ enum JNIJavaTypeTranslator { .dictionary, .set, .foundationDate, .essentialsDate, - .foundationUUID, .essentialsUUID: + .foundationUUID, .essentialsUUID, + .foundationURL, .essentialsURL: nil } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 00c606d66..f4a5f5f1a 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -438,10 +438,7 @@ extension JNISwift2JavaGenerator { genericRequirements: genericRequirements, ) - case .foundationDate, .essentialsDate: - break // Handled as wrapped struct - - case .foundationData, .essentialsData: + case .foundationDate, .essentialsDate, .foundationData, .essentialsData, .foundationURL, .essentialsURL: break // Handled as wrapped struct case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: @@ -877,11 +874,7 @@ extension JNISwift2JavaGenerator { genericRequirements: genericRequirements, ) - case .foundationDate, .essentialsDate: - // Handled as wrapped struct - break - - case .foundationData, .essentialsData: + case .foundationDate, .essentialsDate, .foundationData, .essentialsData, .foundationURL, .essentialsURL: // Handled as wrapped struct break @@ -1043,6 +1036,9 @@ extension JNISwift2JavaGenerator { case .foundationDataProtocol, .essentialsDataProtocol: return .class(package: nil, name: "DataProtocol") + case .foundationURL, .essentialsURL: + return .class(package: nil, name: "URL") + case .foundationUUID, .essentialsUUID: return .javaUtilUUID diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index fe67b5221..60bc9b707 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -145,7 +145,7 @@ extension JNISwift2JavaGenerator { conversionCheck: nil ) - case .foundationDate, .essentialsDate, .foundationData, .essentialsData: + case .foundationDate, .essentialsDate, .foundationData, .essentialsData, .foundationURL, .essentialsURL: // Handled as wrapped struct break @@ -743,7 +743,7 @@ extension JNISwift2JavaGenerator { resultName: resultName ) - case .foundationDate, .essentialsDate, .foundationData, .essentialsData: + case .foundationDate, .essentialsDate, .foundationData, .essentialsData, .foundationURL, .essentialsURL: // Handled as wrapped struct break diff --git a/Sources/SwiftExtract/SwiftAnalyzer+Foundation.swift b/Sources/SwiftExtract/SwiftAnalyzer+Foundation.swift index 720ed4de1..c9f23cfc4 100644 --- a/Sources/SwiftExtract/SwiftAnalyzer+Foundation.swift +++ b/Sources/SwiftExtract/SwiftAnalyzer+Foundation.swift @@ -47,6 +47,12 @@ extension SwiftAnalyzer { fakeSourceFilePath: "Foundation/FAKE_FOUNDATION_UUID.swift", ) ], + [ + .init( + candidates: [.foundationURL, .essentialsURL], + fakeSourceFilePath: "Foundation/FAKE_FOUNDATION_URL.swift", + ) + ], ] for group in groups { diff --git a/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypeDecls.swift index 7b4ea12ea..53ee8101a 100644 --- a/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypeDecls.swift @@ -52,6 +52,8 @@ public enum SwiftKnownType: Equatable { case essentialsDate case foundationUUID case essentialsUUID + case foundationURL + case essentialsURL public init?(kind: SwiftKnownTypeDeclKind, genericArguments: [SwiftType]?) { switch kind { @@ -106,6 +108,8 @@ public enum SwiftKnownType: Equatable { case .essentialsDate: self = .essentialsDate case .foundationUUID: self = .foundationUUID case .essentialsUUID: self = .essentialsUUID + case .foundationURL: self = .foundationURL + case .essentialsURL: self = .essentialsURL } } @@ -146,6 +150,8 @@ public enum SwiftKnownType: Equatable { case .essentialsDate: .essentialsDate case .foundationUUID: .foundationUUID case .essentialsUUID: .essentialsUUID + case .foundationURL: .foundationURL + case .essentialsURL: .essentialsURL } } } @@ -189,6 +195,8 @@ public enum SwiftKnownTypeDeclKind: String, Hashable { case essentialsDate = "FoundationEssentials.Date" case foundationUUID = "Foundation.UUID" case essentialsUUID = "FoundationEssentials.UUID" + case foundationURL = "Foundation.URL" + case essentialsURL = "FoundationEssentials.URL" public var moduleAndName: (module: String, name: String) { let qualified = self.rawValue diff --git a/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypes.swift b/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypes.swift index 6c9c93a5d..953e8f0bc 100644 --- a/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypes.swift +++ b/Sources/SwiftExtract/SwiftTypes/SwiftKnownTypes.swift @@ -51,6 +51,8 @@ public struct SwiftKnownTypes { public var essentialsData: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsData])) } public var foundationUUID: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.foundationUUID])) } public var essentialsUUID: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsUUID])) } + public var foundationURL: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.foundationURL])) } + public var essentialsURL: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsURL])) } /// `(UnsafeRawPointer, Long) -> ()` function type. /// From fe98e20db858b67b3b0a0a4a4bfd9879f8180639 Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 18 Jun 2026 15:43:45 +0900 Subject: [PATCH 2/3] Update tests in JNI example --- .../Sources/MySwiftLibrary/Date.swift | 29 -------------- .../{UUID.swift => FoundationTypes.swift} | 11 +++++- ...{DateTest.java => FoundationTypeTest.java} | 30 +++++++++++++-- .../test/java/com/example/swift/UUIDTest.java | 38 ------------------- 4 files changed, 36 insertions(+), 72 deletions(-) delete mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift rename Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/{UUID.swift => FoundationTypes.swift} (75%) rename Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/{DateTest.java => FoundationTypeTest.java} (73%) delete mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/UUIDTest.java diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift deleted file mode 100644 index 5d700e0d7..000000000 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift +++ /dev/null @@ -1,29 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 SwiftJava - -#if canImport(FoundationEssentials) -import FoundationEssentials -#else -import Foundation -#endif - -public func compareDates(date1: Date, date2: Date) -> Bool { - date1 == date2 -} - -public func dateFromSeconds(_ seconds: Double) -> Date { - Date(timeIntervalSince1970: seconds) -} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift similarity index 75% rename from Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift index e0ec68cab..692746243 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -20,6 +20,14 @@ import FoundationEssentials import Foundation #endif +public func compareDates(date1: Date, date2: Date) -> Bool { + date1 == date2 +} + +public func dateFromSeconds(_ seconds: Double) -> Date { + Date(timeIntervalSince1970: seconds) +} + public func echoUUID(_ uuid: UUID) -> UUID { uuid } @@ -35,4 +43,3 @@ public func echoURL(_ url: URL) -> URL { public func makeURL() -> URL { URL(string: "http://example.com")! } - diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/FoundationTypeTest.java similarity index 73% rename from Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/FoundationTypeTest.java index 9b13f37ec..a789bb206 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/FoundationTypeTest.java @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -19,10 +19,11 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; -public class DateTest { +public class FoundationTypeTest { @Test void date_functions() { try (var arena = SwiftArena.ofConfined()) { @@ -59,4 +60,27 @@ void date_timeIntervalSince1970() { assertEquals(1000, date.getTimeIntervalSince1970()); } } -} \ No newline at end of file + + @Test + void echoUUID() { + var uuid = UUID.randomUUID(); + assertEquals(uuid, MySwiftLibrary.echoUUID(uuid)); + } + + @Test + void makeUUID() { + var uuid = MySwiftLibrary.makeUUID(); + assertEquals(4, uuid.version()); + } + + @Test + void echoURL() { + try (var arena = SwiftArena.ofConfined()) { + var url = URL.init("http://example.com", arena); + assertDoesNotThrow(() -> { + var unwrapped = url.orElseThrow(); + assertEquals("http://example.com", unwrapped.getAbsoluteString()); + }); + } + } +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/UUIDTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/UUIDTest.java deleted file mode 100644 index b06592e48..000000000 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/UUIDTest.java +++ /dev/null @@ -1,38 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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.core.SwiftArena; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.UUID; - -import static org.junit.jupiter.api.Assertions.*; - -public class UUIDTest { - @Test - void echoUUID() { - var uuid = UUID.randomUUID(); - assertEquals(uuid, MySwiftLibrary.echoUUID(uuid)); - } - - @Test - void makeUUID() { - var uuid = MySwiftLibrary.makeUUID(); - assertEquals(4, uuid.version()); - } -} \ No newline at end of file From 8b72d2c10c7646a8b34fef43492d6a28106ccfe2 Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 18 Jun 2026 15:48:20 +0900 Subject: [PATCH 3/3] Remove unused func --- .../Sources/MySwiftLibrary/FoundationTypes.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift index 692746243..9d4ea6ff3 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift @@ -39,7 +39,3 @@ public func makeUUID() -> UUID { public func echoURL(_ url: URL) -> URL { url } - -public func makeURL() -> URL { - URL(string: "http://example.com")! -}