Reflection syntax

90 views
Skip to first unread message

lum...@gmail.com

unread,
Feb 11, 2015, 11:01:06 AM2/11/15
to xtend...@googlegroups.com
Hi,

In the context of metaprogramming, I'd like to ask whether it is currently possible in Xtend to access things like the field of a class through some succinct syntax?

Some hypothetical examples of said syntax being:

Field bar = Foo::bar;
Method baz = Foo::baz();

Which behind the scenes could just translate to the appropriate Reflection calls.
The added benefit being that we don't have to tangle with String and get refactoring & type safety support.

Cheers!

Sven Efftinge

unread,
Feb 11, 2015, 11:49:06 AM2/11/15
to xtend...@googlegroups.com
No it’s not supported currently. We did discuss this in the past and there is also the similar but different Java 8 Method References feature which gets discussed from time to time. Please file a bugzilla request.

Could you also list use cases where you want to use reflection for a known declaration?

Sven

--
You received this message because you are subscribed to the Google Groups "Xtend Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to xtend-lang+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

lum...@gmail.com

unread,
Feb 12, 2015, 2:45:26 PM2/12/15
to xtend...@googlegroups.com, efft...@itemis.de
An example use case could be statically typed SQL statements:

class X { String schema_name; boolean is_default; } val statement = select(X::schema_name, X::is_default) from("information_schema.schemata") orderBy(X::schema_name) prepare(c);

Which then become resistant against refactorization, and support type lookup from the variables.

Sven Efftinge

unread,
Feb 12, 2015, 3:12:15 PM2/12/15
to lum...@gmail.com, xtend...@googlegroups.com, Sven Efftinge
Ah I see. You can do that today by introducing an active annotation that generates such static fields.

Sven
signature.asc

lum...@gmail.com

unread,
Feb 18, 2015, 8:39:08 AM2/18/15
to xtend...@googlegroups.com, lum...@gmail.com, efft...@itemis.de
Thanks for the quick reply and insights :)

lum...@gmail.com

unread,
Apr 20, 2015, 6:40:05 AM4/20/15
to xtend...@googlegroups.com, lum...@gmail.com

The proposed solution of generating static method/fields breaks down when confronted with Annotations.
I also cannot just generate the fields/methods in the class I use them in as this results in potential clashes. (Same name on different classes, coupled with type erasure)

After working a bit with ActiveAnnotations I find that I'd love to have easier syntax for accessing Class members. (Even if only to guard against refactorization)
A prime example being Annotations with values which need to be accessed for the code generation.

Per example:

annotation Foo {
    Class[] targets
}

class Foo Processor extends AbstractClassProcessor {

override doTransform(MutableClassDeclaration factory, extension TransformationContext context) {

val mapper = factory.findAnnotation(Foo.findTypeGlobally)
                val targets = mapper.getStringArrayValue("targets") // Problem: Manually set the expected type, and magic value for the field name
                val targets = Foo.targets(mapper)      //   Currently using: Through an extension method on Class<Foo>; however, causes clashes through type erasure on Class.
                val targets = mapper::targets            //    Ideal
                val targets = factory::Foo::targets     //    Even more ideal; if MutableClassDeclaration has a generic and knows it type; and the :: operator infers Annotation lookup.
}
}


Ideally, the Type/AnnotationReferences would have a generic indicating their type; and extra syntax to easily access their members.
Or this syntax on Class, and a transparent conversion to Type & AnnotationReference



Christian Dietrich

unread,
Apr 20, 2015, 3:31:17 PM4/20/15
to xtend...@googlegroups.com, lum...@gmail.com
what about solving that with an ActiveAnnotation as well? By adding an addition annotation to the annotation itself and generate an extension class from that?

lum...@gmail.com

unread,
Apr 20, 2015, 6:55:20 PM4/20/15
to xtend...@googlegroups.com, lum...@gmail.com
what about solving that with an ActiveAnnotation as well? By adding an addition annotation to the annotation itself and generate an extension class from that?

At some point this would become quite bothersome as there are a plethora of downsides:
  1. Name clashes on fields & methods. (both are accessed through extension methods)
  2. The approach procludes Annotations/Code to which we don't have source access without having to write an extra processor. (Or boilerplate annotating on the use class)
  3. Or, Pollution of class space with classes which consist of nothing but the generated extension methods.
  4. No safety against refactoring somewhere in the future

Frankly; IMHO a language that so heavily leans on meta-programming should have easy and concise reflection syntax.


Edit:  (AnnotationReference etc, marked as *Reference)

I started to work on Active Annotations to solve this, and there is simply no way around the fact that all *References don't have type information.
The best that could be managed is something along the lines of Foo.bar(reference).  But this then still has the following issues:
  1. The Processors involved are prohibitively complex to deal with all variations of the getXXX() accessors (getClass, getDouble, etc).
  2. A new class needs to be generated for every class to which Reflection access must be gained as type erasure prohibits putting them all together in a single class.
This besides the issues mentioned above.
(The pattern was for each field / method on Foo to generate an extension method in a hidden class which targetted Class<Foo>; and optionally accepted an applicable *Reference)


In summary, I think the ActiveAnnotations API would be improved by adding in generic support, and short-hand syntax for Reflection.


Christian Dietrich

unread,
Apr 21, 2015, 12:03:03 AM4/21/15
to xtend...@googlegroups.com, lum...@gmail.com
Hi,

i cannot comment on having this feature in Xtend or not. but i can on the "missing type" information. i do not get that.
Here is a poor implementation try. the complexity you talk of is 3 cases (since the type information is actually there).



MakeMeHappyProcessor.xtend

lum...@gmail.com

unread,
Apr 21, 2015, 6:29:09 AM4/21/15
to xtend...@googlegroups.com, lum...@gmail.com
Hey!

Thanks for taking the time to bear with me through the discussion. :-)

With the type information I meant that currently a *Reference cannot (/should not) be used as a basis for the lookup.
It's probably better if I note down my thought process: 
  1. Accessing variable bar on type Foo:
    def static bar(Class<Foo> clzz)

  2. Now, due to type erasure we can't generate these in the same class for different Types, so we generate an *Extensions class per Type .

  3. If we only accept *Reference, then fields/functions for Foo would be mixed with info from any type. (Clashes and other problems)
    So, for *Reference, the best we can do is:
    def static bar(Class<Foo> clzz, *Reference ref)

    However, the problem is that you can now still pass any *Reference to this, discarding type safety.

  4. If *Reference would have a generic with type information, we could do:
    def static bar(*Reference<Foo> clzz)
The problem with this approach is that we are then creating an Extension class with a rather large amount of functions to deal with all the patterns. (Class<Foo>, *Reference<Foo>)
These classes also cannot be hidden if the code is used in a library. (Or we have to generate them per package they are used in?)

Another issue that this does not address is variable and function name clashing.
Wherever we need to use logic to lookup the variable (ClassReference), we'll need to use some kind of naming convention to prevent clashes.
(Problems with code we don't have access to, and it starts getting in the way of code brevity

Btw; I saw in your code you use findTypeGlobally(Foo).newTypeReference().
Is there any benefit to using this instead of Foo.newTypeReference?
Reply all
Reply to author
Forward
0 new messages