Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Sticking with the naive and simple example from the local transformation page, consider wanting to provide console output at the start and stop of method calls within your code. The following "Hello World" example would actually print "Hello World" along with a start and stop message:

Code Block
def greet() {
      println "Hello World"
}

greet()

...

Code Block
@GroovyASTTransformation(phase=CompilePhase.CONVERSION)
public class LoggingASTTransformation implements ASTTransformation {

      static final def TARGET = WithLogging.getName()

      public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
              List methods = sourceUnit.getAST()?.getMethods()
              methods?.each { MethodNode method ->
                       Statement startMessage = createPrintlnAst("Starting $method.name")
                       Statement endMessage = createPrintlnAst("Ending $method.name")

                       List existingStatements = method.getCode().getStatements()
                       existingStatements.add(0, startMessage)
                       existingStatements.add(endMessage)
              }
      }

      private Statement createPrintlnAst(String message) {
              return new ExpressionStatement(
                       new MethodCallExpression(
                               new VariableExpression("this"),
                               new ConstantExpression("println"),
                               new ArgumentListExpression(
                                       new ConstantExpression(message)
                               )
                       )
              )
      }
}

The first line (@GroovyASTTransformation) line tells the Groovy compiler that this is an AST transformation that should occur in the conversion CompilePhase. Unlike local transformations, global transformations can occur in any phase.

...

Code Block
story "user enters invalid postcode" {

  given    given ....

  expect    expect ...

}

Then you could allow this syntax in .story files only. To do this, you must first have registered your global AST transformation into the 'META-INF/services/org.codehaus.groovy.transform.ASTTransformation' file like explained before. The second step is to register your custom file extension into the 'META-INF/services/org.codehaus.groovy.source.Extensions' file :

...

Code Block
void visit(ASTNode[] nodes, SourceUnit source) {
        if if (!source.name.endsWith('.story')) {
            return         return
    }
         // start transforming the AST

    }

Now you have a global AST transformation that will only apply on .story files.