gwtproject / gwtproject/gwt

Add @MustBeLiteral to make GWT.create(Class) less magical and more extensible

Open
#2,249 17 comments 0 reactions 1 assignee View on GitHub

@dankurka is already working on this.

Since Jun 10, 2015.

Category-Compiler Milestone-Planned Type-Feature
Dominant language
Java
Stars
1.6k
Forks
397
Avg merge
4d 23h
Merged PRs (30d)
7

Description

Originally reported on Google Code with ID 2243

Found in GWT Release:
All of them so far (up to GWT 1.5 M1)

Detailed description:

Every now and then I'd like to be able to wrap a GWT.create() call in a
"library" method that invokes GWT.create() and then does something with the
result before returning it.  The limitation that GWT.create() must be
called with a class literal means that such a library method must have the
argument to GWT.create() "baked in", even if the call sites of the library
method could all provide a class literal.  This could be solved in a
controlled, easy-to-explain manner by adding support for @MustBeLiteral to
the compiler.

Rather than GWT.create() being exceptionally magical, it could be reduced
to mostly magical if it were written like this:

public class GWT {

  public static <T> T create(@MustBeLiteral Class<T> klass) {
    // magic
  }
}

The compiler would then have to be changed to enforce that
@MustBeLiteral-annotated parameters must either be literals, or,
recursively, are @MustBeLiteral-annotated parameters of the call site.  You
could then write this:

public class MyFactory {

  public Foo makeFoo(@MustBeLiteral Class<? extends Foo> klass, Object...
parms) {
    Foo ret = GWT.create(klass);

    ret.setParms(parms);

    return ret;
  }
}

I think the benefits are:

 - libraries can wrap GWT.create() in a controlled manner
 - the transitive nature of @MustBeLiteral is pretty easy to grasp
 - GWT.create()'s magicalness is reduced
 - if GWT.create() is extended to support arbitrary arguments
   as in issue 1595, the required new code might be less magical
   (and therefore more straightforward) if the Object... parameter
   were annotated as follows:
   create(@MustBeLiteral Class<T> klass, @MustBeLiteral Object... args);
 - @MustBeLiteral could conceivably be applied not only to method
   parameters, but also final fields and static final fields for
   additional flexibility

The only downside I can think of is:

 - a given call site for GWT.create() would now have to handle multiple
   possible values for its argument

I think the downside can be handled in a number of ways.  The most
straightforward would be to switch on the passed-in class name and
instantiate the appropriate generated source.  You might be able to avoid
the switch by using Javascript's polymorphic abilities if you added
synthesized methods to each of the Class instances so that GWT.create()
calls would compile down to something like this:

GWT.create(klass) becomes

klass.instatiateWithGeneratorFoo()

Where instantiateWithGeneratorFoo() is added to the vtable for each Class
instance that is passed to a generator named GeneratorFoo, and the
implementation for each class just returns an instance of the type defined
by GeneratorFoo applied to that class.

Workaround if you have one:
Ugly code.

Links to the relevant GWT Developer Forum posts:
I first mentioned the idea in this form here:
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/cf36c64ff48b3e19?hl=en
Ray Cromwell mentioned a similar idea in this thread:
http://groups.google.com/group/Google-Web-Toolkit-Contributors/browse_thread/thread/2039c573f2648344

Reported by ispeters on 2008-04-02 19:37:15

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.