In the last part of the series we had a look at Xtend's built-in Active Annotations. This time you will learn how to write your own Active Annotations to get rid of boilerplate code.

Active Annotations are simply annotations marked with @Active and have an associated processor class. The processor gets access to the annotated elements (classes, methods, etc.) during different phases of the Xtend to Java compilation.

The corresponding interfaces are
  • RegisterGlobalsParticipant (announces additional types)
  • TransformationParticipant (changes the Java model)
  • ValidationParticipant (called after all transformations are done, but before code is generated)
  • CodeGenerationParticipant (generates additional non-Java code, like XML files etc.)
There are convenience base classes like AbstractMethodProcessor and AbstractClassProcessor that implement all these interfaces.

Let's start with the simple example of adding a logger field to a class. I've seen many people either have a template proposal in the IDE or copy-paste something like this over and over again:

We want to automate this, so we create an Active Annotation and extend AbstractClassProcessor.

As you can see, we get access to the Java AST model as well as lots of helpful methods from the TransformationContext object. Using these, we add the log field to the class and just give it some Java snippet as an initializer. We use a template variable when we want to refer to classes in the generated code. This way, imports are automatically organized for us.

Now we can just reuse our @Log annotation everywhere and never have to write the line of boilerplate again. Notice that you cannot use Active Annotations in the same project where they are defined. So put them in a dedicated project that you add as a library to your other projects.

Just as with the built-in annotations you will notice that the outline, validation, content assist etc. are aware of your new log field. Thanks to the primarySourceElement definition in our processor, navigation works correctly and goes to the class when the log field is selected. You can also take a look at the generated Java code to make sure it matches your expectations. It is automatically updated when you change something in the processor. This very useful when prototyping your own annotations.

In the upcoming posts we will build advanced processors and explore the Active Annotation API more thoroughly in the process. If you want to try some examples on your own, you can use New => Examples => Xtend Active Annotation Examples in Eclipse. Or you can have a look at some of my projects, like xtend-contrib and xtend-junit.