Groovy 2.1: groovyc --configscript

One of the new features in Groovy 2.1 [0] is the -configscript Groovy compiler program option.

Compiler Configuration Script with --configscript

The --configscript option can be used to specify a compiler configuration script. Before 2.1, the CompilerConfiguration class could be used to change certain configuration settings:
 
def configuration = new CompilerConfiguration()
// apply some configuration settings ...


def shell = new GroovyShell(configuration)
 
Although we could set the CompilerConfiguration for a given GroovyShell, there was no way to do so for the Groovy compiler groovyc. As of Groovy 2.1, --configscript can be used to point to an external Groovy DSL script that has access to an implicit configuration variable of type CompilerConfiguration. In order to specify a Groovy configuration file we need to create a configuration Groovy script, let's call it config.groovy:
 
import org.codehaus.groovy.control.customizers.ImportCustomizer

def imports = new ImportCustomizer()
imports.addImports('org.some.*')

configuration.addCompilationCustomizers(imports)
 
The script above adds package org.some.* to the default imports. As you can see, Groovy adds an implicit variable called configuration. At runtime, this is the actual compiler configuration our DSL script needs to interact with.

A New Builder: CompilerCustomizationBuilder

Groovy 2.1 comes even with a new DSL for the --configscript configuration file. The builder in the background is CompilerCustomizationBuilder. For the star import example given above, with the builder the configuration file would look like this:
 
import org.codehaus.groovy.control.customizers.ImportCustomizer
import org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder

CompilerCustomizationBuilder.withConfig(configuration) {
    new ImportCustomizer().addImports('org.some.*')
}
 
or we could - due to the fact that Groovy already adds a star import for import static CompilerCustomizationBuilder.* - reduce our code to:
 
// implicitly added ...

// import static org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder.*


import org.codehaus.groovy.control.customizers.ImportCustomizer

withConfig(configuration) {
    new ImportCustomizer().addImports('org.some.*')
}

 
The compiler customization is not restricted to adding CompilerCustomizer implementations. It can be used to add AST transformations on every artifact that is compiled with the -configscript option. Let's say we wanted to apply the newly introduced static compilation feature with @CompileStatic to every class in our project. The compiler configuration script can look like this:
 
// implicitly added ...

// import static org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder.*


withConfig(configuration)  {
    ast(groovy.transform.CompileStatic)
}
 
We can even go further. In addition, CompilerCustomizationBuilder provides a way to register certain source files with AST transformations. Let's say we wanted to couple all files with a *.sgroovy extension to the @StaticCompile annotation. This could be done in the configuration script using a SourceAwareCustomizerFactory:
 
withConfig(configuration) {
    source(extension: 'sgroovy') {
        ast(groovy.transform.CompileStatic)
    }
}
 
When running e.g. groovyc with this configuration script and a *.sgroovy file we have @StaticCompile automatically applied on all newly compiled classes. There are even more features that can be used with this builder. As a starting point, take a look at the registerFactories method in CompilerCustomizationBuilder:
 
registerFactory("ast", new ASTTransformationCustomizerFactory())
registerFactory("customizers", new CustomizersFactory())
registerFactory("imports", new ImportCustomizerFactory())
registerFactory("inline", new InlinedASTCustomizerFactory())
registerFactory("secureAst", new SecureASTCustomizerFactory())
registerFactory("source", new SourceAwareCustomizerFactory())
 
As you can see, there is even a ImportCustomizerFactory predefined. A look at the documentation shows how to use it in the compiler configuration DSL:
 
import org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder

def builder = new CompilerCustomizationBuilder()
builder.imports {
    star 'org.some'
}
 

Conclusion

Groovy 2.1 comes with a new Groovy compiler configuration parameter: -configscript. In conjunction with the new CompilerCustomizationBuilder it can be used to specify a Groovy script holding the compiler configuration DSL code as supported by the builder. This is good news for AST transformation authors as the hook can be used for embedding AST transformations or registering AST transformations on specific source files.

[0] Groovy 2.1 Relase Notes