ClosureExpression with Groovy AST 1.6.5

Today I have to create closure with groovy AST, but when I use ClosureExpression with this snippet :

ClosureExpression closureExpression = new ClosureExpression (
  new Parameter[] {}
  , new ExpressionStatement(new PropertyExpression(new VariableExpression("it"), "class"))
);

I get a very explicit error :

java.lang.NullPointerException
at org.codehaus.groovy.classgen.AsmClassGenerator.createClosureClass(AsmClassGenerator.java:3601)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitClosureExpression(AsmClassGenerator.java:1559)
at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:46)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4037)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCallSite(AsmClassGenerator.java:1965)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1799)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1785)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeInvokeMethodCall(AsmClassGenerator.java:1768)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:2277)
at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:63)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4037)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitCastExpression(AsmClassGenerator.java:1711)
at org.codehaus.groovy.ast.expr.CastExpression.visit(CastExpression.java:66)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4037)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCallSite(AsmClassGenerator.java:1965)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1799)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1785)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeInvokeMethodCall(AsmClassGenerator.java:1768)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:2277)
at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:63)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4037)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCallSite(AsmClassGenerator.java:1941)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1799)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeCall(AsmClassGenerator.java:1785)
at org.codehaus.groovy.classgen.AsmClassGenerator.makeInvokeMethodCall(AsmClassGenerator.java:1768)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethodCallExpression(AsmClassGenerator.java:2277)
at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:63)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitAndAutoboxBoolean(AsmClassGenerator.java:4037)
at org.codehaus.groovy.classgen.AsmClassGenerator.evaluateExpression(AsmClassGenerator.java:1296)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitReturnStatement(AsmClassGenerator.java:1257)
at org.codehaus.groovy.ast.stmt.ReturnStatement.visit(ReturnStatement.java:47)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:73)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:80)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitStdMethod(AsmClassGenerator.java:552)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:528)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:88)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:632)
at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1055)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:48)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:242)
at org.codehaus.groovy.control.CompilationUnit$10.call(CompilationUnit.java:718)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:925)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:462)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:278)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:249)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:244)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:206)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:216)
at org.chromattic.groovy.core.PlopTestCase.testPlop(PlopTestCase.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:108)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:64)

Thanks to IntelliJ idea I can set a breakpoint on NullPointerException and I come in the AsmClassGenerator.java file at the line 3731 from groovy 1.6.5 sources and I can see :

VariableScope scope = ce.getVariableScope();
Parameter[] ret = new Parameter[scope.getReferencedLocalVariablesCount()];

Why developers don’t have set the scope in ClosureExpression’s constructor of control the value of the scope to avoid the NullPointerException ?

Of course the simple following statement resolve the problem :

closure.setVariableScope(new VariableScope());

If you want to use groovy (even from java code), you must be very optimistic.

One thought on “ClosureExpression with Groovy AST 1.6.5

Leave a comment