Skip to content

jextract: keep Swift names that are Java keywords out of generated Java - #954

Merged
ktoso merged 1 commit into
swiftlang:mainfrom
piercifani:jextract-java-identifiers
Nov 8, 2026
Merged

ktoso merged 1 commit into
swiftlang:mainfrom
piercifani:jextract-java-identifiers

Conversation

@piercifani

Copy link
Copy Markdown
Contributor

Problem

In JNI mode, Swift names that are Java keywords, or that Swift writes with backticks, reached the generated Java as they are:

public func automationTag(price: Int64, long: Bool) -> String
public func scale(double: Double, int: Int64, `default`: Bool) -> Double
public enum Pricing { case quote(slug: String, long: Int64) }
public struct Side { public static var `default`: Side }
public func wait()

That generated:

  • boolean long and long int as parameters;
  • record Quote(java.lang.String slug, long long);
  • get`default`();
  • a wait() that redeclares Object.wait().

None of it compiles with javac. The Swift thunks broke the same way for parameters named class or default.

JNIJavaKitTests even expected long int as a Java parameter.

Changes

  • Parameter names, closure parameter names and enum-case payload names get a _ suffix when they are a Java keyword or a reserved Swift keyword: long_, int_, default_. This applies in both the Java bindings and the Swift thunks; argument labels are unchanged, so the thunk still calls scale(double: …, int: …, default: …).
  • Getter and setter names drop a property's backticks: getDefault().
  • Methods that would redeclare a final java.lang.Object method (getClass, notify, notifyAll, wait) get a _ suffix, the same way Java-keyword method names already do. That includes the getter of a property named class.

FFM mode builds its parameter names separately and is unchanged here.

Testing

  • New JavaKeywordTests (4 tests): keyword parameter names in the Java bindings and the Swift thunks, enum-case payload names, a backticked property, and wait/notify/the class getter.
  • JNIJavaKitTests updated: long int_ instead of long int.
  • End to end, outside the repository: a package built with JExtractSwiftPlugin whose API uses all of these names. The generated Java compiles with javac and the generated Swift builds in Swift 6 mode. From Java, wait_(), notify_(1), getClass_() and getDefault() reach Swift through their renamed JNI symbols.
  • swift test passes.

🤖 Generated with Claude Code

Swift parameters may be named `long`, `int`, `double`, `default` or `class`,
and properties may be written with backticks, such as `` `default` ``. In JNI
mode those names reached the generated Java as they are: `boolean long`,
`record Quote(String slug, long long)` and `get`default`()` don't compile,
and the Swift thunks had the same problem with `class` and `default`.

- Parameter names, closure parameter names and enum case payload names get a
  `_` suffix when they are Java keywords or reserved Swift keywords, in both
  the Java bindings and the Swift thunks. Argument labels stay as they are.
- Getter and setter names drop a property's backticks: `getDefault()`.
- Method names that would redeclare a final method of `java.lang.Object`
  (`getClass`, `notify`, `notifyAll`, `wait`), including the getter of a
  property named `class`, get a `_` suffix, as Java keywords already did.

JNIJavaKitTests expected `long int` as a Java parameter, which doesn't
compile; it now expects `long int_`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ktoso ktoso left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with the change, thanks.

For future contributions I would request you write at least your commit messages with some of your own voice and not entirely generate them -- this is outlined in the project policy: https://github.com/swiftlang/project-operations/blob/main/contributing/ai-tools.md#writing-and-voice It can be hard to identify how much a contributor thought through a change if it is entirely generated. In this case I'm confident in it, but in others I'm not so sure, so some more argumentation would be helpful, thanks in advance 🙏

@ktoso
ktoso merged commit 1381a29 into swiftlang:main Nov 8, 2026
42 checks passed
@piercifani

Copy link
Copy Markdown
Contributor Author

@ktoso fair point! Will do next time!

piercifani added a commit to skiptools/swift-java that referenced this pull request Nov 12, 2026
…t-binding-generator-core

swiftlang#957 moved SwiftExtract to swiftlang/swift-binding-generator-core.
Our analysis changes now live on skip/integration of
skiptools/swift-binding-generator-core, which Package.swift depends on
(SWIFT_BINDING_GENERATOR_CORE_PATH still overrides it).

Also brings swiftlang#954 (Java keywords, already here), swiftlang#956, swiftlang#958 and swiftlang#960 (protocol
parameter wrappers named after the Java method): kept this branch's
wrappers for protocols of dependencies, named the swiftlang#960 way. Their
tests expect the wrappers' @unchecked Sendable conformance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants