jsinterop-generator
jsinterop-generator copied to clipboard
Giving a class both a static and instance members with a matching union type causes invalid java to be generated
Given two members on a class, one static and one instance, one will be generated with a _STATIC suffix. That is,
Foo.noArgMethod = function() {};
Foo.prototype.noArgMethod = function() {};
will cause this to be generated:
@JsMethod(name = "noArgMethod")
public static native Object noArgMethod_STATIC();
public native Object noArgMethod();
(removed an incorrect statement, will follow up separately)
However, if both of these have a parameter which is unioned, then the generated *UnionType will be emitted twice, as the names are not distinct - unlike the actual member name, the union type's name is only based on the method name and argument name.
Additionally, once a native method is generated for this, two or more @JsOverlay methods will be generated as well, and when those are renamed to append _STATIC to them, a @JsMethod/@JsProperty annotation will also be decorated on them, which will cause a compiler error in J2CL.
Example js with a method:
/**
* @param {string|number} arg
*/
Foo.unionArgMethod = function(arg) {};
/**
* @param {string|number} arg
*/
Foo.prototype.unionArgMethod = function(arg) {};
Resulting java:
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface UnionArgMethodArgUnionType {
@JsOverlay
static Foo.UnionArgMethodArgUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default double asDouble() {
return Js.asDouble(this);
}
@JsOverlay
default String asString() {
return Js.asString(this);
}
@JsOverlay
default boolean isDouble() {
return (Object) this instanceof Double;
}
@JsOverlay
default boolean isString() {
return (Object) this instanceof String;
}
}
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface UnionArgMethodArgUnionType {
@JsOverlay
static Foo.UnionArgMethodArgUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default double asDouble() {
return Js.asDouble(this);
}
@JsOverlay
default String asString() {
return Js.asString(this);
}
@JsOverlay
default boolean isDouble() {
return (Object) this instanceof Double;
}
@JsOverlay
default boolean isString() {
return (Object) this instanceof String;
}
}
@JsOverlay
@JsMethod(name = "unionArgMethod")
public static final Object unionArgMethod_STATIC(String arg) {
return unionArgMethod(Js.<Foo.UnionArgMethodArgUnionType>uncheckedCast(arg));
}
@JsMethod(name = "unionArgMethod")
public static native Object unionArgMethod_STATIC(Foo.UnionArgMethodArgUnionType arg);
@JsOverlay
@JsMethod(name = "unionArgMethod")
public static final Object unionArgMethod_STATIC(double arg) {
return unionArgMethod(Js.<Foo.UnionArgMethodArgUnionType>uncheckedCast(arg));
}
@JsOverlay
public final Object unionArgMethod(String arg) {
return unionArgMethod(Js.<Foo.UnionArgMethodArgUnionType>uncheckedCast(arg));
}
public native Object unionArgMethod(Foo.UnionArgMethodArgUnionType arg);
@JsOverlay
public final Object unionArgMethod(double arg) {
return unionArgMethod(Js.<Foo.UnionArgMethodArgUnionType>uncheckedCast(arg));
}
Example JS with a property:
/**
* @type {string|number}
*/
Foo.unionProperty;
/**
* @type {string|number}
*/
Foo.prototype.unionProperty;
Resulting Java:
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface UnionPropertyUnionType {
@JsOverlay
static Foo.UnionPropertyUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default double asDouble() {
return Js.asDouble(this);
}
@JsOverlay
default String asString() {
return Js.asString(this);
}
@JsOverlay
default boolean isDouble() {
return (Object) this instanceof Double;
}
@JsOverlay
default boolean isString() {
return (Object) this instanceof String;
}
}
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface UnionPropertyUnionType {
@JsOverlay
static Foo.UnionPropertyUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default double asDouble() {
return Js.asDouble(this);
}
@JsOverlay
default String asString() {
return Js.asString(this);
}
@JsOverlay
default boolean isDouble() {
return (Object) this instanceof Double;
}
@JsOverlay
default boolean isString() {
return (Object) this instanceof String;
}
}
public static Foo.UnionPropertyUnionType unionProperty;
There is also a separate correctness issue which I'll file separately - in some cases, there is only one unionProperty, the static variant, as the non-static member is failed to be emitted.