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()
         '''
     }