Re: [gwt-contrib] Initial support for @GwtCreate (code-gen methods)

2013-08-17 Thread Andrés Testi
Thank Ray :-)
The patch has as an issue with constructor code-gen that I solved, but GIT 
doesn't allows me to push merges.
Of course, has you a link to explore the javac compiler-plugin alternative?
Thanks!

- Andrés

El sábado, 17 de agosto de 2013 01:28:53 UTC-3, Ray Cromwell escribió:

 Andres, this looks amazing! I've been out this week on vacation but 
 returning tomorrow, I'll take a look when I return.



 On Fri, Aug 16, 2013 at 2:22 AM, Andrés Testi 
 andres@gmail.comjavascript:
  wrote:

 I've been working on a prototype inspired by Ray Cromwell's proposal for 
 @GwtCreate parameters, borrowing some ideas from Scala implicit macros. I 
 apologize for not to post this in the Possible GWT.create() Improvements 
 thread, but this message is too long to be only a comment. 
 You can check my patch at https://gwt-review.googlesource.com/4110. This 
 prototype has passed many JUnit tests cases and works fine (only fails 
 JEnumTypeTest after my last pull, I don't know why). Devmode also works.
 This proposal differs from Ray's original idea in that @GwtCreate is a 
 parameter annotation instead of a method annotation. Later I will justify 
 this decision.
 This new proposal consists on rewriting methods adding a trailing 
 implicit parameter of type GwtCreateFactory for each parameter annotated 
 with @GwtCreate. GwtCreateFactory is a hidden interface used by the 
 compiler:

   interface GwtCreateFactory {
 T T create();
   }

 When the compiler finds a code-gen method like

   Foo createFoo(@GwtCreate final Class? extends Foo fooType) {
 return GWT.create(fooType);
   }

 it is rewritten as

   Foo createFoo(final Class? extends Foo type, GwtCreateFactory 
 fooType$factory) {
 return fooType$factory.create();
   }

 IMPORTANT: 
  The @GwtCreate parameter requires to be final.
  This proposal doesn't require constant evaluation expression. The 
 final modifier is required to disable non reproductible side effects.

 At method call site, an invocation like

   Foo foo = createFoo(SubFoo.class);

 is rewritten as

   class SubFoo$GwtCreateFactory implements GwtCreateFactory {
 @Override public T T create() {
   return GWT.create(SubFoo.class);
 }
   }

   Foo foo = createFoo(SubFoo.class, new SubFoo$GwtCreateFactory());

 Just like Scala implicit parameters, @GwtCreate can fight against type 
 erasure and subtyping

   interface FooCreator {

 T extends Foo T create(@GwtCreate ClassT fooType);  
   }

   class FooCreatorImpl extends FooCreator {

 T extends Foo T create(@GwtCreate final ClassT fooType) {
   return GWT.create(fooType);
 }
   }

 code-gen constructors are supported too

   class CreateByConstructorT extends Foo {
   
 final T instance;
  
 public  CreateByConstructor(@GwtCreate final ClassT fooType) {
   instance = GWT.create(fooType);
 }
   }

 Again, as in Scala implicit parameters, nesting is allowed

   class Foo {}
   class SubFoo extends Foo {}

   F extends Foo F createFoo(@GwtCreate final ClassF fooType) {
 return GWT.create(fooType);
   }

   S extends SubFoo S createSubFoo(@GwtCreate final ClassS subFooType) 
 {
 return createFoo(subFooType);
   }

 The decision to locate @GwtCreate on parameters was taken to support 
 mixed code-gen methods

   F extends Foo, B extends Bar
   void fooBarCreator(@GwtCreate final ClassF fooType, @GwtCreate final 
 ClassB barType) {
 foo = GWT.create(fooType);
 bar = GWT.create(barType);
   }

 Note that the @GwtCreate class parameters aren't replaced by 
 GwtCreateFactory as was originally suggested by Ray Cromwell. This provides 
 access to actual parameters.

   ClassT storedType;
   T instance;

   void createFoo(@GwtCreate final ClassT type) {
 storedType = type;
 instance = GWT.create(type);  
   }

 * Further improvements:

   1) Support for explicit generators

 @GwtCreate(generator = FooGenerator.class)

 We should forbid assignation between parameters that differs in 
 @GwtCreate signature

   Foo createFoo(@GwtCreate(generator = FooGen.class) final Class? 
 extends Foo) {...}

   // This will fail
   Foo forbiddenNesting(@GwtCreate(generator = BarGen.class) final 
 Class? extends Foo fooType) {
 return createFoo(fooType);
   }

   2) Multiple parameters for GWT.create() by means of @GwtCreate.Param

   U, O UiBinderU, O createBinder(
 @GwtCreate(generator = UiBinGen.class) final ClassU uiType, 
 @GwtCreate.Param final ClassO ownerType) {

  return GWT.create(uiType, ownerType);
   }

 @GwtCreate.Params must respect the same kind of signature rules than 
 @GwtCreate, and a strict order of invocation

   // Good ordering
   Foo createFoo(
 @GwtCreate final Class? extends Foo fooType,
 @GwtCreate.Param final Class? arg1,
 @GwtCreate.Param final Class? arg2) {  
 return GWT.create(fooType, arg1, arg2);
   }

   

