Chapter 8
[ 195 ]
This is sort of what we are trying to do with our pretty print AST transformation.
AST transformations happen at compile time, so what if we could extend a class
with a trait as part of an AST transformation? This will save us a lot of AST node
manipulation in the transformation. Fortunately, we can actually do this as the
following example illustrates:
trait PrettyAwesomeTrait {
void prettyPrint() {
this.properties.sort { it.key }.each {
if (it.key != 'prettyPrint' && it.key != 'class')
println it.key + ": " + it.value
}
}
}
@Target([ElementType.TYPE])
@Retention(RetentionPolicy.SOURCE)
@GroovyASTTransformationClass(["PrettyAwesomeASTTransformation"])
public @interface PrettyAwesome {
}
@GroovyASTTransformation (phase = CompilePhase.SEMANTIC_ANALYSIS)
class PrettyAwesomeASTTransformation implements ASTTransformation,
CompilationUnitAware {
def compilationUnit
void visit(ASTNode[] nodes, SourceUnit source) {
ClassNode classNode = nodes[1]
def traitNode = ClassHelper.make(PrettyAwesomeTrait)
if (!classNode.implementsInterface(traitNode)) {
classNode.addInterface(traitNode)
TraitComposer.doExtendTraits(
classNode,source,compilationUnit)
}
}
@Override
void setCompilationUnit(CompilationUnit unit) {
compilationUnit = unit
}
}