|
2 | 2 | //
|
3 | 3 | // This source file is part of the Swift.org open source project
|
4 | 4 | //
|
5 |
| -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors |
| 5 | +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors |
6 | 6 | // Licensed under Apache License v2.0
|
7 | 7 | //
|
8 | 8 | // See LICENSE.txt for license information
|
|
13 | 13 | //===----------------------------------------------------------------------===//
|
14 | 14 |
|
15 | 15 | import JavaTypes
|
16 |
| -import SwiftSyntax |
17 |
| -import SwiftSyntaxBuilder |
18 |
| - |
19 |
| -// ==== --------------------------------------------------------------------------------------------------------------- |
20 |
| -// MARK: File writing |
21 |
| - |
22 |
| -let PATH_SEPARATOR = "/" // TODO: Windows |
23 |
| - |
24 |
| -extension Swift2JavaTranslator { |
25 |
| - |
26 |
| - /// Every imported public type becomes a public class in its own file in Java. |
27 |
| - public func writeJavaBindingsSources(outputDirectory: String) throws { |
28 |
| - var printer = CodePrinter() |
29 |
| - try writeJavaBindingsSources(outputDirectory: outputDirectory, printer: &printer) |
30 |
| - } |
31 |
| - |
32 |
| - public func writeJavaBindingsSources(outputDirectory: String, printer: inout CodePrinter) throws { |
33 |
| - for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { |
34 |
| - let filename = "\(ty.swiftNominal.name).java" |
35 |
| - log.info("Printing contents: \(filename)") |
36 |
| - printImportedNominal(&printer, ty) |
37 |
| - |
38 |
| - if let outputFile = try printer.writeContents( |
39 |
| - outputDirectory: outputDirectory, |
40 |
| - javaPackagePath: javaPackagePath, |
41 |
| - filename: filename |
42 |
| - ) { |
43 |
| - print("[swift-java] Generated: \(ty.swiftNominal.name.bold).java (at \(outputFile))") |
44 |
| - } |
45 |
| - } |
46 |
| - |
47 |
| - do { |
48 |
| - let filename = "\(self.swiftModuleName).java" |
49 |
| - log.info("Printing contents: \(filename)") |
50 |
| - printModule(&printer) |
51 |
| - |
52 |
| - if let outputFile = try printer.writeContents( |
53 |
| - outputDirectory: outputDirectory, |
54 |
| - javaPackagePath: javaPackagePath, |
55 |
| - filename: filename) |
56 |
| - { |
57 |
| - print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") |
58 |
| - } |
59 |
| - } |
60 |
| - } |
61 |
| -} |
62 |
| - |
63 |
| -// ==== --------------------------------------------------------------------------------------------------------------- |
64 |
| -// MARK: Java/text printing |
65 | 16 |
|
66 | 17 | extension Swift2JavaTranslator {
|
67 |
| - |
68 |
| - /// Render the Java file contents for an imported Swift module. |
69 |
| - /// |
70 |
| - /// This includes any Swift global functions in that module, and some general type information and helpers. |
71 |
| - public func printModule(_ printer: inout CodePrinter) { |
72 |
| - printHeader(&printer) |
73 |
| - printPackage(&printer) |
74 |
| - printImports(&printer) |
75 |
| - |
76 |
| - printModuleClass(&printer) { printer in |
77 |
| - // TODO: print all "static" methods |
78 |
| - for decl in importedGlobalFuncs { |
79 |
| - self.log.trace("Print imported decl: \(decl)") |
80 |
| - printFunctionDowncallMethods(&printer, decl) |
81 |
| - } |
82 |
| - } |
83 |
| - } |
84 |
| - |
85 |
| - package func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { |
86 |
| - printHeader(&printer) |
87 |
| - printPackage(&printer) |
88 |
| - printImports(&printer) |
89 |
| - |
90 |
| - printNominal(&printer, decl) { printer in |
91 |
| - // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static. |
92 |
| - // We call into source swift-java source generated accessors which give us the type of the Swift object: |
93 |
| - // TODO: seems we no longer need the mangled name per se, so avoiding such constant and downcall |
94 |
| - // printer.printParts( |
95 |
| - // "public static final String TYPE_MANGLED_NAME = ", |
96 |
| - // SwiftKitPrinting.renderCallGetSwiftTypeMangledName(module: self.swiftModuleName, nominal: decl), |
97 |
| - // ";" |
98 |
| - // ) |
99 |
| - |
100 |
| - // We use a static field to abuse the initialization order such that by the time we get type metadata, |
101 |
| - // we already have loaded the library where it will be obtained from. |
102 |
| - printer.printParts( |
103 |
| - """ |
104 |
| - @SuppressWarnings("unused") |
105 |
| - private static final boolean INITIALIZED_LIBS = initializeLibs(); |
106 |
| - static boolean initializeLibs() { |
107 |
| - System.loadLibrary(SwiftKit.STDLIB_DYLIB_NAME); |
108 |
| - System.loadLibrary("SwiftKitSwift"); |
109 |
| - System.loadLibrary(LIB_NAME); |
110 |
| - return true; |
111 |
| - } |
112 |
| -
|
113 |
| - public static final SwiftAnyType TYPE_METADATA = |
114 |
| - new SwiftAnyType(\(SwiftKitPrinting.renderCallGetSwiftType(module: self.swiftModuleName, nominal: decl))); |
115 |
| - public final SwiftAnyType $swiftType() { |
116 |
| - return TYPE_METADATA; |
117 |
| - } |
118 |
| - """ |
119 |
| - ) |
120 |
| - printer.println() |
121 |
| - |
122 |
| - // Layout of the class |
123 |
| - printClassMemoryLayout(&printer, decl) |
124 |
| - |
125 |
| - printer.println() |
126 |
| - |
127 |
| - printer.print( |
128 |
| - """ |
129 |
| - public \(decl.swiftNominal.name)(MemorySegment segment, SwiftArena arena) { |
130 |
| - super(segment, arena); |
131 |
| - } |
132 |
| - """ |
133 |
| - ) |
134 |
| - |
135 |
| - // Initializers |
136 |
| - for initDecl in decl.initializers { |
137 |
| - printInitializerDowncallConstructors(&printer, initDecl) |
138 |
| - } |
139 |
| - |
140 |
| - // Properties |
141 |
| - for accessorDecl in decl.variables { |
142 |
| - printFunctionDowncallMethods(&printer, accessorDecl) |
143 |
| - } |
144 |
| - |
145 |
| - // Methods |
146 |
| - for funcDecl in decl.methods { |
147 |
| - printFunctionDowncallMethods(&printer, funcDecl) |
148 |
| - } |
149 |
| - |
150 |
| - // Helper methods and default implementations |
151 |
| - printToStringMethod(&printer, decl) |
152 |
| - } |
153 |
| - } |
154 |
| - |
155 |
| - public func printHeader(_ printer: inout CodePrinter) { |
156 |
| - printer.print( |
157 |
| - """ |
158 |
| - // Generated by jextract-swift |
159 |
| - // Swift module: \(swiftModuleName) |
160 |
| -
|
161 |
| - """ |
162 |
| - ) |
163 |
| - } |
164 |
| - |
165 |
| - public func printPackage(_ printer: inout CodePrinter) { |
166 |
| - printer.print( |
167 |
| - """ |
168 |
| - package \(javaPackage); |
169 |
| -
|
170 |
| - """ |
171 |
| - ) |
172 |
| - } |
173 |
| - |
174 |
| - public func printImports(_ printer: inout CodePrinter) { |
175 |
| - for i in Swift2JavaTranslator.defaultJavaImports { |
176 |
| - printer.print("import \(i);") |
177 |
| - } |
178 |
| - printer.print("") |
179 |
| - } |
180 |
| - |
181 |
| - package func printNominal( |
182 |
| - _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void |
183 |
| - ) { |
184 |
| - let baseProtocol = decl.swiftNominal.isReferenceType ? "SwiftHeapObject" : "SwiftValue" |
185 |
| - |
186 |
| - printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends SwiftInstance implements \(baseProtocol)") { printer in |
187 |
| - // Constants |
188 |
| - printClassConstants(printer: &printer) |
189 |
| - |
190 |
| - body(&printer) |
191 |
| - } |
192 |
| - } |
193 |
| - |
194 |
| - public func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { |
195 |
| - printer.printBraceBlock("public final class \(swiftModuleName)") { printer in |
196 |
| - printPrivateConstructor(&printer, swiftModuleName) |
197 |
| - |
198 |
| - // Constants |
199 |
| - printClassConstants(printer: &printer) |
200 |
| - |
201 |
| - printer.print( |
202 |
| - """ |
203 |
| - static MemorySegment findOrThrow(String symbol) { |
204 |
| - return SYMBOL_LOOKUP.find(symbol) |
205 |
| - .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); |
206 |
| - } |
207 |
| - """ |
208 |
| - ) |
209 |
| - |
210 |
| - printer.print( |
211 |
| - """ |
212 |
| - static MethodHandle upcallHandle(Class<?> fi, String name, FunctionDescriptor fdesc) { |
213 |
| - try { |
214 |
| - return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); |
215 |
| - } catch (ReflectiveOperationException ex) { |
216 |
| - throw new AssertionError(ex); |
217 |
| - } |
218 |
| - } |
219 |
| - """ |
220 |
| - ) |
221 |
| - |
222 |
| - printer.print( |
223 |
| - """ |
224 |
| - static MemoryLayout align(MemoryLayout layout, long align) { |
225 |
| - return switch (layout) { |
226 |
| - case PaddingLayout p -> p; |
227 |
| - case ValueLayout v -> v.withByteAlignment(align); |
228 |
| - case GroupLayout g -> { |
229 |
| - MemoryLayout[] alignedMembers = g.memberLayouts().stream() |
230 |
| - .map(m -> align(m, align)).toArray(MemoryLayout[]::new); |
231 |
| - yield g instanceof StructLayout ? |
232 |
| - MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); |
233 |
| - } |
234 |
| - case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); |
235 |
| - }; |
236 |
| - } |
237 |
| - """ |
238 |
| - ) |
239 |
| - |
240 |
| - // SymbolLookup.libraryLookup is platform dependent and does not take into account java.library.path |
241 |
| - // https://bugs.openjdk.org/browse/JDK-8311090 |
242 |
| - printer.print( |
243 |
| - """ |
244 |
| - static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); |
245 |
| - private static SymbolLookup getSymbolLookup() { |
246 |
| - // Ensure Swift and our Lib are loaded during static initialization of the class. |
247 |
| - SwiftKit.loadLibrary("swiftCore"); |
248 |
| - SwiftKit.loadLibrary("SwiftKitSwift"); |
249 |
| - SwiftKit.loadLibrary(LIB_NAME); |
250 |
| -
|
251 |
| - if (PlatformUtils.isMacOS()) { |
252 |
| - return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) |
253 |
| - .or(SymbolLookup.loaderLookup()) |
254 |
| - .or(Linker.nativeLinker().defaultLookup()); |
255 |
| - } else { |
256 |
| - return SymbolLookup.loaderLookup() |
257 |
| - .or(Linker.nativeLinker().defaultLookup()); |
258 |
| - } |
259 |
| - } |
260 |
| - """ |
261 |
| - ) |
262 |
| - |
263 |
| - body(&printer) |
264 |
| - } |
265 |
| - } |
266 |
| - |
267 |
| - private func printClassConstants(printer: inout CodePrinter) { |
268 |
| - printer.print( |
269 |
| - """ |
270 |
| - static final String LIB_NAME = "\(swiftModuleName)"; |
271 |
| - static final Arena LIBRARY_ARENA = Arena.ofAuto(); |
272 |
| - """ |
273 |
| - ) |
274 |
| - } |
275 |
| - |
276 |
| - private func printPrivateConstructor(_ printer: inout CodePrinter, _ typeName: String) { |
277 |
| - printer.print( |
278 |
| - """ |
279 |
| - private \(typeName)() { |
280 |
| - // Should not be called directly |
281 |
| - } |
282 |
| -
|
283 |
| - // Static enum to force initialization |
284 |
| - private static enum Initializer { |
285 |
| - FORCE; // Refer to this to force outer Class initialization (and static{} blocks to trigger) |
286 |
| - } |
287 |
| - """ |
288 |
| - ) |
289 |
| - } |
290 |
| - |
291 |
| - private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { |
292 |
| - printer.print( |
293 |
| - """ |
294 |
| - private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); |
295 |
| - public static final GroupLayout $LAYOUT() { |
296 |
| - return $LAYOUT; |
297 |
| - } |
298 |
| - public final GroupLayout $layout() { |
299 |
| - return $LAYOUT; |
300 |
| - } |
301 |
| - """ |
302 |
| - ) |
303 |
| - } |
304 |
| - |
305 | 18 | public func printInitializerDowncallConstructors(
|
306 | 19 | _ printer: inout CodePrinter,
|
307 | 20 | _ decl: ImportedFunc
|
@@ -582,23 +295,6 @@ extension Swift2JavaTranslator {
|
582 | 295 | fatalError("renderMemoryLayoutValue not supported for \(javaType)")
|
583 | 296 | }
|
584 | 297 | }
|
585 |
| - |
586 |
| - package func printToStringMethod( |
587 |
| - _ printer: inout CodePrinter, _ decl: ImportedNominalType |
588 |
| - ) { |
589 |
| - printer.print( |
590 |
| - """ |
591 |
| - @Override |
592 |
| - public String toString() { |
593 |
| - return getClass().getSimpleName() |
594 |
| - + "(" |
595 |
| - + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) |
596 |
| - + ")@" |
597 |
| - + $memorySegment(); |
598 |
| - } |
599 |
| - """) |
600 |
| - } |
601 |
| - |
602 | 298 | }
|
603 | 299 |
|
604 | 300 | extension JavaConversionStep {
|
|
0 commit comments