Runtime and compile-time metaprogramming

The Groovy language supports two flavors of metaprogramming: runtime and compile-time.
The first allows altering the class model and the behavior of a program at runtime while the second only occurs
at compile-time. Both have pros and cons that we will detail in this section.

1. Runtime metaprogramming

With runtime metaprogramming we can postpone to runtime the decision to intercept, inject and even synthesize methods of classes and interfaces. For a deep understanding of Groovy’s metaobject protocol (MOP) we need to understand Groovy objects and Groovy’s method handling.
In Groovy we work with three kinds of objects: POJO, POGO and Groovy Interceptors. Groovy allows metaprogramming for all types of objects but in a different manner.

POJO - A regular Java object, whose class can be written in Java or any other language for the JVM.

POGO - A Groovy object, whose class is written in Groovy. It extends java.lang.Object and implements the groovy.lang.GroovyObject interface by default.

For every method call Groovy checks whether the object is a POJO or a POGO. For POJOs, Groovy fetches its MetaClass from the groovy.lang.MetaClassRegistry and delegates method invocation to it. For POGOs, Groovy takes more steps, as illustrated in the following figure:

However, the use of invokeMethod to intercept missing methods is discouraged. In cases where the intent is to only
intercept method calls in the case of a failed method dispatch use methodMissing
instead.

1.1.2. get/setProperty

Every read access to a property can be intercepted by overriding the getProperty() method of the current object.
Here is a simple example:

1.1.3. get/setMetaClass

You can a access an object’s metaClass or set your own MetaClass implementation for changing the default interception mechanism. For example, you can write your own implementation of the MetaClass interface and assign it to objects in order to change the interception mechanism:

1.2. get/setAttribute

This functionality is related to the MetaClass implementation. In the default implementation you can access fields without invoking their getters and setters. The examples below demonstrates this approach:

1.3. methodMissing

Groovy supports the concept of methodMissing. This method differs from invokeMethod in that it
is only invoked in the case of a failed method dispatch when no method can be found for the given name and/or the
given arguments:

Notice how, if we find a method to invoke, we then dynamically register a new method on the fly using ExpandoMetaClass.
This is so that the next time the same method is called it is more efficient. This way of using methodMissing does not have
the overhead of invokeMethodand is not expensive from the second call on.

1.4. propertyMissing

Groovy supports the concept of propertyMissing for intercepting otherwise failing property resolution attempts. In the
case of a getter method, propertyMissing takes a single String argument containing the property name:

As with methodMissing it is best practice to dynamically register new properties at runtime to improve the overall lookup
performance.

methodMissing and propertyMissing methods that deal with static methods and properties can be added via
the ExpandoMetaClass.

1.5. GroovyInterceptable

The groovy.lang.GroovyInterceptable interface is marker interface that extends GroovyObject and is used to notify the Groovy runtime that all methods should be intercepted through the method dispatcher mechanism of the Groovy runtime.

We cannot use default groovy methods like println because these methods are injected into all Groovy objects so they will be intercepted too.

If we want to intercept all method calls but do not want to implement the GroovyInterceptable interface we can implement invokeMethod() on an object’s MetaClass.
This approach works for both POGOs and POJOs, as shown by this example:

Additional information about MetaClass can be found in the MetaClasses section.

1.6. Categories

There are situations where it is useful if a class not under control had additional methods. In order to enable this
capability, Groovy implements a feature borrowed from Objective-C, called Categories.

Categories are implemented with so-called category classes. A category class is special in that it needs to meet certain
pre-defined rules for defining extension methods.

There are a few categories that are included in the system for adding functionality to classes that make them more
usable within the Groovy environment:

Category classes aren’t enabled by default. To use the methods defined in a category class it is necessary to apply
the scoped use method that is provided by the GDK and available from inside every Groovy object instance:

The use method takes the category class as its first parameter and a closure code block as second parameter. Inside the
Closure access to the category methods is available. As can be seen in the example above even JDK classes
like java.lang.Integer or java.util.Date can be enriched with user-defined methods.

A category needs not to be directly exposed to the user code, the following will also do:

When we have a look at the groovy.time.TimeCategory class we see that the extension methods are all declared as static
methods. In fact, this is one of the requirements that must be met by category classes for its methods to be successfully added to
a class inside the use code block:

Another requirement is the first argument of the static method must define the type the method is attached to once being activated. The
other arguments are the normal arguments the method will take as parameters.

Because of the parameter and static method convention, category method definitions may be a bit less intuitive than
normal method definitions. As an alternative Groovy comes with a @Category annotation that transforms annotated classes
into category classes at compile-time.

Applying the @Category annotation has the advantage of being able to use instance methods without the target type as a
first parameter. The target type class is given as an argument to the annotation instead.

1.7. Metaclasses

(TBD)

1.7.1. Custom metaclasses

(TBD)

Delegating metaclass

(TBD)

Magic package (Maksym Stavytskyi)

(TBD)

1.7.2. Per instance metaclass

(TBD)

1.7.3. ExpandoMetaClass

Groovy comes with a special MetaClass the so-called ExpandoMetaClass. It is special in that it allows for dynamically
adding or changing methods, constructors, properties and even static methods by using a neat closure syntax.

