Skip to content

Commit 69a4bff

Browse files
iDevidktoso
andauthored
Fix Java package mapping for dependent modules (#699)
Co-authored-by: Konrad Malawski <ktoso@apple.com>
1 parent 2c3fff8 commit 69a4bff

12 files changed

Lines changed: 104 additions & 56 deletions

File tree

Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ private let SwiftJavaConfigFileName = "swift-java.config"
2020
@main
2121
struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
2222

23+
struct DependentConfigFile {
24+
let swiftModuleName: String
25+
let configURL: URL
26+
}
27+
2328
var pluginName: String = "swift-java"
2429
var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE")
2530

@@ -78,11 +83,10 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
7883
arguments += ["--static-build-config", resolvedURL.absoluteURL.path(percentEncoded: false)]
7984
}
8085

81-
let dependentConfigFilesArguments = dependentConfigFiles.flatMap { moduleAndConfigFile in
82-
let (moduleName, configFile) = moduleAndConfigFile
83-
return [
86+
let dependentConfigFilesArguments = dependentConfigFiles.flatMap { dependentConfigFile in
87+
[
8488
"--depends-on",
85-
"\(moduleName)=\(configFile.path(percentEncoded: false))",
89+
"\(dependentConfigFile.swiftModuleName)=\(dependentConfigFile.configURL.path(percentEncoded: false))",
8690
]
8791
}
8892
arguments += dependentConfigFilesArguments
@@ -270,8 +274,8 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
270274

271275
/// Find the manifest files from other swift-java executions in any targets
272276
/// this target depends on.
273-
func searchForDependentConfigFiles(in target: any Target) -> [(String, URL)] {
274-
var dependentConfigFiles = [(String, URL)]()
277+
func searchForDependentConfigFiles(in target: any Target) -> [DependentConfigFile] {
278+
var dependentConfigFiles: [DependentConfigFile] = []
275279

276280
func _searchForConfigFiles(in target: any Target) {
277281
// log("Search for config files in target: \(target.name)")
@@ -286,7 +290,9 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
286290
.path(percentEncoded: false)
287291

288292
if FileManager.default.fileExists(atPath: dependencyConfigString) {
289-
dependentConfigFiles.append((target.name, dependencyConfigURL))
293+
dependentConfigFiles.append(
294+
DependentConfigFile(swiftModuleName: target.name, configURL: dependencyConfigURL)
295+
)
290296
}
291297
}
292298

Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ private let SwiftJavaConfigFileName = "swift-java.config"
1919

2020
@main
2121
struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
22+
struct DependentConfigFile {
23+
let swiftModuleName: String
24+
let configURL: URL
25+
}
2226

2327
var pluginName: String = "swift-java"
2428
var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE")
@@ -46,7 +50,7 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
4650

4751
/// Find the manifest files from other swift-java executions in any targets
4852
/// this target depends on.
49-
var dependentConfigFiles: [(String, URL)] = []
53+
var dependentConfigFiles: [DependentConfigFile] = []
5054
func searchForConfigFiles(in target: any Target) {
5155
// log("Search for config files in target: \(target.name)")
5256
let dependencyURL = target.directoryURL
@@ -60,7 +64,9 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin {
6064
.path(percentEncoded: false)
6165

6266
if FileManager.default.fileExists(atPath: dependencyConfigString) {
63-
dependentConfigFiles.append((target.name, dependencyConfigURL))
67+
dependentConfigFiles.append(
68+
DependentConfigFile(swiftModuleName: target.name, configURL: dependencyConfigURL)
69+
)
6470
}
6571
}
6672

@@ -223,12 +229,11 @@ extension SwiftJavaBuildToolPlugin {
223229
]
224230
}
225231

226-
func argumentsDependedOnConfigs(_ dependentConfigFiles: [(String, URL)]) -> [String] {
227-
dependentConfigFiles.flatMap { moduleAndConfigFile in
228-
let (moduleName, configFile) = moduleAndConfigFile
229-
return [
232+
func argumentsDependedOnConfigs(_ dependentConfigFiles: [DependentConfigFile]) -> [String] {
233+
dependentConfigFiles.flatMap { dependentConfigFile in
234+
[
230235
"--depends-on",
231-
"\(moduleName)=\(configFile.path(percentEncoded: false))",
236+
"\(dependentConfigFile.swiftModuleName)=\(dependentConfigFile.configURL.path(percentEncoded: false))",
232237
]
233238
}
234239
}

Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import SwiftJavaJNICore
1616

1717
extension JavaType {
18+
1819
var jniTypeSignature: String {
1920
switch self {
2021
case .boolean: return "Z"

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extension JNISwift2JavaGenerator {
2323
swiftModuleName: swiftModuleName,
2424
javaPackage: self.javaPackage,
2525
javaClassLookupTable: self.javaClassLookupTable,
26+
moduleJavaPackages: self.moduleJavaPackages,
2627
knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable),
2728
protocolWrappers: self.interfaceProtocolWrappers,
2829
logger: self.logger,
@@ -64,6 +65,7 @@ extension JNISwift2JavaGenerator {
6465
swiftModuleName: swiftModuleName,
6566
javaPackage: self.javaPackage,
6667
javaClassLookupTable: self.javaClassLookupTable,
68+
moduleJavaPackages: self.moduleJavaPackages,
6769
knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable),
6870
protocolWrappers: self.interfaceProtocolWrappers,
6971
logger: self.logger,
@@ -85,6 +87,7 @@ extension JNISwift2JavaGenerator {
8587
let swiftModuleName: String
8688
let javaPackage: String
8789
let javaClassLookupTable: JavaClassLookupTable
90+
let moduleJavaPackages: ModuleJavaPackages
8891
var knownTypes: SwiftKnownTypes
8992
let protocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper]
9093
let logger: Logger
@@ -546,7 +549,7 @@ extension JNISwift2JavaGenerator {
546549
}
547550

548551
let javaType = JavaType.class(
549-
package: nil,
552+
package: moduleJavaPackages[nominalType.nominalTypeDecl.moduleName],
550553
name: nominalTypeName,
551554
typeParameters: try nominalType.genericArguments?.map { swiftType in
552555
try translateGenericTypeParameter(
@@ -982,7 +985,7 @@ extension JNISwift2JavaGenerator {
982985
}
983986

984987
let javaType = JavaType.class(
985-
package: nil,
988+
package: moduleJavaPackages[nominalType.nominalTypeDecl.moduleName],
986989
name: nominalType.nominalTypeDecl.qualifiedName,
987990
typeParameters: try nominalType.genericArguments?.map { swiftType in
988991
try translateGenericTypeParameter(
@@ -1131,7 +1134,7 @@ extension JNISwift2JavaGenerator {
11311134
} ?? []
11321135

11331136
return .class(
1134-
package: nil,
1137+
package: moduleJavaPackages[nominalType.nominalTypeDecl.moduleName],
11351138
name: nominalTypeName,
11361139
typeParameters: typeParameters,
11371140
)
@@ -1512,7 +1515,7 @@ extension JNISwift2JavaGenerator {
15121515
],
15131516
),
15141517
function: "toArray",
1515-
arguments: [.constant("\(javaType.className!)[]::new")]
1518+
arguments: [.constant("\(javaType.fullyQualifiedClassName!)[]::new")]
15161519
)
15171520
)
15181521

@@ -1914,7 +1917,7 @@ extension JNISwift2JavaGenerator {
19141917

19151918
case .wrapMemoryAddressUnsafe(let inner, let javaType):
19161919
let inner = inner.render(&printer, placeholder)
1917-
guard case .class(_, let className, let typeParameters) = javaType else {
1920+
guard case .class(_, _, let typeParameters) = javaType else {
19181921
fatalError("\(javaType) is not class.")
19191922
}
19201923
let genericClause =
@@ -1923,7 +1926,7 @@ extension JNISwift2JavaGenerator {
19231926
} else {
19241927
""
19251928
}
1926-
return "\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
1929+
return "\(javaType.fullyQualifiedClassName!).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
19271930

19281931
case .constructJavaClass(let inner, let javaType):
19291932
let inner = inner.render(&printer, placeholder)

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import SwiftJavaJNICore
2020
/// the fully qualified canoical names.
2121
package typealias JavaClassLookupTable = [String: String]
2222

23+
/// A table where keys are Swift module names and the values are Java package names.
24+
package typealias ModuleJavaPackages = [String: String]
25+
2326
package class JNISwift2JavaGenerator: Swift2JavaGenerator {
2427

2528
let logger: Logger
@@ -32,6 +35,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator {
3235
let lookupContext: SwiftTypeLookupContext
3336

3437
let javaClassLookupTable: JavaClassLookupTable
38+
let moduleJavaPackages: ModuleJavaPackages
3539

3640
var javaPackagePath: String {
3741
javaPackage.replacingOccurrences(of: ".", with: "/")
@@ -75,6 +79,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator {
7579
swiftOutputDirectory: String,
7680
javaOutputDirectory: String,
7781
javaClassLookupTable: JavaClassLookupTable,
82+
moduleJavaPackages: ModuleJavaPackages,
7883
) {
7984
self.config = config
8085
self.logger = Logger(label: "jni-generator", logLevel: translator.log.logLevel)
@@ -84,6 +89,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator {
8489
self.swiftOutputDirectory = swiftOutputDirectory
8590
self.javaOutputDirectory = javaOutputDirectory
8691
self.javaClassLookupTable = javaClassLookupTable
92+
self.moduleJavaPackages = moduleJavaPackages
8793
self.lookupContext = translator.lookupContext
8894

8995
// If we are forced to write empty files, construct the expected outputs.

Sources/JExtractSwiftLib/Swift2Java.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import SwiftSyntaxBuilder
2121

2222
public struct SwiftToJava {
2323
let config: Configuration
24-
let dependentConfigs: [Configuration]
24+
let dependentConfigs: [DependentConfig]
2525

26-
public init(config: Configuration, dependentConfigs: [Configuration]) {
26+
public init(config: Configuration, dependentConfigs: [DependentConfig]) {
2727
self.config = config
2828
self.dependentConfigs = dependentConfigs
2929
}
@@ -95,12 +95,23 @@ public struct SwiftToJava {
9595
fatalError("Missing --output-java directory!")
9696
}
9797

98-
let wrappedJavaClassesLookupTable: JavaClassLookupTable = dependentConfigs.compactMap(\.classes).reduce(into: [:]) {
98+
let wrappedJavaClassesLookupTable: JavaClassLookupTable = dependentConfigs.compactMap(\.configuration.classes).reduce(into: [:]) {
9999
for (canonicalName, javaClass) in $1 {
100100
$0[javaClass] = canonicalName
101101
}
102102
}
103103

104+
let moduleJavaPackages = dependentConfigs.reduce(into: [String: String]()) { partialResult, dependency in
105+
guard
106+
let moduleName = dependency.swiftModuleName,
107+
let javaPackage = dependency.configuration.javaPackage,
108+
!javaPackage.isEmpty
109+
else {
110+
return
111+
}
112+
partialResult[moduleName] = javaPackage
113+
}
114+
104115
translator.dependenciesClasses = Array(wrappedJavaClassesLookupTable.keys)
105116

106117
try translator.analyze()
@@ -124,7 +135,8 @@ public struct SwiftToJava {
124135
javaPackage: config.javaPackage ?? "",
125136
swiftOutputDirectory: outputSwiftDirectory,
126137
javaOutputDirectory: outputJavaDirectory,
127-
javaClassLookupTable: wrappedJavaClassesLookupTable
138+
javaClassLookupTable: wrappedJavaClassesLookupTable,
139+
moduleJavaPackages: moduleJavaPackages
128140
)
129141

130142
try generator.generate()

Sources/SwiftJavaConfigurationShared/Configuration.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,19 @@ public func readConfiguration(
426426
}
427427
}
428428

429-
/// Load all dependent configs configured with `--depends-on` and return a list of
430-
/// `(SwiftModuleName, Configuration)` tuples.
431-
public func loadDependentConfigs(dependsOn: [String]) throws -> [(String?, Configuration)] {
429+
/// Parsed dependent configuration provided via `--depends-on`.
430+
public struct DependentConfig {
431+
public let swiftModuleName: String?
432+
public let configuration: Configuration
433+
434+
public init(swiftModuleName: String?, configuration: Configuration) {
435+
self.swiftModuleName = swiftModuleName
436+
self.configuration = configuration
437+
}
438+
}
439+
440+
/// Load all dependent configs configured with `--depends-on`.
441+
public func loadDependentConfigs(dependsOn: [String]) throws -> [DependentConfig] {
432442
try dependsOn.map { dependentConfig in
433443
let equalLoc = dependentConfig.firstIndex(of: "=")
434444

@@ -442,7 +452,7 @@ public func loadDependentConfigs(dependsOn: [String]) throws -> [(String?, Confi
442452

443453
let config = try readConfiguration(configPath: URL(fileURLWithPath: configFileName)) ?? Configuration()
444454

445-
return (swiftModuleName, config)
455+
return DependentConfig(swiftModuleName: swiftModuleName, configuration: config)
446456
}
447457
}
448458

Sources/SwiftJavaTool/Commands/JExtractCommand.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ extension SwiftJava.JExtractCommand {
178178
let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn)
179179
print("[debug][swift-java] Dependent configs: \(dependentConfigs.count)")
180180

181-
try jextractSwift(config: config, dependentConfigs: dependentConfigs.map(\.1))
181+
try jextractSwift(config: config, dependentConfigs: dependentConfigs)
182182
}
183183

184184
/// Check if the configured modes are compatible, and fail if not
@@ -207,7 +207,7 @@ struct IncompatibleModeError: Error {
207207
extension SwiftJava.JExtractCommand {
208208
func jextractSwift(
209209
config: Configuration,
210-
dependentConfigs: [Configuration],
210+
dependentConfigs: [DependentConfig],
211211
) throws {
212212
try SwiftToJava(config: config, dependentConfigs: dependentConfigs).run()
213213
}

Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ extension SwiftJava {
7878
}
7979

8080
extension SwiftJava.WrapJavaCommand {
81+
struct NamedDependentConfig {
82+
let swiftModuleName: String
83+
let configuration: Configuration
84+
}
8185

8286
mutating func runSwiftJavaCommand(config: inout Configuration) async throws {
8387
print("self.filterInclude = \(self.filterInclude)")
@@ -101,23 +105,23 @@ extension SwiftJava.WrapJavaCommand {
101105
)
102106

103107
// Load all of the dependent configurations and associate them with Swift modules.
104-
let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn).map { moduleName, config in
105-
guard let moduleName else {
108+
let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn).map { dependentConfig in
109+
guard let moduleName = dependentConfig.swiftModuleName else {
106110
throw JavaToSwiftError.badConfigOption(self.dependsOn.joined(separator: " "))
107111
}
108-
return (moduleName, config)
112+
return NamedDependentConfig(swiftModuleName: moduleName, configuration: dependentConfig.configuration)
109113
}
110114
print("[debug][swift-java] Dependent configs: \(dependentConfigs.count)")
111115

112116
// Include classpath entries which libs we depend on require...
113-
for (fromModule, config) in dependentConfigs {
117+
for dependentConfig in dependentConfigs {
114118
print(
115-
"[trace][swift-java] Add dependent config (\(fromModule)) classpath elements: \(config.classpathEntries.count)"
119+
"[trace][swift-java] Add dependent config (\(dependentConfig.swiftModuleName)) classpath elements: \(dependentConfig.configuration.classpathEntries.count)"
116120
)
117121
// TODO: may need to resolve the dependent configs rather than just get their configs
118122
// TODO: We should cache the resolved classpaths as well so we don't do it many times
119-
for entry in config.classpathEntries {
120-
print("[trace][swift-java] Add dependent config (\(fromModule)) classpath element: \(entry)")
123+
for entry in dependentConfig.configuration.classpathEntries {
124+
print("[trace][swift-java] Add dependent config (\(dependentConfig.swiftModuleName)) classpath element: \(entry)")
121125
classpathEntries.append(entry)
122126
}
123127
}
@@ -137,7 +141,7 @@ extension SwiftJava.WrapJavaCommand {
137141

138142
mutating func generateWrappers(
139143
config: Configuration,
140-
dependentConfigs: [(String, Configuration)],
144+
dependentConfigs: [NamedDependentConfig],
141145
environment: JNIEnvironment
142146
) throws {
143147
let translator = JavaTranslator(
@@ -163,10 +167,10 @@ extension SwiftJava.WrapJavaCommand {
163167
}
164168

165169
// Note all of the dependent configurations.
166-
for (swiftModuleName, dependentConfig) in dependentConfigs {
170+
for dependentConfig in dependentConfigs {
167171
translator.addConfiguration(
168-
dependentConfig,
169-
forSwiftModule: swiftModuleName
172+
dependentConfig.configuration,
173+
forSwiftModule: dependentConfig.swiftModuleName
170174
)
171175
}
172176

Tests/JExtractSwiftTests/Asserts/TextAssertions.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ func assertOutput(
7373
javaPackage: "com.example.swift",
7474
swiftOutputDirectory: "/fake",
7575
javaOutputDirectory: "/fake",
76-
javaClassLookupTable: javaClassLookupTable
76+
javaClassLookupTable: javaClassLookupTable,
77+
moduleJavaPackages: [:]
7778
)
7879

7980
switch renderKind {

0 commit comments

Comments
 (0)