Search code examples
grailsgroovygrails-ormabstract-syntax-tree

Cannot get method added to GORM object using AST transformation


Here is my GORM object

@UpdatedProperties
class Cart {
    Date lastUpdated
    Date dateCreated

    String name 
}

Here is annotation definition:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@GroovyASTTransformationClass(["UpdatedPropertiesASTTransformation"])

public @interface UpdatedProperties {
}

Here is the AST definition

@GroovyASTTransformation(phase = CompilePhase.CLASS_GENERATION)
class UpdatedPropertiesASTTransformation implements ASTTransformation{
    //...

    public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
        astNodes.findAll { node -> node instanceof ClassNode}.each {
        classNode ->
            def testMethodBody = new AstBuilder().buildFromString (
                    """
                    println(">>*************myMethod)";
                    """
            )

            def myMethod = new MethodNode('myMethod', ACC_PUBLIC, ClassHelper.VOID_TYPE, [] as Parameter[], [] as ClassNode[], testMethodBody[0])
            classNode.addMethod(myMethod)   
        }
    }
...
}

WhenI try to invoke the method I get:

groovy.lang.MissingMethodException: No signature of method: Cart.myMethod() is applicable for argument types: () values: []

Any tips appreciated. Thanks


Solution

  • Class Generation is too late a compile phase in which to add a method to a class, so you'll need to change your compile phase to either Semantic Analysis or Canonicalization. (This was probably much later than you wanted for adding a method, anyway. Groovy Compile Phase Guide)

    There are also a couple of problems in your AST String. There's a syntax error in your println, println(">>*************myMethod)"; should read println(">>*************myMethod");, and you'll need to add an explicit return; statement, since you're returning void (otherwise Groovy will add a return null; at the end of your method and this will clash with your void return type).