diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 1c9477f11..9ccbc164b 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -23,6 +23,8 @@ import Glibc import CRT #elseif canImport(Darwin) import Darwin.C +#elseif canImport(Android) +import Android #endif public func helloWorld() { diff --git a/Sources/SwiftJava/AndroidSupport.swift b/Sources/SwiftJava/AndroidSupport.swift new file mode 100644 index 000000000..926049867 --- /dev/null +++ b/Sources/SwiftJava/AndroidSupport.swift @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 AndroidSupport { + /// Performs any known name conversions + /// for types that are desugared on specific Android versions + public static func androidDesugarClassNameConversion( + for fullClassName: String + ) -> String { +#if os(Android) && compiler(>=6.3) + switch fullClassName { + case "java.util.Optional": + // On API 23, Optionals are desugared + if #unavailable(Android 24) { + return "j$.util.Optional" + } + + default: + break + } +#endif + return fullClassName + } +} diff --git a/Sources/SwiftJavaMacros/JavaClassMacro.swift b/Sources/SwiftJavaMacros/JavaClassMacro.swift index 9a2dd4a58..1fcbf11fd 100644 --- a/Sources/SwiftJavaMacros/JavaClassMacro.swift +++ b/Sources/SwiftJavaMacros/JavaClassMacro.swift @@ -79,7 +79,7 @@ extension JavaClassMacro: MemberMacro { } var members: [DeclSyntax] = [] - + // Determine the modifiers to use for the fullJavaClassName member. let fullJavaClassNameMemberModifiers: String switch (isSwiftClass, isJavaLangObject) { @@ -94,7 +94,13 @@ extension JavaClassMacro: MemberMacro { let classNameAccessSpecifier = isSwiftClass ? "open" : "public" members.append(""" /// The full Java class name for this Swift type. - \(raw: classNameAccessSpecifier) \(raw: fullJavaClassNameMemberModifiers) var fullJavaClassName: String { \(literal: className) } + \(raw: classNameAccessSpecifier) \(raw: fullJavaClassNameMemberModifiers) var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "\(raw: className)") + #else + "\(raw: className)" + #endif + } """ ) diff --git a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift index 5cbeae162..85a124760 100644 --- a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift +++ b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift @@ -43,7 +43,11 @@ class JavaKitMacroTests: XCTestCase { /// The full Java class name for this Swift type. open override class var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "org.swift.example.HelloWorld") + #else "org.swift.example.HelloWorld" + #endif } public required init(javaHolder: JavaObjectHolder) { @@ -150,7 +154,11 @@ class JavaKitMacroTests: XCTestCase { /// The full Java class name for this Swift type. public static var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "org.swift.example.HelloWorld") + #else "org.swift.example.HelloWorld" + #endif } public typealias JavaSuperclass = JavaObject @@ -242,7 +250,11 @@ class JavaKitMacroTests: XCTestCase { /// The full Java class name for this Swift type. open override class var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "org.swift.example.HelloWorld") + #else "org.swift.example.HelloWorld" + #endif } public required init(javaHolder: JavaObjectHolder) { @@ -283,7 +295,11 @@ class JavaKitMacroTests: XCTestCase { /// The full Java class name for this Swift type. open class var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "java.lang.Object") + #else "java.lang.Object" + #endif } public var javaHolder: JavaObjectHolder @@ -319,7 +335,11 @@ class JavaKitMacroTests: XCTestCase { /// The full Java class name for this Swift type. open override class var fullJavaClassName: String { + #if os(Android) + AndroidSupport.androidDesugarClassNameConversion(for: "java.lang.Optional") + #else "java.lang.Optional" + #endif } public required init(javaHolder: JavaObjectHolder) {