Is it possible to create a Groovy class dynamically and add fields to it using the FieldNode class? Here is my attempt:
package asttest
import org.codehaus.groovy.control.*
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.expr.*
GroovyClassLoader loader = new GroovyClassLoader()
cls = loader.parseClass('class Position{}')
ClassNode integerClassNode = new ClassNode(Integer.class)
ClassNode classNode = new ClassNode(cls)
FieldNode xFieldNode = new FieldNode(
'x', FieldNode.ACC_PUBLIC, integerClassNode, classNode, new EmptyExpression())
FieldNode yFieldNode = new FieldNode(
'y', FieldNode.ACC_PUBLIC, integerClassNode, classNode, new EmptyExpression())
FieldNode zFieldNode = new FieldNode(
'z', FieldNode.ACC_PUBLIC, integerClassNode, classNode, new EmptyExpression())
classNode.addField(xFieldNode)
classNode.addField(yFieldNode)
classNode.addField(zFieldNode)
CompilationUnit compilationUnit = new CompilationUnit(loader)
compilationUnit.addClassNode(classNode)
compilationUnit.compile()
instance = cls.newInstance()
instance.x = 1
The result when running this code is:
Caught: BUG! exception in phase 'class generation' in source unit '?' unexpected NullpointerException
BUG! exception in phase 'class generation' in source unit '?' unexpected NullpointerException
at asttest.Main.run(Main.groovy:35)
Caused by: java.lang.NullPointerException
... 1 more
I know I can add fields to a class using MetaClass (I posted a separate question), but it seems that using Groovy AST classes would be more flexible.