-
Notifications
You must be signed in to change notification settings - Fork 48
JavaKit: Macro and translator support for mapping Java classes to Swift classes #140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaKit: Macro and translator support for mapping Java classes to Swift classes #140
Conversation
…ft classes Java classes are currently translated in Swift structs, and we use is/as functions to cast up and down the hierarchy. Start down an alternative path where we translate Java classes into Swift classes, making proper use of inheritance in Swift to reflect inheritance in Java. This step updates the @javaclass macro implementation to check whether it is being applied to a class (rather than a struct) and adjust its behavior accordingly: * The superclass is extracted from the inheritance clause of the class rather than the "extends" argument to the macro. * The "full Java class name" static member becomes a "class" member. For everything other than JavaObject itself, it is an override. * The `javaHolder` property is only emitted into JavaObject, nowhere else. * The `init(javaHolder:)` initializer becomes required. For everything other than JavaObject, it's implemented as a super.init call. * The `JavaSuperclass` typealias is no longer emitted. All of this is keyed off the subject of the attribute being a "class" rather than a "struct", so we keep the existing struct versions working. Relatedly, extend the translator with an option to map Java classes to Swift classes. This involves a number of changes: * Emitting each as an "open class" rather than "public struct" * Emitting the superclass into the inheritance clause rather than the "extends" argument * Emitting methods as "open" rather than "public" * Only emit methods and fields declared in the class, not inherited ones This option is only currently only enabled in test cases while we stage in this functionality.
…lass When we import a class from Java into Swift, we check whether its superclass was also imported before generating a reference to that superclass. If it isn't there, we fell back to JavaObject. That's too conservative, because there might be a superclass in between that we could use. Instead, walk up the superclass chain until we find the most-specific superclass that *is* mapped into Swift, and use that as the generated superclass. Additionally, use this as the basis for determining when we need the "override" keyword when in the class-generating mode.
No functionality changes here; we're just more consistent about putting JavaObject in as the extended type.
We don't need this function when generating classes, because we'll already get the subtype conversion for free.
Hm, definitely promising direction. I like that the object holder is in the super class, that makes sense. So far looking good :) |
When looking for a declared method with a given signature, we need to check all superclasses that have been mapped into Swift, not just the closest one.
Swift doesn't have the notion of "protected", so treat these as "open" (or "public") as approriate.
Keep interfaces as structs for now. Their future is yet unwritten.
…va and Swift Java allows more subtyping relationships for the result types in a covariant method override than Swift does, such as covariant arrays and wildcards. Take the Swift semantics into account when determining whether to apply the `override` keyword.
Swift has inheritance of initializers, while Java does not have inheritance of constructors. This means that Swift's attempt to treat a convenience initializer as an override within a subclass can cause problems with mismatched signatures. Use `@_nonoverride` to avoid this problem.
@@ -314,7 +314,7 @@ class Java2SwiftTests: XCTestCase { | |||
""", | |||
""" | |||
@JavaMethod | |||
public convenience init(environment: JNIEnvironment? = nil) | |||
@_nonoverride public convenience init(environment: JNIEnvironment? = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hah sneaky 👍
Looks good 👍 |
Merging this one. Aside from bringing in another Java class or two into JavaKit, it doesn't affect the current behavior. |
Java classes are currently translated in Swift structs, and we use is/as
functions to cast up and down the hierarchy. Start down an alternative
path where we translate Java classes into Swift classes, making proper use
of inheritance in Swift to reflect inheritance in Java.
This step updates the @javaclass macro implementation to check whether
it is being applied to a class (rather than a struct) and adjust its
behavior accordingly:
rather than the "extends" argument to the macro.
For everything other than JavaObject itself, it is an override.
javaHolder
property is only emitted into JavaObject, nowhere else.init(javaHolder:)
initializer becomes required. For everythingother than JavaObject, it's implemented as a super.init call.
JavaSuperclass
typealias is no longer emitted.All of this is keyed off the subject of the attribute being a "class"
rather than a "struct", so we keep the existing struct versions working.
Relatedly, extend the translator with an option to map Java classes to
Swift classes. This involves a number of changes:
This option is only currently only enabled in test cases while we stage in this functionality.
This is for issue #132.