1

Let's say, I have a Java interface:

public interface IMyInterface {
    void hello(String who);
}

I want to create an active annotation with Xtend that automatically (and generically) implements that interface for an Xtend class. So that, when I write

@InterfaceImplementor
class MyInterfaceImplementation implements IMyInterface {       
} 

I want Xtend to generate

@InterfaceImplementor
@SuppressWarnings("all")
public class MyInterfaceImplementation implements IMyInterface {
  public void hello(final String who) {
    delegate.hello(who);
  }
}

I came as far as this:

@Active(typeof(ImplementationGenerator))
annotation InterfaceImplementor{}

class ImplementationGenerator implements TransformationParticipant<MutableClassDeclaration> {

    override doTransform(List<? extends MutableClassDeclaration> annotatedTargetElements, extension TransformationContext context) 
    {
        for(element : annotatedTargetElements)
        {
            for(method : element.declaredMethods) 
            {
                implementMethod(element, method, context)               
            }
        }
    }

    def implementMethod(MutableClassDeclaration clazz, MutableMethodDeclaration method, extension TransformationContext context) 
    {
        method.body = ['''delegate.«method.simpleName»(«method.callParameters»);''']
    }

    def callParameters(MutableMethodDeclaration method) 
    {
        method.parameters.map[ simpleName ].join(', ')
    }
}

This works as long as I override each method in the target class:

@InterfaceImplementor
class MyInterfaceImplementation implements IMyInterface {       

    override hello(String who) {}

} 

However, I actually want Xtend to generate the whole class body, without me having to declare each method manually. For this, I tried to use element.implementedInterfaces in the active annotation, but these are merely TypeReferences, and I don't know how to get the declared methods from a type reference. So this is where I am stuck.

Is it even possible to resolve a TypeReference during an active annotation evaluation? Is there any other way of reaching my goal?

Stefan Winkler
  • 3,871
  • 1
  • 18
  • 35

2 Answers2

2

"element.declaredMethods" returns locally declared methods (i.e. is empty in your case). You need to traverse the methods of the implemented interface instead and then create new methods in the current annotation target.

Sven Efftinge
  • 3,065
  • 17
  • 17
  • How do I get the methods from the implemented interface? I can get the `TypeReference` of `element.implementedInterfaces`. But how do I get the methods declared by the referenced interface? – Stefan Winkler Jun 02 '14 at 15:48
  • Ah, got it. `TypeReference` has a `getType()` method which returns a `Type` which can be cast to `InterfaceDeclaration`. That was the missing piece. Thank you, Sven! – Stefan Winkler Jun 02 '14 at 16:37
1

You can also take a look at the new Xtend built-in @Delegate annotation.

This example is taken from release notes (https://eclipse.org/xtend/releasenotes.html):

interface I {
   def void m1()
   def void m2()
   def void m3()
}
class A implements I {
   override m1() {}
   override m2() {}
   override m3() {}
}
class B implements I {
   //all methods automatically implemented
   @Delegate A delegate = new A
}

Here is the link to the relevant section in Xtend's online documentation: https://eclipse.org/xtend/documentation/204_activeannotations.html

Viliam Simko
  • 1,711
  • 17
  • 31