Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
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
}
}
Free download pdf