Re: [gwt-contrib] Initial support for @GwtCreate (code-gen methods)

2013-08-17 Thread Andrés Testi
BTW consider that I forgot to commit @GwtCreate annotation, you can find it 
here: https://gwt-review.googlesource.com/#/c/4111/
Where I wrote Further Improvements, I meant Upcoming Improvements (I'm 
not native english speaker)

- Andrés

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- 
You received this message because you are subscribed to the Google Groups GWT 
Contributors group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit-contributors+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-17 Thread James Nelson
I like it!

I've got a few comments / ideas, but overall, I'm glad to see more work 
being done to empower core GWT functionality.

 

 Note that the @GwtCreate class parameters aren't replaced by 
 GwtCreateFactory as was originally suggested by Ray Cromwell. This provides 
 access to actual parameters.


It would be possible to do a full replacement if the factory also gave 
access to the class field, and any code in the method block accessing the 
class could be re-routed through the factory.
Though, I see no good reason why to do the extra work this way, I figured 
I'd mention it in case someone else has a use case for it.
 

* Upcoming improvements:

   1) Support for explicit generators

 @GwtCreate(generator = FooGenerator.class)


Did you see my pull request with some (very) basic support for this?
https://gwt-review.googlesource.com/#/c/4000/

 

 We should forbid assignation between parameters that differs in 
 @GwtCreate signature

   Foo createFoo(@GwtCreate(generator = FooGen.class) final Class? 
 extends Foo) {...}


Agreed.  Final isn't necessary to trace values, but it does ensure users 
don't get weird behavior.


  2) Multiple parameters for GWT.create() by means of @GwtCreate.Param

   U, O UiBinderU, O createBinder(
 @GwtCreate(generator = UiBinGen.class) final ClassU uiType, 
 @GwtCreate.Param final ClassO ownerType) {


Is the intention here to just send more classes to the generator,
or to actually send parameters to the constructor of the rebound object 
being instantiated?

  Foo createFoo(
@GwtCreate final Class? extends Foo fooType,
@GwtCreate.Param final Class? arg1,
@GwtCreate.Param final Class? arg2) {  
return GWT.create(fooType, arg1, arg2);
  }

Sending classes is no good, because the constructor needs the values.

Personally, I think the best solution is to add the parameters to 
@GwtCreate;

  Foo createFoo(
@GwtCreate({String.class, int.class})
final Class? extends Foo fooType,
String arg1, int arg2) {  
return GWT.create(fooType, arg1, arg2);
  }

Class values in annotations must be class literals, so that makes that easy.

It also means we don't care about the order of extra parameters sent to the 
method,
nor are we forced to get these values from the method parameters (or even 
declare GWT.create params as params in method);
the invocation of GWT.create(cls, params) would simply supply the 
JExpressions to pass along to constructors.
(Have to pull out the initializers from the JNewArray made by the generics, 
but that's simple).

I assume we would be changing GWT.create to be create(Class? c, Object 
... params);
the compiler could bail if params.length  0 anywhere that's not in a 
method (method w/ parameter) annotated with @GwtCreate.

Then, add a JType[] and JExpression[] to JGwtCreate to be able to find the 
right constructor and have values to send it 
(not sure if unboxing would work without a tweak, but that's no biggie).


The only hard-ish part would be updating ResolveRebinds to pass along the 
list of JExpressions correctly.


Do you have any work started in this area, cos I'd be glad to give it a 
shot / send over a pull request.
 

To allow mixed multiple code-gen parameters, we would bind main 
parameters by name


   F extends Foo, B extends Bar
   void mixedMultiple(
   @GwtCreate final ClassF fooType, 
   @GwtCreate.Param(fooType) final Class? fooArg,
   @GwtCreate final ClassB barType, 
   @GwtCreate.Param(barType) final Class? barArg)


I really don't like this much typing to wire stuff up.
Putting the params in the @GwtCreate would make this much cleaner:

F extends Foo, B extends Bar B create(
@GwtCreate({String.class}) final ClassF fooType,
@GwtCreate({Foo.class}) final ClassB barType) {
F foo = GWT.create(fooType, some string);
return GWT.create(barType, foo); // params can come from anywhere
  }
 

   3) Support for GWT.create(this.getClass()) ? not exactly, but...

 Explicits generators can eliminate the issue of the unique generator 
 per class hierarchy. An aditional boolean parameter for @GwtCreate would 
 mitigate the code size issue

   abstract class UiBinderComposite extends UiBinderComposite {

 public UiBinderComposite() {
   UiBinderWidget, UiBinderComposite binder = 
 createBinder(getClass());
 }

 private static UiBinderWidget, UiBinderComposite
 createBinder(@GwtCreate(
 // The explicit generator knows when to stop the code 
 generation
 generator = UiBinderCompositeGenerator.class,

 // this.getClass() is disallowed by default.
 allowsThisClass = true) 
 final Class? extends UiBinderComposite type) {

   return GWT.create(type);
 }
   }


I am unsure how