Applying those modifications can be especially useful in mocking or stubbing scenarios as shown in the Testing Guide.

Every java.lang.Class is supplied by Groovy with a special metaClass property that will give you a reference to an
ExpandoMetaClass instance. This instance can then be used to add methods or change the behaviour of already existing
ones.

By default ExpandoMetaClass doesn’t do inheritance. To enable this you must call ExpandoMetaClass#enableGlobally()
before your app starts such as in the main method or servlet bootstrap.

The following sections go into detail on how ExpandoMetaClass can be used in various scenarios.

Methods

Once the ExpandoMetaClass is accessed by calling the metaClass property, methods can added by using either the left shift
<< or the = operator.

Note that the left shift operator is used to append a new method. If a public method with the same name and
parameter types is declared by the class or interface, including those inherited from superclasses and superinterfaces
but excluding those added to the metaClass at runtime, an exception will be thrown. If you want to replace a
method declared by the class or interface you can use the = operator.

The operators are applied on a non-existent property of metaClass passing an instance of a Closure code block.

The example above shows how a new method can be added to a class by accessing the metaClass property and using the << or
= operator to assign a Closure code block. The Closure parameters are interpreted as method parameters. Parameterless methods
can be added by using the {→ …​} syntax.

Properties

ExpandoMetaClass supports two mechanisms for adding or overriding properties.

Firstly, it has support for declaring a mutable property by simply assigning a value to a property of metaClass:

In the source code example above the property is dictated by the closure and is a read-only property. It is feasible to add
an equivalent setter method but then the property value needs to be stored for later usage. This could be done as
shown in the following example.

This is not the only technique however. For example in a servlet container one way might be to store the values in
the currently executing request as request attributes (as is done in some cases in Grails).

Constructors

Constructors can be added by using a special constructor property. Either the << or = operator can be used
to assign a Closure code block. The Closure arguments will become the constructor arguments when the code is
executed at runtime.

Dynamic Method Names

Since Groovy allows you to use Strings as property names this in turns allows you to dynamically create method and
property names at runtime. To create a method with a dynamic name simply use the language feature of reference property
names as strings.

The example above shows a codec implementation. Grails comes with various codec implementations each defined in a single class.
At runtime there will be multiple codec classes in the application classpath. At application startup the framework adds
a encodeXXX and a decodeXXX method to certain meta-classes where XXX is the first part of the codec class name (e.g.
encodeHTML). This mechanism is in the following shown in some Groovy pseudo-code:

Runtime Discovery

At runtime it is often useful to know what other methods or properties exist at the time the method is executed. ExpandoMetaClass
provides the following methods as of this writing:

getMetaMethod

hasMetaMethod

getMetaProperty

hasMetaProperty

Why can’t you just use reflection? Well because Groovy is different, it has the methods that are "real" methods and
methods that are available only at runtime. These are sometimes (but not always) represented as MetaMethods. The
MetaMethods tell you what methods are available at runtime, thus your code can adapt.

This is of particular use when overriding invokeMethod, getProperty and/or setProperty.

GroovyObject Methods

Another feature of ExpandoMetaClass is that it allows to override the methods invokeMethod, getProperty and
setProperty, all of them can be found in the groovy.lang.GroovyObject class.

The first step in the Closure code is to lookup the MetaMethod for the given name and arguments. If the method
can be found everything is fine and it is delegated to. If not, a dummy value is returned.

A MetaMethod is a method that is known to exist on the MetaClass whether added at runtime or at compile-time.

The logic that is used for overriding the static method is the same as we’ve seen before for overriding instance methods. The
only difference is the access to the metaClass.static property and the call to getStaticMethodName for retrieving
the static MetaMethod instance.

Extending Interfaces

It is possible to add methods onto interfaces with ExpandoMetaClass. To do this however, it must be enabled
globally using the ExpandoMetaClass.enableGlobally() method before application start-up.

1.8. Extension modules

1.8.1. Extending existing classes

An extension module allows you to add new methods to existing classes, including classes which are precompiled, like
classes from the JDK. Those new methods, unlike those defined through a metaclass or using a category, are available
globally. For example, when you write:

Standard extension method

def file = new File(...)
def contents = file.getText('utf-8')

The getText method doesn’t exist on the File class. However, Groovy knows it because it is defined in a special
class, ResourceGroovyMethods:

You may notice that the extension method is defined using a static method in a helper class (where various extension
methods are defined). The first argument of the getText method corresponds to the receiver, while additional parameters
correspond to the arguments of the extension method. So here, we are defining a method called getText on
the File class (because the first argument is of type File), which takes a single argument as a parameter (the encoding String).

The process of creating an extension module is simple:

write an extension class like above

write a module descriptor file

Then you have to make the extension module visible to Groovy, which is as simple as having the extension module classes
and descriptor available on classpath. This means that you have the choice:

either provide the classes and module descriptor directly on classpath

or bundle your extension module into a jar for reusability

An extension module may add two kind of methods to a class:

instance methods (to be called on an instance of a class)

static methods (to be called on the class itself)

1.8.2. Instance methods

To add an instance method to an existing class, you need to create an extension class. For example, let’s say you
want to add a maxRetries method on Integer which accepts a closure and executes it at most n times until no
exception is thrown. To do that, you only need to write the following:

