Skip to content
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

Giving a class both a static and instance members with a matching union type causes invalid java to be generated #46

Open
niloc132 opened this issue May 27, 2020 · 0 comments

Comments

@niloc132
Copy link
Contributor

niloc132 commented May 27, 2020

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.

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 a pull request may close this issue.

1 participant