June 3, 2011

Groovy Goodness: Add AST Transformations Transparently to Scripts

With Groovy 1.8 we can add compilation customizers when for example we want to run a Groovy script from our application code. Cedric Champeau has a nice blog post about this feature. And we already learned about the import customizer in a previous Groovy Goodness blog post.

Another customizer is the ASTTransformationCustomizer. We can use this customizer to add an AST transformation to a script. The AST transformation is then applied to all classes in the script. This means we can only apply transformations that can be used at class level. Another thing we need to notice is that we cannot set parameters for the AST transformation, so only the defaults for the parameters are used.

We can use both local and global AST transformations with the ASTTransformationCustomizer. For a local transformation we use the annotation class, for a global transformation we pass the AST transformation class to the constructor.

package com.mrhaki.blog

import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
import org.codehaus.groovy.control.CompilerConfiguration
import groovy.transform.Canonical

def conf = new CompilerConfiguration()
conf.addCompilationCustomizers(new ASTTransformationCustomizer(Canonical))

def shell = new GroovyShell(conf)
shell.evaluate '''
package com.mrhaki.blog

class User {
    String username, fullname

// TupleConstructor is added by Canonical transformation.
def user = new User('mrhaki', 'Hubert A. Klein Ikkink')
// ToString is added by Canonical transformation.
assert user.toString() == 'com.mrhaki.blog.User(mrhaki, Hubert A. Klein Ikkink)'

// AST transformation is also applied to the Script class.
assert this.toString() == 'com.mrhaki.blog.Script1()'