First argument of the static method corresponds to the class being extended and is unused

In which case you can call it directly on the String class:

assert String.greeting() == 'Hello, world!'

1.8.4. Module descriptor

For Groovy to be able to load your extension methods, you must declare
your extension helper classes. You must create a file named
org.codehaus.groovy.runtime.ExtensionModule into the
META-INF/services directory:

moduleVersion: the version of your module. Note that version number
is only used to check that you don’t load the same module in two
different versions.

extensionClasses: the list of extension helper classes for instance
methods. You can provide several classes, given that they are comma
separated.

staticExtensionClasses: the list of extension helper classes for
static methods. You can provide several classes, given that they are
comma separated.

Note that it is not required for a module to define both static helpers
and instance helpers, and that you may add several classes to a single
module. You can also extend different classes in a single module without
problem. It is even possible to use different classes in a single
extension class, but it is recommended to group extension methods into
classes by feature set.

1.8.5. Extension modules and classpath

It’s worth noting that you can’t use an extension which is compiled at the same time as code using it. That means that
to use an extension, it has to be available on classpath, as compiled classes, before the code using it gets compiled.
Usually, this means that you can’t have the test classes in the same source unit as the extension class itself. Since
in general, test sources are separated from normal sources and executed in another step of the build, this is not an issue.

1.8.6. Compatibility with type checking

Unlike categories, extension modules are compatible with type checking: if they are found on classpath, then the type
checker is aware of the extension methods and will not complain when you call them. It is also compatible with static
compilation.

2. Compile-time metaprogramming

Compile-time metaprogramming in Groovy allows code generation at compile-time. Those transformations are altering the
Abstract Syntax Tree (AST) of a program, which is why in Groovy we call it AST transformations. AST transformations
allow you to hook into the compilation process, modify the AST and continue the compilation process to generate regular
bytecode. Compared to runtime metaprogramming, this has the advantage of making the changes visible in the class file
itself (that is to say, in the bytecode). Making it visible in the bytecode is important for example if you want the
transformations to be part of the class contract (implementing interfaces, extending abstract classes, …​) or even
if you need your class to be callable from Java (or other JVM languages). For example, an AST transformation can add
methods to a class. If you do it with runtime metaprogramming, the new method would only be visible from Groovy. If you
do the same using compile-time metaprogramming, the method would be visible from Java too. Last but not least, performance
would likely be better with compile-time metaprogramming (because no initialization phase is required).

In this section, we will start with explaining the various compile-time transformations that are bundled with the Groovy
distribution. In a subsequent section, we will describe how you can implement your own AST transformations
and what are the disadvantages of this technique.

global AST transformations are applied transparently, globally, as soon as they are found on compile classpath

local AST transformations are applied by annotating the source code with markers. Unlike global AST transformations,
local AST transformations may support parameters.

Groovy doesn’t ship with any global AST transformation, but you can find a list of local AST transformations
available for you to use in your code here:

2.1.1. Code generation transformations

This category of transformation includes AST transformations which help removing boilerplate code. This is typically
code that you have to write but that does not carry any useful information. By autogenerating this boilerplate code,
the code you have to write is left clean and concise and the chance of introducing an error by getting such
boilerplate code incorrect is reduced.

@groovy.transform.ToString

The @ToString AST transformation generates a human readable toString representation of the class. For example,
annotating the Person class like below will automatically generate the toString method for you:

@groovy.transform.TupleConstructor

The @TupleConstructor annotation aims at eliminating boilerplate code by generating constructors for you. A tuple
constructor is created for each property, with default values (using the Java default values). For example, the
following code will generate 3 constructors:

The first constructor is a no-arg constructor which allows the traditional map-style construction. It is worth noting
that if the first property (or field) has type LinkedHashMap or if there is a single Map, AbstractMap or HashMap
property (or field), then the map-style mapping is not available.

The other constructors are generated by taking the properties in the order they are defined. Groovy will generate as
many constructors as they are properties (or fields, depending on the options).

By default, the transformation will do nothing if a constructor is already defined. Setting this property
to true, the constructor will be generated and it’s your responsibility to ensure that no duplicate constructor
is defined

The @Category transformation lets you write the same using an instance-style class, rather than a static class style.
This removes the need for having the first argument of each method being the receiver. The category can be written like
this:

Note that the mixed in class can be referenced using this instead. It’s also worth noting that using instance fields
in a category class is inherently unsafe: categories are not stateful (like traits).

@groovy.transform.IndexedProperty

The @IndexedProperty annotation aims at generating indexed getters/setters for properties of list/array types.
This is in particular useful if you want to use a Groovy class from Java. While Groovy supports GPath to access properties,
this is not available from Java. The @IndexedProperty annotation will generate indexed properties of the following
form:

The default value which is used to initialize the field is the default constructor of the declaration type. It is possible
to define a default value by using a closure on the right hand side of the property assignment, as in the following
example:

If the field is declared volatile then initialization will be synchronized using the
double-checked locking pattern.

Using the soft=true parameter, the helper field will use a SoftReference instead, providing a simple way to
implement caching. In that case, if the garbage collector decides to collect the reference, initialization will occur
the next time the field is accessed.

