From 1ed22ce30a91072565020c1826b01829edb25b9f Mon Sep 17 00:00:00 2001 From: Stephan Diederich Date: Fri, 19 Dec 2025 17:27:50 +0100 Subject: [PATCH] fix duplicated fields from superclass in case of duplicated properties, e.g. from a base class it was generating duplicate property definitions, e.g.: ``` extension JavaClass { @JavaStaticField(isFinal: true) public var serialVersionUID: Int64 @JavaStaticField(isFinal: true) public var serialVersionUID: Int64 } ``` (see e.g. https://docs.oracle.com/javase/8/docs/api/java/security/PrivateKey.html) which then fails the swift build. Analog to methods, this now skips the property in case it wasn't directly from the class itself. --- .../JavaClassTranslator.swift | 13 +++--- .../WrapJavaTests/BasicWrapJavaTests.swift | 41 +++++++++++++++++++ 2 files changed, 48 insertions(+), 6 deletions(-) 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