Initial implementation committed at r4347 for more general review with
a desk review of the implementation by Ray.  I'll address any
follow-up reviews with a second commit.

Changes from previous patch:
  - Added a @DefaultValue annotation to allow @AllowNonVoid getters to
return whatever value the developer wants.
  - Expanded the test case to cover default values.

Further discussion below:

> Design-wise, the main remaining question I have is about AllowNonVoid.
>  The main idea is that an existing interface could be reused with
> minimal change.  That's probably the most common way runAsync will be
> used: on an existing app that has grown large.  The issue is that
> existing interfaces will have some methods that don't work as deferred
> because they return some value.  I believe the idea in the current
> patch is for the generator to object by default, but to provide an
> override that allows the interface to go through anyway.  It will all
> work so long as the callers can tolerate seeing the default value up
> until the concrete implementation is actually loaded.

  The developer has to explicitly opt into making non-void methods
work, because it does have the potential to cause undesired operation
in code that assumes that (o.setFoo(f);  f == o.getFoo()) would always
hold true.

>    @IfNotLoaded(-1)
>    int getValue();

This was implemented as @DefaultValue(); it has value methods for all
primitive types.

> What do you think about encouraging people to split their interfaces
> like this?  Even aside from the void returns, it seems like some
> methods don't really work when deferred anyway.

I'd suggest a pattern like this

interface WorksWithDeferred {
  setProperty(Object a);

  // Basically cast-or-null operation, like in the AST
  UseAfterInstantiation asUseAfterInstantiation();
}

interface UseAfterInstantiation extends WorksWithDeferred {
  int getProperty();
}

class ConcreteType implements UseAfterInstantiation {
  UseAfterInstantiation asUseAfterInstantiation() {
    return this;
  }
}

  An AsyncProxy<WorksWithDeferred> will return null for the
asUseAfterInstantiation() call, while the concrete type can just
"return this" after it's instantiated.  It avoids the need for awkward
narrowing casts which would fail if you were to try to cast the proxy
implementation.  Consuming code can continue to be written against the
UserAfterImplementation interface instead of the concrete type.

-- 
Bob Vawter
Google Web Toolkit Team

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to