diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index f5b0b890d..94140cf64 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -270,6 +270,13 @@ extension JavaClassTranslator { /// Add a field to the appropriate lists(s) for later translation. private mutating func addField(_ field: Field) { + // Don't include inherited fields when translating to a class. + // This applies to both instance and static fields to avoid duplicates + if translateAsClass && + !field.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) { + return + } + // Static fields go into a separate list. if field.isStatic { staticFields.append(field) @@ -283,12 +290,6 @@ extension JavaClassTranslator { return } - // Don't include inherited fields when translating to a class. - if translateAsClass && - !field.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) { - return - } - fields.append(field) } diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift index 74ed3ce28..3738ebf4d 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift @@ -88,4 +88,45 @@ final class BasicWrapJavaTests: XCTestCase { ) } + + // Test that static fields from superclasses are not duplicated in generated code. + // This prevents duplicate serialVersionUID declarations when both a class and its + // superclass declare the field. The subclass field "hides" the superclass field, + // similar to how static methods work in Java. + func test_wrapJava_noDuplicateStaticFieldsFromSuperclass() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class SuperClass { + public static final long serialVersionUID = 1L; + } + + class SubClass extends SuperClass { + public static final long serialVersionUID = 2L; + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.SuperClass", + "com.example.SubClass" + ], + classpath: [classpathURL], + expectedChunks: [ + // SuperClass should have its static field + """ + extension JavaClass { + @JavaStaticField(isFinal: true) + public var serialVersionUID: Int64 + """, + // SubClass should only have its own static field, not the superclass one + """ + extension JavaClass { + @JavaStaticField(isFinal: true) + public var serialVersionUID: Int64 + """, + ] + ) + } } \ No newline at end of file