From af05e0aaa4a205337eb663a8278108ecde3b31c9 Mon Sep 17 00:00:00 2001 From: Stephan Diederich Date: Fri, 19 Dec 2025 17:30:00 +0100 Subject: [PATCH] fix `init` naming mismatch Java's `init` methods are bridged as is and made swift compatible via the backticks. At runtime though, this is forgotten and the java methods are looked up _with_ the backticks. This approach of fixing adds a `@JavaMethod("init")` annotation, which fixes the issue. (Though I'm not sure if this shouldn't be fixed in the generated macro code. Open for suggestions!) --- .../JavaClassTranslator.swift | 5 +++ .../WrapJavaTests/BasicWrapJavaTests.swift | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index f5b0b890d..fde2bd4e1 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -697,6 +697,11 @@ extension JavaClassTranslator { } // Do we need to record any generic information, in order to enable type-erasure for the upcalls? var parameters: [String] = [] + // If the method name is "init", we need to explicitly specify it in the annotation + // because "init" is a Swift keyword and will be escaped in the function name via `init` + if javaMethod.getName() == "init" { + parameters.append("\"init\"") + } if hasTypeEraseGenericResultType { parameters.append("typeErasedResult: \"\(resultType)\"") } diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift index 74ed3ce28..d376ab43c 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift @@ -88,4 +88,36 @@ final class BasicWrapJavaTests: XCTestCase { ) } + // Test that Java methods named "init" get @JavaMethod("init") annotation. + // Since "init" is a Swift keyword and gets escaped with backticks in the function name, + // we explicitly specify the Java method name in the annotation. + // See KeyAgreement.init() methods as a real-world example. + func test_wrapJava_initMethodAnnotation() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class TestClass { + public void init(String arg) throws Exception {} + public void init() throws Exception {} + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.TestClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaMethod("init") + open func `init`(_ arg0: String) throws + """, + """ + @JavaMethod("init") + open func `init`() throws + """, + ] + ) + } } \ No newline at end of file