You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/03/29 18:15:37 UTC
[groovy] 02/02: GROOVY-8104: fix this$0 for closure with anon.
inner class of inner type
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit ffb6856474f7cf138eabd594fc22bb06fa7cf0e3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Mar 21 13:21:33 2021 -0500
GROOVY-8104: fix this$0 for closure with anon. inner class of inner type
3_0_X backport
class Outer {
class Inner {
// requires Outer reference
}
def x = { ->
new Inner() { // this.this$0 returns closure; call getThisObject()
}
}
}
---
.../groovy/classgen/InnerClassVisitor.java | 29 +++++++++++------
src/test/gls/innerClass/InnerClassTest.groovy | 36 ++++++++++++++++++----
2 files changed, 50 insertions(+), 15 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java
index 4826404..2222c58 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java
@@ -33,7 +33,7 @@ import org.codehaus.groovy.ast.VariableScope;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
@@ -48,6 +48,11 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+
public class InnerClassVisitor extends InnerClassVisitorHelper implements Opcodes {
private ClassNode classNode;
@@ -290,14 +295,20 @@ public class InnerClassVisitor extends InnerClassVisitorHelper implements Opcode
// if constructor call is not in outer class, don't pass 'this' implicitly. Return.
if (parent == null) return;
- //add this parameter to node
- Expression argsExp = call.getArguments();
- if (argsExp instanceof TupleExpression) {
- TupleExpression argsListExp = (TupleExpression) argsExp;
- Expression this0 = VariableExpression.THIS_EXPRESSION;
- for (int i = 0; i != level; ++i)
- this0 = new PropertyExpression(this0, "this$0");
- argsListExp.getExpressions().add(0, this0);
+ Expression args = call.getArguments();
+ if (args instanceof TupleExpression) {
+ Expression this0 = varX("this"); // bypass closure
+ for (int i = 0; i != level; ++i) {
+ this0 = attrX(this0, constX("this$0"));
+ // GROOVY-8104: an anonymous inner class may still have closure nesting
+ if (i == 0 && classNode.getDeclaredField("this$0").getType().equals(ClassHelper.CLOSURE_TYPE)) {
+ MethodCallExpression getThis = callX(this0, "getThisObject");
+ getThis.setImplicitThis(false);
+ this0 = getThis;
+ }
+ }
+
+ ((TupleExpression) args).getExpressions().add(0, this0);
}
}
}
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 3e56772..c280d6f 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -18,7 +18,6 @@
*/
package gls.innerClass
-import groovy.test.NotYetImplemented
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import org.codehaus.groovy.control.CompilationFailedException
@@ -273,13 +272,38 @@ final class InnerClassTest {
'''
}
- @Test @NotYetImplemented
- void testNonStaticInnerClass2() {
- shouldFail CompilationFailedException, '''
+ @Test // GROOVY-8104
+ void testNonStaticInnerClass5() {
+ assertScript '''
class A {
- class B {}
+ void foo() {
+ C c = new C()
+ ['1','2','3'].each { obj ->
+ c.baz(obj, new I() {
+ @Override
+ void bar(Object o) {
+ B b = new B() // Could not find matching constructor for: A$B(A$_foo_closure1)
+ }
+ })
+ }
+ }
+
+ class B {
+ }
+ }
+
+ class C {
+ void baz(Object o, I i) {
+ i.bar(o)
+ }
}
- def x = new A.B() // requires reference to A
+
+ interface I {
+ void bar(Object o)
+ }
+
+ A a = new A()
+ a.foo()
'''
}