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.
Actually, see this thread: http://groovy.329449.n5.nabble.com/AST-problem-with-mapEntry-td3423653.html
I think your problem is similar to my problem, and the details are here:
http://groovy.329449.n5.nabble.com/AST-problem-with-mapEntry-tp3423653p3425634.html
Hope this makes more sense!