forked from swiftlang/swift-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJNISwift2JavaGenerator.swift
More file actions
119 lines (103 loc) · 4.45 KB
/
JNISwift2JavaGenerator.swift
File metadata and controls
119 lines (103 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//===----------------------------------------------------------------------===//
//
// 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 CodePrinting
import SwiftJavaConfigurationShared
import SwiftJavaJNICore
/// A table that where keys are Swift class names and the values are
/// the fully qualified canoical names.
package typealias JavaClassLookupTable = [String: String]
package class JNISwift2JavaGenerator: Swift2JavaGenerator {
let logger: Logger
let config: Configuration
let analysis: AnalysisResult
let swiftModuleName: String
let javaPackage: String
let swiftOutputDirectory: String
let javaOutputDirectory: String
let lookupContext: SwiftTypeLookupContext
let javaClassLookupTable: JavaClassLookupTable
var javaPackagePath: String {
javaPackage.replacingOccurrences(of: ".", with: "/")
}
var thunkNameRegistry = ThunkNameRegistry()
/// Cached Java translation result. 'nil' indicates failed translation.
var translatedDecls: [ImportedFunc: TranslatedFunctionDecl] = [:]
var translatedEnumCases: [ImportedEnumCase: TranslatedEnumCase] = [:]
var interfaceProtocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper] = [:]
/// Duplicate identifier tracking for the current batch of methods being generated.
var currentJavaIdentifiers: JavaIdentifierFactory = JavaIdentifierFactory()
/// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet,
/// and write an empty file for those.
///
/// Since Swift files in SwiftPM builds needs to be unique, we use this fact to flatten paths into plain names here.
/// For uniqueness checking "did we write this file already", just checking the name should be sufficient.
var expectedOutputSwiftFileNames: Set<String>
package init(
config: Configuration,
translator: Swift2JavaTranslator,
javaPackage: String,
swiftOutputDirectory: String,
javaOutputDirectory: String,
javaClassLookupTable: JavaClassLookupTable
) {
self.config = config
self.logger = Logger(label: "jni-generator", logLevel: translator.log.logLevel)
self.analysis = translator.result
self.swiftModuleName = translator.swiftModuleName
self.javaPackage = javaPackage
self.swiftOutputDirectory = swiftOutputDirectory
self.javaOutputDirectory = javaOutputDirectory
self.javaClassLookupTable = javaClassLookupTable
self.lookupContext = translator.lookupContext
// If we are forced to write empty files, construct the expected outputs.
// It is sufficient to use file names only, since SwiftPM requires names to be unique within a module anyway.
if translator.config.writeEmptyFiles ?? false {
self.expectedOutputSwiftFileNames = Set(
translator.inputs.compactMap { (input) -> String? in
guard let fileName = input.path.split(separator: PATH_SEPARATOR).last else {
return nil
}
guard fileName.hasSuffix(".swift") else {
return nil
}
return String(fileName.replacing(".swift", with: "+SwiftJava.swift"))
}
)
self.expectedOutputSwiftFileNames.insert("\(translator.swiftModuleName)Module+SwiftJava.swift")
self.expectedOutputSwiftFileNames.insert("Foundation+SwiftJava.swift")
} else {
self.expectedOutputSwiftFileNames = []
}
if translator.config.enableJavaCallbacks ?? false {
// We translate all the protocol wrappers
// as we need them to know what protocols we can allow the user to implement themselves
// in Java.
self.interfaceProtocolWrappers = self.generateInterfaceWrappers(Array(self.analysis.importedTypes.values))
}
}
func generate() throws {
try writeSwiftThunkSources()
try writeExportedJavaSources()
let pendingFileCount = self.expectedOutputSwiftFileNames.count
if pendingFileCount > 0 {
print("[swift-java] Write empty [\(pendingFileCount)] 'expected' files in: \(swiftOutputDirectory)/")
try writeSwiftExpectedEmptySources()
}
}
}
extension JNISwift2JavaGenerator {
static func indirectVariableName(for parameterName: String) -> String {
"\(parameterName)$indirect"
}
}