From de290a94d1c753da31420b66afaac5d6351264a1 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Tue, 15 Oct 2024 18:57:58 -0400 Subject: [PATCH 01/11] First pass --- Sources/Java2SwiftLib/JavaTranslator.swift | 21 +++++++++++++++++++ .../JavaClass+Reflection.swift | 6 ++++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 20 +++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index fa7e5789..412648a9 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -194,6 +194,15 @@ extension JavaTranslator { let fullName = javaClass.getCanonicalName() let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) + for internalClass in javaClass.getClasses() { + if let internalClass { + print("Translating name \(internalClass.getName())") + let internalJavaClassName = internalClass.getName() + let translatedInternalSwiftName = internalJavaClassName.replacing("$", with: ".") + translatedClasses[translatedInternalSwiftName] = ("\(swiftTypeName).\(internalClass.getSimpleName())", nil, true) + } + } + // Superclass. let extends: String if !javaClass.isInterface(), @@ -239,6 +248,18 @@ extension JavaTranslator { // Members var members: [DeclSyntax] = [] + members.append( + contentsOf: javaClass.getClasses().compactMap { + $0.flatMap { clazz in + let text = translateClass(clazz) + text.map { t in t.formatted().description } + .forEach { t in print(t) } + print() + return text + } + }.flatMap(\.self) + ) + // Fields var staticFields: [Field] = [] var enumConstants: [Field] = [] diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index 569b72e8..461fda6b 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -37,4 +37,10 @@ extension JavaClass { @JavaMethod public func getGenericInterfaces() -> [Type?] + + @JavaMethod + public func isInterface() -> Bool + + @JavaMethod + public func getClasses() -> [JavaClass?] } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index a2e3cb34..5231eca7 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -24,9 +24,9 @@ var jvm: JavaVirtualMachine { } @JavaClass("java.time.Month") -public struct JavaMonth { - -} +public struct JavaMonth {} +@JavaClass("java.lang.ProcessBuilder") +struct ProcessBuilder {} class Java2SwiftTests: XCTestCase { func testJavaLangObjectMapping() throws { @@ -114,6 +114,18 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testNestedSubclasses() async throws { + try assertTranslatedClass( + ProcessBuilder.self, + swiftTypeName: "ProcessBuilder", + expectedChunks: [ + "import JavaKit", + "" + ] + ) + } + } @JavaClass("java.util.ArrayList") @@ -145,6 +157,7 @@ func assertTranslatedClass( translator.translatedClasses = translatedClasses translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) + translator.startNewFile() let translatedDecls = translator.translateClass( try JavaClass( @@ -160,6 +173,7 @@ func assertTranslatedClass( """ for expectedChunk in expectedChunks { + print(swiftFileText) if swiftFileText.contains(expectedChunk) { continue } From f18d3276fbec5683300ea1b70fae19c673a6de88 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Tue, 15 Oct 2024 20:40:15 -0400 Subject: [PATCH 02/11] Keep going --- Sources/Java2Swift/JavaToSwift.swift | 37 +++++++++++++++++++ Sources/Java2SwiftLib/JavaTranslator.swift | 30 +++++---------- .../JavaClass+Reflection.swift | 6 --- Tests/Java2SwiftTests/Java2SwiftTests.swift | 6 +++ 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 80058ccd..8f3992ae 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -228,6 +228,13 @@ struct JavaToSwift: ParsableCommand { // Note that we will be translating this Java class, so it is a known class. translator.translatedClasses[javaClassName] = (translatedSwiftName, nil, true) + + for internalClass in javaClass.getClasses() { + if let internalClass { + let (javaName, swiftName) = names(from: internalClass.getCanonicalName()) + translator.translatedClasses[internalClass.getCanonicalName()] = (swiftName.replacing("$", with: "."), nil, true) + } + } } // Translate all of the Java classes into Swift classes. @@ -252,6 +259,36 @@ struct JavaToSwift: ParsableCommand { } } + private func names(from javaClassNameOpt: String) -> (javaClassName: String, swiftName: String) { + let javaClassName: String + let swiftName: String + if let equalLoc = javaClassNameOpt.firstIndex(of: "=") { + let afterEqual = javaClassNameOpt.index(after: equalLoc) + javaClassName = String(javaClassNameOpt[.. [Type?] - - @JavaMethod - public func isInterface() -> Bool - - @JavaMethod - public func getClasses() -> [JavaClass?] } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 5231eca7..37bda0c4 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -119,6 +119,12 @@ class Java2SwiftTests: XCTestCase { try assertTranslatedClass( ProcessBuilder.self, swiftTypeName: "ProcessBuilder", + translatedClasses: [ + "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), + "java.lang.ProcessBuilder.Redirect": ("ProcessBuilder.Redirect", nil, true), + "java.lang.ProcessBuilder.Redirect.Type": ("ProcessBuilder.Redirect.Type", nil, true), + "java.lang.Enum.EnumDesc": ("Enum.EnumDesc", nil, true) + ], expectedChunks: [ "import JavaKit", "" From 720c2cf8586b8109d905c73121a420f37b747b8e Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Tue, 15 Oct 2024 23:50:01 -0400 Subject: [PATCH 03/11] Add Tests for Subclasses --- Sources/Java2Swift/JavaToSwift.swift | 20 ++++++++++++++++++-- Sources/Java2SwiftLib/JavaTranslator.swift | 16 ++++++++++++---- Tests/Java2SwiftTests/Java2SwiftTests.swift | 14 +++++++++++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 8f3992ae..c83520ce 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -229,10 +229,26 @@ struct JavaToSwift: ParsableCommand { // Note that we will be translating this Java class, so it is a known class. translator.translatedClasses[javaClassName] = (translatedSwiftName, nil, true) - for internalClass in javaClass.getClasses() { + var classes: [(classToImport: JavaClass?, prefix: String)] = javaClass.getClasses().map { ($0, translatedSwiftName) } + + // Go through all subclasses to find all of the classes to translate + while let (internalClass, prefix) = classes.popLast() { if let internalClass { let (javaName, swiftName) = names(from: internalClass.getCanonicalName()) - translator.translatedClasses[internalClass.getCanonicalName()] = (swiftName.replacing("$", with: "."), nil, true) + // If we have already been through this class, don't go through it again + guard translator.translatedClasses[javaName] == nil else { continue } + let currentClassName: String + // If the prefix is the part of the canonical name, continue (else use the same) + // This is needed since `java.lang.Enum.EnumDesc` is one of the declared classes of all of the enums + if (internalClass.getCanonicalName().contains(prefix)) { + currentClassName = "\(prefix).\(swiftName)" + } else { + currentClassName = swiftName + } + + let currentSanitizedClassName = currentClassName.replacing("$", with: ".") + classes.append(contentsOf: internalClass.getClasses().map { ($0, currentSanitizedClassName) }) + translator.translatedClasses[javaName] = (currentSanitizedClassName, nil, true) } } } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index de974377..e331e7fd 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -193,6 +193,15 @@ extension JavaTranslator { package func translateClass(_ javaClass: JavaClass) -> [DeclSyntax] { let fullName = javaClass.getCanonicalName() let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) + let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() + + // If the swift parent type has not been translated, don't try to translate this one + if let swiftParentType, + !translatedClasses.contains(where: { _, value in value.swiftType == swiftParentType }) + { + logUntranslated("Unable to translate '\(fullName)' parent class: \(swiftParentType) not found") + return [] + } // Superclass. let extends: String @@ -356,13 +365,12 @@ extension JavaTranslator { staticMemberWhereClause = "" } - // Emit the struct declaration describing the java class. - let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() + // Emit the struct declaration describing the java class. Add backticks to the name since the type might interfere with Swift type names let classOrInterface: String = javaClass.isInterface() ? "JavaInterface" : "JavaClass"; var classDecl = """ @\(raw:classOrInterface)(\(literal: fullName)\(raw: extends)\(raw: interfacesStr)) - public struct \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { + public struct `\(raw: swiftInnermostTypeName)`\(raw: genericParameterClause) { \(raw: members.map { $0.description }.joined(separator: "\n\n")) } """ as DeclSyntax @@ -382,6 +390,7 @@ extension JavaTranslator { classDecl = classDecl.formatted(using: format).cast(DeclSyntax.self) topLevelDecls.append(classDecl) + let subClassDecls = javaClass.getClasses().compactMap { $0.flatMap { clazz in return translateClass(clazz) @@ -391,7 +400,6 @@ extension JavaTranslator { topLevelDecls.append( contentsOf: subClassDecls ) - // Translate static members. var staticMembers: [DeclSyntax] = [] diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 37bda0c4..8070569c 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -37,7 +37,7 @@ class Java2SwiftTests: XCTestCase { "import JavaKit", """ @JavaClass("java.lang.Object") - public struct MyJavaObject { + public struct `MyJavaObject` { """, """ @JavaMethod @@ -127,7 +127,16 @@ class Java2SwiftTests: XCTestCase { ], expectedChunks: [ "import JavaKit", - "" + """ + extension ProcessBuilder { + @JavaClass("java.lang.ProcessBuilder.Redirect") + public struct `Redirect` { + """, + """ + extension ProcessBuilder.Redirect { + @JavaClass("java.lang.ProcessBuilder.Redirect.Type") + public struct `Type` { + """ ] ) } @@ -179,7 +188,6 @@ func assertTranslatedClass( """ for expectedChunk in expectedChunks { - print(swiftFileText) if swiftFileText.contains(expectedChunk) { continue } From 2f246e49f4e7df4a2622bec2b0aa60eb3258a9aa Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Sun, 20 Oct 2024 12:46:01 -0400 Subject: [PATCH 04/11] Fix issues with nested classes --- Sources/Java2Swift/JavaToSwift.swift | 13 ++----------- Sources/Java2SwiftLib/JavaTranslator.swift | 11 ++++++++--- Tests/Java2SwiftTests/Java2SwiftTests.swift | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index c83520ce..754755dc 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -243,7 +243,7 @@ struct JavaToSwift: ParsableCommand { if (internalClass.getCanonicalName().contains(prefix)) { currentClassName = "\(prefix).\(swiftName)" } else { - currentClassName = swiftName + continue // If we have a class that is not a nested one, ignore it } let currentSanitizedClassName = currentClassName.replacing("$", with: ".") @@ -256,7 +256,7 @@ struct JavaToSwift: ParsableCommand { // Translate all of the Java classes into Swift classes. for javaClass in javaClasses { translator.startNewFile() - let swiftClassDecls = translator.translateClass(javaClass) + let swiftClassDecls = try! translator.translateClass(javaClass) let importDecls = translator.getImportDecls() let swiftFileText = """ @@ -296,15 +296,6 @@ struct JavaToSwift: ParsableCommand { return (javaClassName, swiftName) } - /// Return the class path augmented with the Jar file, if there is one. - var classPathWithJarFile: [String] { - if jarFile { - return [input] + classpath - } - - return classpath - } - mutating func writeContents(_ contents: String, to filename: String, description: String) throws { guard let outputDir = actualOutputDirectory else { print("// \(filename) - \(description)") diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index e331e7fd..c3196a01 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -190,9 +190,9 @@ extension JavaTranslator { /// Translates the given Java class into the corresponding Swift type. This /// can produce multiple declarations, such as a separate extension of /// JavaClass to house static methods. - package func translateClass(_ javaClass: JavaClass) -> [DeclSyntax] { + package func translateClass(_ javaClass: JavaClass) throws -> [DeclSyntax] { let fullName = javaClass.getCanonicalName() - let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) + let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName) let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() // If the swift parent type has not been translated, don't try to translate this one @@ -393,7 +393,12 @@ extension JavaTranslator { let subClassDecls = javaClass.getClasses().compactMap { $0.flatMap { clazz in - return translateClass(clazz) + do { + return try translateClass(clazz) + } catch { + logUntranslated("Unable to translate '\(fullName)' subclass '\(clazz.getName())': \(error)") + return nil + } } }.flatMap(\.self) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 8070569c..6507afa5 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -174,8 +174,8 @@ func assertTranslatedClass( translator.startNewFile() - let translatedDecls = translator.translateClass( - try JavaClass( + let translatedDecls = try translator.translateClass( + JavaClass( javaThis: javaType.getJNIClass(in: environment), environment: environment) ) From 2a37c208d9ac187c05a216a47c71c6464d2a252f Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:20:44 -0400 Subject: [PATCH 05/11] Remove $ checks --- Sources/Java2Swift/JavaToSwift.swift | 5 ----- Tests/Java2SwiftTests/Java2SwiftTests.swift | 1 - 2 files changed, 6 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 754755dc..5a0460ed 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -342,11 +342,6 @@ struct JavaToSwift: ParsableCommand { } } - // TODO: For now, skip all nested classes. - if entry.getName().contains("$") { - continue - } - let javaCanonicalName = String(entry.getName().replacing("/", with: ".") .dropLast(".class".count)) configuration.classes[javaCanonicalName] = diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 6507afa5..b2d6a9b8 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -123,7 +123,6 @@ class Java2SwiftTests: XCTestCase { "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), "java.lang.ProcessBuilder.Redirect": ("ProcessBuilder.Redirect", nil, true), "java.lang.ProcessBuilder.Redirect.Type": ("ProcessBuilder.Redirect.Type", nil, true), - "java.lang.Enum.EnumDesc": ("Enum.EnumDesc", nil, true) ], expectedChunks: [ "import JavaKit", From 647d99335c966b38a01f9d727423995035ab7bea Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:30:39 -0400 Subject: [PATCH 06/11] Correctly support $ --- Sources/Java2Swift/JavaToSwift.swift | 20 ++++++-------------- Sources/Java2SwiftLib/JavaTranslator.swift | 10 +++++----- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 5a0460ed..706c4819 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -229,25 +229,17 @@ struct JavaToSwift: ParsableCommand { // Note that we will be translating this Java class, so it is a known class. translator.translatedClasses[javaClassName] = (translatedSwiftName, nil, true) - var classes: [(classToImport: JavaClass?, prefix: String)] = javaClass.getClasses().map { ($0, translatedSwiftName) } + var classes: [JavaClass?] = javaClass.getClasses() // Go through all subclasses to find all of the classes to translate - while let (internalClass, prefix) = classes.popLast() { + while let internalClass = classes.popLast() { if let internalClass { - let (javaName, swiftName) = names(from: internalClass.getCanonicalName()) + let (javaName, swiftName) = names(from: internalClass.getName()) // If we have already been through this class, don't go through it again guard translator.translatedClasses[javaName] == nil else { continue } - let currentClassName: String - // If the prefix is the part of the canonical name, continue (else use the same) - // This is needed since `java.lang.Enum.EnumDesc` is one of the declared classes of all of the enums - if (internalClass.getCanonicalName().contains(prefix)) { - currentClassName = "\(prefix).\(swiftName)" - } else { - continue // If we have a class that is not a nested one, ignore it - } - + let currentClassName = swiftName let currentSanitizedClassName = currentClassName.replacing("$", with: ".") - classes.append(contentsOf: internalClass.getClasses().map { ($0, currentSanitizedClassName) }) + classes.append(contentsOf: internalClass.getClasses()) translator.translatedClasses[javaName] = (currentSanitizedClassName, nil, true) } } @@ -270,7 +262,7 @@ struct JavaToSwift: ParsableCommand { try writeContents( swiftFileText, to: swiftFileName, - description: "Java class '\(javaClass.getCanonicalName())' translation" + description: "Java class '\(javaClass.getName())' translation" ) } } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index c3196a01..c2c6cfe2 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -191,7 +191,7 @@ extension JavaTranslator { /// can produce multiple declarations, such as a separate extension of /// JavaClass to house static methods. package func translateClass(_ javaClass: JavaClass) throws -> [DeclSyntax] { - let fullName = javaClass.getCanonicalName() + let fullName = javaClass.getName() let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName) let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() @@ -207,7 +207,7 @@ extension JavaTranslator { let extends: String if !javaClass.isInterface(), let superclass = javaClass.getSuperclass(), - superclass.getCanonicalName() != "java.lang.Object" + superclass.getName() != "java.lang.Object" { do { extends = ", extends: \(try getSwiftTypeName(superclass).swiftName).self" @@ -287,7 +287,7 @@ extension JavaTranslator { do { let implementedInSwift = constructor.isNative && constructor.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getCanonicalName()) + swiftNativeImplementations.contains(javaClass.getName()) let translated = try translateConstructor( constructor, @@ -321,7 +321,7 @@ extension JavaTranslator { let implementedInSwift = method.isNative && method.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getCanonicalName()) + swiftNativeImplementations.contains(javaClass.getName()) // Translate the method if we can. do { @@ -460,7 +460,7 @@ extension JavaTranslator { // Members that are native and will instead go into a NativeMethods // protocol. var nativeMembers: [DeclSyntax] = [] - if swiftNativeImplementations.contains(javaClass.getCanonicalName()) { + if swiftNativeImplementations.contains(javaClass.getName()) { nativeMembers.append( contentsOf: javaClass.getDeclaredMethods().compactMap { $0.flatMap { method in From 49c6818d5ac796693eb279439c09477758f3dde6 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:33:11 -0400 Subject: [PATCH 07/11] remove tick --- Sources/Java2SwiftLib/JavaTranslator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index c2c6cfe2..4c953445 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -370,7 +370,7 @@ extension JavaTranslator { var classDecl = """ @\(raw:classOrInterface)(\(literal: fullName)\(raw: extends)\(raw: interfacesStr)) - public struct `\(raw: swiftInnermostTypeName)`\(raw: genericParameterClause) { + public struct \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { \(raw: members.map { $0.description }.joined(separator: "\n\n")) } """ as DeclSyntax From e12d92d29fd22edd1aff7e1e511ce8ca9615c836 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:37:00 -0400 Subject: [PATCH 08/11] Add Subclass Generated --- Sources/JavaKitJar/generated/Attributes.swift | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 22aa68a4..74a1352c 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -44,6 +44,9 @@ public struct Attributes { @JavaMethod public func getValue(_ arg0: String) -> String + @JavaMethod + public func getValue(_ arg0: Attributes.Name?) -> String + @JavaMethod public func isEmpty() -> Bool @@ -95,3 +98,92 @@ public struct Attributes { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? } +extension Attributes { + @JavaClass("java.util.jar.Attributes$Name") + public struct Name { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension JavaClass { + @JavaStaticField + public var MANIFEST_VERSION: Attributes.Name? + + @JavaStaticField + public var SIGNATURE_VERSION: Attributes.Name? + + @JavaStaticField + public var CONTENT_TYPE: Attributes.Name? + + @JavaStaticField + public var CLASS_PATH: Attributes.Name? + + @JavaStaticField + public var MAIN_CLASS: Attributes.Name? + + @JavaStaticField + public var SEALED: Attributes.Name? + + @JavaStaticField + public var EXTENSION_LIST: Attributes.Name? + + @JavaStaticField + public var EXTENSION_NAME: Attributes.Name? + + @JavaStaticField + public var EXTENSION_INSTALLATION: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_TITLE: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VERSION: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VENDOR: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VENDOR_ID: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_URL: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_TITLE: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_VERSION: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_VENDOR: Attributes.Name? + + @JavaStaticField + public var MULTI_RELEASE: Attributes.Name? +} From 82e86fd5f87e40fd88c4884a79bfa989b5c53026 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:42:56 -0400 Subject: [PATCH 09/11] Update enums and tests --- Sources/Java2SwiftLib/JavaTranslator.swift | 2 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 4c953445..fe429515 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -274,7 +274,7 @@ extension JavaTranslator { ) if !enumConstants.isEmpty { - let enumName = "\(swiftTypeName)Cases" + let enumName = "\(swiftTypeName.splitSwiftTypeName().name)Cases" members.append( contentsOf: translateToEnumValue(name: enumName, enumFields: enumConstants) ) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index b2d6a9b8..cdab4d4a 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -37,7 +37,7 @@ class Java2SwiftTests: XCTestCase { "import JavaKit", """ @JavaClass("java.lang.Object") - public struct `MyJavaObject` { + public struct MyJavaObject { """, """ @JavaMethod @@ -121,20 +121,24 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "ProcessBuilder", translatedClasses: [ "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), - "java.lang.ProcessBuilder.Redirect": ("ProcessBuilder.Redirect", nil, true), - "java.lang.ProcessBuilder.Redirect.Type": ("ProcessBuilder.Redirect.Type", nil, true), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil, true), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil, true), ], expectedChunks: [ "import JavaKit", + """ + @JavaMethod + public func redirectInput() -> ProcessBuilder.Redirect? + """, """ extension ProcessBuilder { - @JavaClass("java.lang.ProcessBuilder.Redirect") - public struct `Redirect` { + @JavaClass("java.lang.ProcessBuilder$Redirect") + public struct Redirect { """, """ extension ProcessBuilder.Redirect { - @JavaClass("java.lang.ProcessBuilder.Redirect.Type") - public struct `Type` { + @JavaClass("java.lang.ProcessBuilder$Redirect$Type") + public struct Type { """ ] ) From 3e86f7016aef7baff33fa3b9b2ab62bc8f23c09d Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Fri, 25 Oct 2024 21:46:49 -0400 Subject: [PATCH 10/11] Fix incorrect comment --- Sources/Java2SwiftLib/JavaTranslator.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index fe429515..c6a5a54e 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -207,7 +207,7 @@ extension JavaTranslator { let extends: String if !javaClass.isInterface(), let superclass = javaClass.getSuperclass(), - superclass.getName() != "java.lang.Object" + superclass.getName() != "java.lang.Object" { do { extends = ", extends: \(try getSwiftTypeName(superclass).swiftName).self" @@ -365,7 +365,7 @@ extension JavaTranslator { staticMemberWhereClause = "" } - // Emit the struct declaration describing the java class. Add backticks to the name since the type might interfere with Swift type names + // Emit the struct declaration describing the java class. let classOrInterface: String = javaClass.isInterface() ? "JavaInterface" : "JavaClass"; var classDecl = """ From c0f6321bac1537494e2ce8160c73e0f44d3b08c3 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Sat, 26 Oct 2024 08:46:53 -0400 Subject: [PATCH 11/11] Some pr feedback --- Sources/Java2Swift/JavaToSwift.swift | 2 +- Sources/Java2SwiftLib/JavaTranslator.swift | 2 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 706c4819..86d3cf8d 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -248,7 +248,7 @@ struct JavaToSwift: ParsableCommand { // Translate all of the Java classes into Swift classes. for javaClass in javaClasses { translator.startNewFile() - let swiftClassDecls = try! translator.translateClass(javaClass) + let swiftClassDecls = try translator.translateClass(javaClass) let importDecls = translator.getImportDecls() let swiftFileText = """ diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index c6a5a54e..cf04ba79 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -274,7 +274,7 @@ extension JavaTranslator { ) if !enumConstants.isEmpty { - let enumName = "\(swiftTypeName.splitSwiftTypeName().name)Cases" + let enumName = "\(swiftInnermostTypeName)Cases" members.append( contentsOf: translateToEnumValue(name: enumName, enumFields: enumConstants) ) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index cdab4d4a..5d446162 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -115,7 +115,7 @@ class Java2SwiftTests: XCTestCase { ) } - func testNestedSubclasses() async throws { + func testNestedSubclasses() throws { try assertTranslatedClass( ProcessBuilder.self, swiftTypeName: "ProcessBuilder",