diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift similarity index 77% rename from Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/FoundationTypes.swift index 5d700e0d7..9d4ea6ff3 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Date.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 @@ -27,3 +27,15 @@ public func compareDates(date1: Date, date2: Date) -> Bool { public func dateFromSeconds(_ seconds: Double) -> Date { Date(timeIntervalSince1970: seconds) } + +public func echoUUID(_ uuid: UUID) -> UUID { + uuid +} + +public func makeUUID() -> UUID { + UUID() +} + +public func echoURL(_ url: URL) -> URL { + url +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.swift deleted file mode 100644 index 29769f3a0..000000000 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/UUID.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 echoUUID(_ uuid: UUID) -> UUID { - uuid -} - -public func makeUUID() -> UUID { - UUID() -} 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 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. ///