This is where Active Annotations come into play. They allow you to participate in the translation from Xtend to Java code. You can do everything from adding simple methods to creating completely new classes or generating arbitrary resources. And the IDE knows what you are doing at all times, giving you the navigation, validation and auto completion that your are used to with hand-written code.
The Xtend library ships with a few Active Annotations out of the box. Let's have a look at these first to get a basic idea of what they are all about.
Remember our Complex number example? We wanted an immutable datatype with two double values. Now normally we would have to write a constructor, getters, equals/hashCode and toString for that.
But there is an annotation that does exactly that. Just annotate the class with @Data and all the boilerplate is generated for you. Now you can focus on the interesting math. Neat, huh? ;)
When you switch the outline view into "JVM mode" you will also see all the generated members in grey. You can click on getters in the outline and are taken to the corresponding field and vice versa.
The generated methods and constructors are also proposed in content assist. The IDE experience is the same as if you had written them yourself. If you are curious, you can open up the generated Java file to assure yourself that the annotation does exactly what you expect.
Another common pattern are getters and setters. When you annotated a field with @Accessors, a getter and setter will be generated for you. If you put the annotation on a class, there will be getters and setters for all fields. If there are final fields, then there will be no setter for them of course. Instead there will be a constructor that takes those final fields.
Want to have getters only? Or protected setters? Or exclude one field completely? No problem, just use the AccessorType value inside the @Accessors annotation.
Quite often you want to implement an interface, reusing 95% of an existing implementation and only changing a few methods. That's exactly what @Delegate allows you to do. Just annotate a field or method with @Delegate.
Any interfaces that your class and the delegate object share will get default implementations that just forward the call to the delegate object. You can restrict the interfaces you want to have implemented by listing them inside the annotation.
@FinalFieldsConstructor, @EqualsHashCode, @ToString
These are basically the parts that make up @Data. We broke them out for two reasons. First of all because they are useful on their own. Secondly because you can use them to customize the behavior of @Data.
Let's say you don't like the default toString method and want a more concise representation. Just add @ToString(hideFieldNames = true, singleLine = true)
Or maybe your final-fields-constructor needs some additional annotations. Just write an empty constructor and annotate it with @FinalFieldsConstructor. The annotation will insert the boring parameters and body for you.
These annotations alone are a good reason to like Xtend. But the real killer feature is that you can easily write your own. Get ready to automate the hell out of your projects! =)