From fa6bf76ec591f05a9422a42a7ec79b640e0c8a15 Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 9 Apr 2026 15:40:27 -0400 Subject: [PATCH] Enable Bundle bridging --- .../SkipBuild/Commands/VerifyCommand.swift | 11 +++++++--- .../Kotlin/KotlinBundleTransformer.swift | 21 ++++++++----------- .../SkipSyntaxTests/BridgeToKotlinTests.swift | 20 +++++++----------- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Sources/SkipBuild/Commands/VerifyCommand.swift b/Sources/SkipBuild/Commands/VerifyCommand.swift index 1e024c1b..cf179266 100644 --- a/Sources/SkipBuild/Commands/VerifyCommand.swift +++ b/Sources/SkipBuild/Commands/VerifyCommand.swift @@ -211,9 +211,6 @@ extension ToolOptionsCommand where Self : StreamingCommand { let packageJSON = try await parseSwiftPackage(with: out, at: projectPath) let packageName = packageJSON.name - guard let moduleName = packageJSON.products.first?.name else { - throw AppVerifyError(errorDescription: "No products declared in package \(packageName) at \(projectPath)") - } //let project = try FrameworkProjectLayout(root: projectFolderURL) //let sourcesDir = URL(fileURLWithPath: "Sources", isDirectory: true, relativeTo: projectFolderURL) @@ -259,6 +256,14 @@ extension ToolOptionsCommand where Self : StreamingCommand { throw MissingProjectFileError(errorDescription: "Expected path at \(url.path) does not exist") } + guard let firstProduct = packageJSON.products.first else { + throw AppVerifyError(errorDescription: "No products declared in package \(packageName) at \(projectPath)") + } + + guard let moduleName = firstProduct.targets.first else { + throw AppVerifyError(errorDescription: "The products \(firstProduct) declared in package \(packageName) at \(projectPath) has no targets") + } + let project = try AppProjectLayout(moduleName: moduleName, root: projectFolderURL, check: validateLayoutURL) await checkFile(project.skipEnv, with: out) { title, url in diff --git a/Sources/SkipSyntax/Kotlin/KotlinBundleTransformer.swift b/Sources/SkipSyntax/Kotlin/KotlinBundleTransformer.swift index 9a02d3e4..1d77c6b7 100644 --- a/Sources/SkipSyntax/Kotlin/KotlinBundleTransformer.swift +++ b/Sources/SkipSyntax/Kotlin/KotlinBundleTransformer.swift @@ -88,27 +88,24 @@ public final class KotlinBundleTransformer: KotlinTransformer { let className = moduleBundleAccessorClassName(moduleName: moduleName) let outputNode = SwiftDefinition { output, indentation, _ in // The blank line after the SkipBridge import is expected by our bridge testing + // the unusedp_0 param is needed or else error: initializer 'init(path:)' declared in 'Bundle' cannot be overridden from extension output.append(""" import SkipBridge import Foundation import SkipAndroidBridge - typealias Bundle = AndroidModuleBundle - class AndroidModuleBundle : AndroidBundle, @unchecked Sendable { - required init(_ bundle: SkipAndroidBridge.BundleAccess) { - super.init(bundle) - } - - init?(path: String) { - super.init(path: path, moduleName: "\(moduleName)") { + public typealias Bundle = AndroidBundle + + // Interceptor for initializing a Bundle with a path + // (either manually or through the synthesized Bundle.module property), + // which forwards the bundle access up to the Android asset manager + extension AndroidBundle { + convenience init?(path: String, unusedp_0: Void? = nil) { + self.init(path: path, moduleName: "\(moduleName)") { try! AnyDynamicObject(className: "\(packageName).\(className)").moduleBundle! } } - - override init?(url: URL) { - super.init(url: url) - } } let NSLocalizedString = AndroidLocalizedString() diff --git a/Tests/SkipSyntaxTests/BridgeToKotlinTests.swift b/Tests/SkipSyntaxTests/BridgeToKotlinTests.swift index cc591d46..e3ad0aec 100644 --- a/Tests/SkipSyntaxTests/BridgeToKotlinTests.swift +++ b/Tests/SkipSyntaxTests/BridgeToKotlinTests.swift @@ -9044,21 +9044,17 @@ final class BridgeToKotlinTests: XCTestCase { import Foundation import SkipAndroidBridge - typealias Bundle = AndroidModuleBundle - class AndroidModuleBundle : AndroidBundle, @unchecked Sendable { - required init(_ bundle: SkipAndroidBridge.BundleAccess) { - super.init(bundle) - } - - init?(path: String) { - super.init(path: path, moduleName: "") { + public typealias Bundle = AndroidBundle + + // Interceptor for initializing a Bundle with a path + // (either manually or through the synthesized Bundle.module property), + // which forwards the bundle access up to the Android asset manager + extension AndroidBundle { + convenience init?(path: String, unusedp_0: Void? = nil) { + self.init(path: path, moduleName: "") { try! AnyDynamicObject(className: ".module._ModuleBundleAccessor_").moduleBundle! } } - - override init?(url: URL) { - super.init(url: url) - } } let NSLocalizedString = AndroidLocalizedString()