google / google/jsinterop-generator
Giving a class both a static and instance members with a matching union type causes invalid java to be generated
- Dominant language
- Java
- Stars
- 85
- Forks
- 24
- PR merge metrics
- No merged PRs in 30d
Description
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.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.uncheckedCast(arg));
}
@JsOverlay
public final Object unionArgMethod(String arg) {
return unionArgMethod(Js.uncheckedCast(arg));
}
public native Object unionArgMethod(Foo.UnionArgMethodArgUnionType arg);
@JsOverlay
public final Object unionArgMethod(double arg) {
return unionArgMethod(Js.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.
Contributor guide
Assessment
This issue has not been assessed yet.