Details
-
Bug
-
Status: Closed
-
Critical
-
Resolution: Fixed
-
3.0.6
-
None
-
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-8u242-b08-0ubuntu3~18.04-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)
Description
I have encountered an issue when trying to generate code, containing chained method calls, at runtime (without source code) and compiling using CompileStatic.
What I am trying to achieve is produce code similar to:
public StringBuilder test() { StringBuilder sb = new StringBuilder().append("testString"); return sb; }
I create the appropriate AST nodes, statements, expressions, etc.
Everything works fine if I add a method like the one shown in a top-level class (the class is also dynamically generated at runtime). However, if I try to add the exact same method to a nested class, it seems like the groovy compiler gets somehow confused and, judging by the decompiler output, produces something like:
public StringBuilder test() { StringBuilder sb = ((StringBuilder)((Closure)this).getThisObject()).append("testString"); return sb; }
Naturally, this does not work.
Here's how I try to generate the method:
ClassNode topLevelClass = ClassHelper.make( "com.example.groovycompiler.test.TopLevelClass"); InnerClassNode nestedClass = new InnerClassNode( topLevelClass, "com.example.groovycompiler.test.TopLevelClass$NestedClass", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, ClassHelper.OBJECT_TYPE); ClassNode stringBuilderClass = ClassHelper.make(StringBuilder.class); nestedClass.addMethod( "test", Opcodes.ACC_PUBLIC, stringBuilderClass, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, block( declS( varX("sb", stringBuilderClass), callX(ctorX(stringBuilderClass), "append", args(constX("testString")))), returnS( varX("sb", stringBuilderClass)) ) );
Perhaps I am missing something, in which case I will be very happy to receive some pointers.
I have created a github repo with a maven project containing a unit test that demonstrates the issue: https://github.com/l-atanasov/groovy-static-compile-issue
Note, that I have extended the CompilationUnit a little to allow to run the static compiler without source.
Also, if I am not using the static compiler, everything works as expected.
Update: reformatted code for readability