@groovy.lang.Newify

The @Newify AST transformation is used to bring alternative syntaxes to construct objects:

@groovy.transform.Sortable

The @Sortable AST transformation is used to help write classes that are Comparable and easily sorted by
numerous properties. It is easy to use as shown in the following example where we annotate the Person class:

Normally, all properties are used in the generated compareTo method in the priority order in which they are defined.
You can include or exclude certain properties from the generated compareTo method by giving a list of property names
in the includes or excludes annotation attributes. If using includes, the order of the property names given will
determine the priority of properties when comparing. To illustrate, consider the following Person class definition:

@groovy.transform.builder.Builder

The @Builder AST transformation is used to help write classes that can be created using fluent api calls.
The transform supports multiple building strategies to cover a range of cases and there are a number
of configuration options to customize the building process. If you’re an AST hacker, you can also define your own
strategy class. The following table lists the available strategies that are bundled with Groovy and the
configuration options each strategy supports.

Strategy

Description

builderClassName

builderMethodName

buildMethodName

prefix

includes/excludes

SimpleStrategy

chained setters

n/a

n/a

n/a

yes, default "set"

yes

ExternalStrategy

explicit builder class, class being built untouched

n/a

n/a

yes, default "build"

yes, default ""

yes

DefaultStrategy

creates a nested helper class

yes, default <TypeName>Builder

yes, default "builder"

yes, default "build"

yes, default ""

yes

InitializerStrategy

creates a nested helper class providing type-safe fluent creation

yes, default <TypeName>Initializer

yes, default "createInitializer"

yes, default "create" but usually only used internally

yes, default ""

yes

SimpleStrategy

To use the SimpleStrategy, annotate your Groovy class using the @Builder annotation, and specify the strategy as shown in this example:

You can use the SimpleStrategy in conjunction with @Canonical. If your @Builder annotation doesn’t have
explicit includes or excludes annotation attributes but your @Canonical annotation does, the ones
from @Canonical will be re-used for @Builder.

The annotation attributes builderClassName, buildMethodName, builderMethodName and forClass are not supported for this strategy.

Groovy already has built-in building mechanisms. Don’t rush to using @Builder if the built-in mechanisms meet your needs. Some examples:

To use the ExternalStrategy, create and annotate a Groovy builder class using the @Builder annotation, specify the
class the builder is for using forClass and indicate use of the ExternalStrategy.
Suppose you have the following class you would like a builder for:

The class you are creating the builder for can be any Java or Groovy class following the normal JavaBean conventions,
e.g. a no-arg constructor and setters for the properties. Here is an example using a Java class:

The builderMethodName and builderClassName annotation attributes for @Builder aren’t applicable for this strategy.

You can use the ExternalStrategy in conjunction with @Canonical. If your @Builder annotation doesn’t have
explicit includes or excludes annotation attributes but the @Canonical annotation of the class you are creating
the builder for does, the ones from @Canonical will be re-used for @Builder.

DefaultStrategy

To use the DefaultStrategy, annotate your Groovy class using the @Builder annotation as shown in this example:

If you want, you can customize various aspects of the building process
using the builderClassName, buildMethodName, builderMethodName, prefix, includes and excludes annotation attributes,
some of which are used in the example here:

This strategy also supports annotating static methods and constructors. In this case, the static method or constructor
parameters become the properties to use for building purposes and in the case of static methods, the return type
of the method becomes the target class being built. If you have more than one @Builder annotation used within
a class (at either the class, method or constructor positions) then it is up to you to ensure that the generated
helper classes and factory methods have unique names (i.e. no more than one can use the default name values).
Here is an example highlighting method and constructor usage (and also illustrating the renaming required for unique names).

Any attempt to use the initializer which doesn’t involve setting all the properties (though order is not important) will result in
a compilation error. If you don’t need this level of strictness, you don’t need to use @CompileStatic.

You can use the InitializerStrategy in conjunction with @Canonical and @Immutable. If your @Builder annotation
doesn’t have explicit includes or excludes annotation attributes but your @Canonical annotation does, the ones
from @Canonical will be re-used for @Builder. Here is an example using @Builder with @Immutable:

This strategy also supports annotating static methods and constructors. In this case, the static method or constructor
parameters become the properties to use for building purposes and in the case of static methods, the return type
of the method becomes the target class being built. If you have more than one @Builder annotation used within
a class (at either the class, method or constructor positions) then it is up to you to ensure that the generated
helper classes and factory methods have unique names (i.e. no more than one can use the default name values).
For an example of method and constructor usage but using the DefaultStrategy strategy, consult that strategy’s
documentation.

The annotation attribute forClass is not supported for this strategy.

2.1.2. Class design annotations

This category of annotations are aimed at simplifying the implementation of well-known design patterns (delegation,
singleton, …​) by using a declarative style.

@groovy.transform.BaseScript

@BaseScript is used within scripts to indicate that the script should
extend fron a custom script base class rather than groovy.lang.Script.
See the documentation for domain specific languages for further details.

@groovy.lang.Delegate

The @Delegate AST transformation aims at implementing the delegation design pattern. In the following class:

class Event {
@Delegate Date when
String title
}

The when field is annotated with @Delegate, meaning that the Event class will delegate calls to Date methods
to the when field. In this case, the generated code looks like this:

@groovy.transform.Immutable

The @Immutable AST transformation simplifies the creation of immutable classes, that is to say classes for which
members are deemed immutable. For that, all you have to do is annotating the class like in the following example:

Immutable classes generated with @Immutable are automatically made final. For a class to be immutable, you have to
make sure that properties are of an immutable type (primitive or boxed types), of a known-immutable type or another
class annotated with @Immutable. The effect of applying @Immutable to a class are pretty similar to those of
applying the @Canonical AST transformation, but with an immutable class: automatic generation of
toString, equals and hashCode methods for example, but trying to modify a property would throw a ReadOnlyPropertyException
in that case.

Since @Immutable relies on a predefined list of known immutable classes (like java.net.URI or java.lang.String
and fails if you use a type which is not in that list, you are allowed to instruct the transformation that some types
are deemed immutable thanks to the following parameters:

@groovy.transform.Memoized

The @Memoized AST transformations simplifies the implementation of caching by allowing the result of method calls
to be cached just by annotating the method with @Memoized. Let’s imagine the following method:

The size of the cache can be configured using two optional parameters:

protectedCacheSize: the number of results which are guaranteed not to be cleared after garbage collection

maxCacheSize: the maximum number of results that can be kept in memory

By default, the size of the cache is unlimited and no cache result is protected from garbage collection. Setting a
protectedCacheSize>0 would create an unlimited cache with some results protected. Setting maxCacheSize>0 would
create a limited cache but without any protection from garbage protection. Setting both would create a limited,
protected cache.

@groovy.transform.TailRecursive

TBD

@groovy.lang.Singleton

The @Singleton annotation can be used to implement the singleton design pattern on a class. The singleton instance
is defined eagerly by default, using class initialization, or lazily, in which case the field is initialized using
double checked locking.

In this example, we also set the strict parameter to false, which allows us to define our own constructor.

@groovy.lang.Mixin

Deprecated. Consider using traits instead.

2.1.3. Logging improvements

Groovy provides AST transformation that helps integrating with the most widely used logging frameworks. It’s worth noting
that annotating a class with one of those annotations doesn’t prevent you from adding the appropriate logging framework
on classpath.

All transformations work in a similar way:

add static final log field corresponding to the logger

wrap all calls to log.level() into the appropriate log.isLevelEnabled guard, depending on the underlying framework

Those transformations support two parameters:

value (default log) corresponds to the name of the logger field

category (defaults to the class name) is the name of the logger category

@groovy.util.logging.Log

The first logging AST transformation available is the @Log annotation which relies on the JDK logging framework. Writing:

@groovy.transform.WithReadLock and @groovy.transform.WithWriteLock

The @WithReadLock AST transformation works in conjunction with the @WithWriteLock transformation
to provide read/write synchronization using the ReentrantReadWriteLock facility that the JDK provides. The annotation
can be added to a method or a static method. It will transparently create a $reentrantLock final field (or
$REENTRANTLOCK for a static method) and proper synchronization code will be added. For example, the following code:

Note that the String properties aren’t explicitly handled because Strings are immutable and the clone() method from Object will copy the String references. The same would apply to primitive fields and most of the concrete subclasses of java.lang.Number.

In addition to cloning styles, @AutoClone supports multiple options:

Attribute

Default value

Description

Example

excludes

Empty list

A list of property or field names that need to be excluded from cloning. A string consisting of a comma-separated field/property names is also allowed.
See groovy.transform.AutoClone#excludes for details

@groovy.transform.AutoExternalize

The @AutoExternalize AST transformation will assist in the creation of java.io.Externalizable classes. It will
automatically add the interface to the class and generate the writeExternal and readExternal methods. For example, this
code:

The @AutoExternalize annotation supports two parameters which will let you slightly customize its behavior:

Attribute

Default value

Description

Example

excludes

Empty list

A list of property or field names that need to be excluded from externalizing. A string consisting of a comma-separated field/property names is also allowed.
See groovy.transform.AutoExternalize#excludes for details

2.1.6. Safer scripting

The Groovy language makes it easy to execute user scripts at runtime (for example using groovy.lang.GroovyShell),
but how do you make sure that a script won’t eat all CPU (infinite loops) or that concurrent scripts won’t slowly consume
all available threads of a thread pool? Groovy provides several annotations which are aimed towards safer scripting,
generating code which will for example allow you to interrupt execution automatically.

@groovy.transform.ThreadInterrupt

One complicated situation in the JVM world is when a thread can’t be stopped. The Thread#stop method exists but is
deprecated (and isn’t reliable) so your only chance relies in Thread#interrupt. Calling the latter will set the
interrupt flag on the thread, but it will not stop the execution of the thread. This is problematic because it’s the
responsibility of the code executing in the thread to check the interrupt flag and properly exit. This makes sense when
you, as a developer, know that the code you are executing is meant to be run in an independent thread, but in general,
you don’t know it. It’s even worse with user scripts, who might not even know what a thread is (think of DSLs).

@ThreadInterrupt simplifies this by adding thread interruption checks at critical places in the code:

loops (for, while)

first instruction of a method

first instruction of a closure body

Let’s imagine the following user script:

while (true) {
i++
}

This is an obvious infinite loop. If this code executes in its own thread, interrupting wouldn’t help: if you join on
the thread, then the calling code would be able to continue, but the thread would still be alive, running in background
without any ability for you to stop it, slowly causing thread starvation.

@groovy.transform.TimedInterrupt

The @TimedInterrupt AST transformation tries to solve a slightly different problem from @groovy.transform.ThreadInterrupt: instead of checking the interrupt flag of the thread, it will automatically
throw an exception if the thread has been running for too long.

This annotation does not spawn a monitoring thread. Instead, it works in a similar manner as @ThreadInterrupt by placing checks at appropriate places in the code. This means that if you
have a thread blocked by I/O, it will not be interrupted.

Imagine the following user code:

def fib(int n) { n<2?n:fib(n-1)+fib(n-2) }
result = fib(600)

The implementation of the famous Fibonacci number computation here is far from optimized. If it is called with a high n value, it can take minutes to answer. With @TimedInterrupt, you can
choose how long a script is allowed to run. The following setup code will allow the user script to run for 1 second at max:

@groovy.transform.ConditionalInterrupt

The last annotation for safer scripting is the base annotation when you want to interrupt a script using a custom strategy. In particular, this is the annotation of choice if you
want to use resource management (limit the number of calls to an API, …​). In the following example, user code is using an infinite loop, but @ConditionalInterrupt will allow us
to check a quota manager and interrupt automatically the script:

2.1.7. Compiler directives

This category of AST transformations groups annotations which have a direct impact on the semantics of the code, rather
than focusing on code generation. With that regards, they can be seen as compiler directives that either change the
behavior of a program at compile time or runtime.

@groovy.transform.Field

The @Field annotation only makes sense in the context of a script and aims at solving a common scoping error with
scripts. The following example will for example fail at runtime:

The error that is thrown may be difficult to interpret: groovy.lang.MissingPropertyException: No such property: x. The reason is that scripts are compiled
to classes and the script body is itself compiled as a single run() method. Methods which are defined in the scripts are independent, so the code above is
equivalent to this:

So def x is effectively interpreted as a local variable, outside of the scope of the line method. The @Field AST transformation aims at fixing this
by changing the scope of the variable to a field of the enclosing script:

@groovy.transform.PackageScope

By default, Groovy visibility rules imply that if you create a field without specifying a modifier, then the field is interpreted as a property:

class Person {
String name // this is a property
}

Should you want to create a package private field instead of a property (private field+getter/setter), then annotate your field with @PackageScope:

class Person {
@PackageScope String name // not a property anymore
}

The @PackageScope annotation can also be used for classes, methods and constructors. In addition, by specifying a list
of PackageScopeTarget values as the annotation attribute at the class level, all members within that class that don’t
have an explicit modifier and match the provided PackageScopeTarget will remain package protected. For example to apply
to fields within a class use the following annotation:

The @PackageScope annotation is seldom used as part of normal Groovy conventions but is sometimes useful
for factory methods that should be visible internally within a package or for methods or constructors provided
for testing purposes, or when integrating with third-party libraries which require such visibility conventions.

@groovy.transform.AnnotationCollector

@AnnotationCollector allows the creation of meta-annotation, which are described in a dedicated section.

@groovy.transform.CompileDynamic

@groovy.lang.DelegatesTo

@DelegatesTo is not, technically speaking, an AST transformation. It is aimed at documenting code and helping the compiler in case you are
using type checking or static compilation. The annotation is described thoroughly in the
DSL section of this guide.

@groovy.transform.SelfType

@SelfType is not an AST transformation but rather a marker interface used
with traits. See the traits documentation for further details.

2.1.8. Swing patterns

@groovy.beans.Bindable

@Bindable is an AST transformation that transforms a regular property into a bound property (according to the JavaBeans specification).
The @Bindable annotation can be placed on a property or a class. To convert all properties of a class into bound properties, on can annotate the class like in this example:

The transform will generate the appropriate add/remove methods based on the generic type of the list. In addition, it will also create fireXXX methods based on the public methods declared on the class:

@groovy.beans.Vetoable

The @Vetoable annotation works in a similar manner to @Bindable but generates constrained property according to the JavaBeans specification, instead of bound properties. The annotation
can be placed on a class, meaning that all properties will be converted to constrained properties, or on a single property. For example, annotating this class with @Vetoable:

2.1.9. Test assistance

@groovy.transform.NotYetImplemented

@NotYetImplemented is used to invert the result of a JUnit 3/4 test case. It is in particular useful if a feature is not yet implemented but the test is. In that case, it is expected
that the test fails. Marking it with @NotYetImplemented will inverse the result of the test, like in this example:

Another advantage of using this technique is that you can write test cases for bugs before knowing how to fix them. If some time in the future, a modification in the code fixes a bug by side effect,
you’ll be notified because a test which was expected to fail passed.

@groovy.transform.ASTTest

@ASTTest is a special AST transformation meant to help debugging other AST transformations or the Groovy compiler itself. It will let the developer "explore" the AST during compilation and
perform assertions on the AST rather than on the result of compilation. This means that this AST transformations gives access to the AST before the bytecode is produced. @ASTTest can be
placed on any annotable node and requires two parameters:

phase: sets at which phase at which @ASTTest will be triggered. The test code will work on the AST tree at the end of this phase.

value: the code which will be executed once the phase is reached, on the annotated node

Compile phase has to be chosen from one of org.codehaus.groovy.control.CompilePhase . However, since it is not possible to annotate a node twice with the same annotation, you will
not be able to use @ASTTest on the same node at two distinct compile phases.

value is a closure expression which has access to a special variable node corresponding to the annotated node, and a helper lookup method which will be discussed here.
For example, you can annotate a class node like this:

we’re checking the state of the Abstract Syntax Tree after the CONVERSION phase

2

node refers to the AST node which is annotated by @ASTTest

3

it can be used to perform assertions at compile time

One interesting feature of @ASTTest is that if an assertion fails, then compilation will fail. Now imagine that we want to check the behavior of an AST transformation at compile time.
We will take @PackageScope here, and we will want to verify that a property annotated with @PackageScope becomes a package private field. For this, we have to know at which phase the
transform runs, which can be found in org.codehaus.groovy.transform.PackageScopeASTTransformation : semantic analysis. Then a test can be written like this:

The @ASTTest annotation can only be placed wherever the grammar allows it. Sometimes, you would like to test the contents of an AST node which is not annotable. In this case,
@ASTTest provides a convenient lookup method which will search the AST for nodes which are labelled with a special token:

def list = lookup('anchor') (1)
Statement stmt = list[0] (2)

1

returns the list of AST nodes which label is 'anchor'

2

it is always necessary to choose which element to process since lookup always returns a list

Imagine, for example, that you want to test the declared type of a for loop variable. Then you can do it like this:

The latter is interesting if you don’t specify the phase attribute. In that case, the closure will be executed after
each compile phase after (and including) SEMANTIC_ANALYSIS. The context of the transformation is kept after each phase,
giving you a chance to check what changed between two phases.

As an example, here is how you could dump the list of AST transformations registered on a class node:

otherwise, if toString exists and that the variable from the context, added is null

4

then it means that this compile phase is the one where toString was added

2.1.10. Grape handling

@groovy.lang.Grab

@groovy.lang.GrabConfig

@groovy.lang.GrabExclude

@groovy.lang.GrabResolver

@groovy.lang.Grapes

Grape is a dependency management engine embedded into Groovy, relying on several annotations which are described
thoroughly in this section of the guide.

2.2. Developing AST transformations

There are two kinds of transformations: global and local transformations.

Global transformations are applied to by the compiler on the code being compiled,
wherever the transformation apply. Compiled classes that implement global transformations
are in a JAR added to the classpath of the compiler and contain service locator file
META-INF/services/org.codehaus.groovy.transform.ASTTransformation with a line with the name of the
transformation class. The transformation class must have a no-args constructor and implement the
org.codehaus.groovy.transform.ASTTransformation interface.
It will be run against every source in the compilation, so be sure to not create transformations which
scan all the AST in an expansive and time-consuming manner, to keep the compiler fast.

Local transformations are transformations applied locally by annotating code elements you want to
transform. For this, we reuse the annotation notation, and those annotations should implement
org.codehaus.groovy.transform.ASTTransformation. The compiler will discover them and apply the
transformation on these code elements.

Generally speaking, there is more type information available later in
the phases. If your transformation is concerned with reading the AST,
then a later phase where information is more plentiful might be a good
choice. If your transformation is concerned with writing AST, then an
earlier phase where the tree is more sparse might be more convenient.

2.2.2. Local transformations

Local AST transformations are relative to the context they are applied to. In
most cases, the context is defined by an annotation that will define the scope
of the transform. For example, annotating a field would mean that the transformation
applies to the field, while annotating the class would mean that the transformation
applies to the whole class.

As a naive and simple example, consider wanting to write a @WithLogging
transformation that would add console messages at the start and end of a
method invocation. So the following "Hello World" example would
actually print "Hello World" along with a start and stop message:

Poor man’s aspect oriented programming

@WithLogging
def greet() {
println "Hello World"
}
greet()

A local AST transformation is an easy way to do this. It requires two things:

The annotation retention can be SOURCE because you won’t need the annotation
past that. The element type here is METHOD, the @WithLogging because the annotation
applies to methods.

But the most important part is the
@GroovyASTTransformationClass annotation. This links the @WithLogging
annotation to the ASTTransformation class you will write.
gep.WithLoggingASTTransformation is the fully qualified class name of the
ASTTransformation we are going to write. This line wires the annotation to the transformation.

With this in place, the Groovy compiler is going to invoke
gep.WithLoggingASTTransformation every time an @WithLogging is found in a
source unit. Any breakpoint set within LoggingASTTransformation will now
be hit within the IDE when running the sample script.

The ASTTransformation class is a little more complex. Here is the
very simple, and very naive, transformation to add a method start and
stop message for @WithLogging:

the nodes parameter is a 2 AST node array, for which the first one is the annotation node (@WithLogging) and
the second one is the annotated node (the method node)

6

create a statement that will print a message when we enter the method

7

create a statement that will print a message when we exit the method

8

get the method body, which in this case is a BlockStatement

9

add the enter method message before the first statement of existing code

10

append the exit method message after the last statement of existing code

11

creates an ExpressionStatement wrapping a MethodCallExpression corresponding to this.println("message")

It is important to notice that for the brevity of this example, we didn’t make the necessary checks, such as checking
that the annotated node is really a MethodNode, or that the method body is an instance of BlockStatement. This
exercise is left to the reader.

Note the creation of the new println statements in the
createPrintlnAst(String) method. Creating AST for code is not always
simple. In this case we need to construct a new method call, passing in
the receiver/variable, the name of the method, and an argument list.
When creating AST, it might be helpful to write the code you’re trying
to create in a Groovy file and then inspect the AST of that code in the
debugger to learn what to create. Then write a function like
createPrintlnAst using what you learned through the debugger.

In the end:

@WithLogging
def greet() {
println "Hello World"
}
greet()

Produces:

Starting greet
Hello World
Ending greet

It is important to note that an AST transformation participates directly in the compilation process. A common
error by beginners is to have the AST transformation code in the same source tree as a class that uses the transformation.
Being in the same source tree in general means that they are compiled at the same time. Since the transformation itself
is going to be compiled in phases and that each compile phase processes all files of the same source unit before going
to the next one, there’s a direct consequence: the transformation will not be compiled before the class that uses it! In
conclusion, AST transformations need to be precompiled before you can use them. In general, it is as easy as having them
in a separate source tree.

2.2.3. Global transformations

Global AST transformation are similar to local one with a major difference: they do not need an annotation, meaning that
they are applied globally, that is to say on each class being compiled. It is therefore very important to limit their
use to last resort, because it can have a significant impact on the compiler performance.

Following the example of the local AST transformation, imagine that we would like to trace all
methods, and not only those which are annotated with @WithLogging. Basically, we need this code to behave the same
as the one annotated with @WithLogging before:

the sourceUnit parameter gives access to the source being compiled, so we get the AST of the current source
and retrieve the list of methods from this file

6

we iterate on each method from the source file

7

create a statement that will print a message when we enter the method

8

create a statement that will print a message when we exit the method

9

get the method body, which in this case is a BlockStatement

10

add the enter method message before the first statement of existing code

11

append the exit method message after the last statement of existing code

12

creates an ExpressionStatement wrapping a MethodCallExpression corresponding to this.println("message")

2.2.4. AST API guide

AbstractASTTransformation

While you have seen that you can directly implement the ASTTransformation interface, in almost all cases you will not
do this but extend the org.codehaus.groovy.transform.AbstractASTTransformation class. This class provides several
utility methods that make AST transformations easier to write. Almost all AST transformations included in Groovy
extend this class.

Internally the transformation creates a ClassCodeExpressionTransformer

2

The transformer needs to return the source unit

3

if a constant expression of type string is detected inside an argument list, transform it into its upper case version

4

call the transformer on the method being annotated

AST Nodes

Writing an AST transformation requires a deep knowledge of the internal Groovy API. In particular it requires
knowledge about the AST classes. Since those classes are internal, there are chances that the API will change in the
future, meaning that your transformations could break. Despite that warning, the AST has been very stable over time
and such a thing rarely happens.

Classes of the Abstract Syntax Tree belong to the org.codehaus.groovy.ast package. It is recommended to the reader
to use the Groovy Console, in particular the AST browser tool, to gain knowledge about those classes. However, a good
resource for learning is the AST Builder
test suite.

2.2.5. Testing AST transformations

Separating source trees

This section is about good practices with regards to testing AST transformations. Previous sections highlighted the fact
that to be able to execute an AST transformation, it has to be precompiled. It might sound obvious but a lot of people
get caught on this, trying to use an AST transformation in the same source tree as where it is defined.

The first tip for testing AST transformation is therefore to separate test sources from the sources of the transform.
Again, this is nothing but best practices, but you must make sure that your build too does actually compile them separately.
This is the case by default with both Apache Maven and Gradle.

Debugging AST transformations

It is very handy to be able to put a breakpoint in an AST transformation, so that you can debug your code in the IDE.
However, you might be surprised to see that your IDE doesn’t stop on the breakpoint. The reason is actually simple: if
your IDE uses the Groovy compiler to compile the unit tests for your AST transformation, then the compilation is triggered
from the IDE, but the process which will compile the files doesn’t have debugging options. It’s only when the test case
is executed that the debugging options are set on the virtual machine. In short: it is too late, the class has been compiled
already, and your transformation is already applied.

A very easy workaround is to use the GroovyTestCase class which provides an assertScript method. This means that
instead of writing this in a test case:

The difference is that when you use assertScript, the code in the assertScript block is compiled when the
unit test is executed. That is to say that this time, the Subject class will be compiled with debugging active, and
the breakpoint is going to be hit.

ASTTest

Last but not least, testing an AST transformation is also about testing the state of the AST during compilation. Groovy
provides a tool named @ASTTest for this: it is an annotation that will let you add assertions on an abstract syntax
tree. Please check the documentation for ASTTest for more details.

2.2.6. External references

If you are interested in a step-by-step tutorial about writing AST transformations, you can follow
this workshop.