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:35 UTC

[groovy] branch GROOVY_3_0_X updated (f745b82 -> ffb6856)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from f745b82  GROOVY-9974: extract generics connections: Closure<T> vs SAM return type
     new ed35751  GROOVY-5728: anon. inner can use private constructor when super is outer
     new ffb6856  GROOVY-8104: fix this$0 for closure with anon. inner class of inner type

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../classgen/InnerClassCompletionVisitor.java      | 31 +++++++++++++++++--
 .../groovy/classgen/InnerClassVisitor.java         | 29 +++++++++++------
 src/test/gls/innerClass/InnerClassTest.groovy      | 36 ++++++++++++++++++----
 .../stc/AnonymousInnerClassSTCTest.groovy          | 17 ++++++++++
 4 files changed, 96 insertions(+), 17 deletions(-)

[groovy] 01/02: GROOVY-5728: anon. inner can use private constructor when super is outer

Posted by em...@apache.org.
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 ed3575178050b467c5cdfecf2314a0a030df44f7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Mar 20 10:51:07 2021 -0500

    GROOVY-5728: anon. inner can use private constructor when super is outer
---
 .../classgen/InnerClassCompletionVisitor.java      | 31 ++++++++++++++++++++--
 .../stc/AnonymousInnerClassSTCTest.groovy          | 17 ++++++++++++
 2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
index 37336f0..eb4103e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java
@@ -46,8 +46,11 @@ import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorSuperX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorThisX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
@@ -73,7 +76,7 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper impleme
     }
 
     @Override
-    public void visitClass(ClassNode node) {
+    public void visitClass(final ClassNode node) {
         classNode = node;
         thisField = null;
         InnerClassNode innerClass = null;
@@ -94,9 +97,33 @@ public class InnerClassCompletionVisitor extends InnerClassVisitorHelper impleme
     }
 
     @Override
-    public void visitConstructor(ConstructorNode node) {
+    public void visitConstructor(final ConstructorNode node) {
         addThisReference(node);
         super.visitConstructor(node);
+        // an anonymous inner class may use a private constructor (via a bridge) if its super class is also an outer class
+        if (((InnerClassNode) classNode).isAnonymous() && classNode.getOuterClasses().contains(classNode.getSuperClass())) {
+            ConstructorNode superCtor = classNode.getSuperClass().getDeclaredConstructor(node.getParameters());
+            if (superCtor != null && superCtor.isPrivate()) {
+                ClassNode superClass = classNode.getUnresolvedSuperClass();
+                makeBridgeConstructor(superClass, node.getParameters()); // GROOVY-5728
+                ConstructorCallExpression superCtorCall = getFirstIfSpecialConstructorCall(node.getCode());
+                ((TupleExpression) superCtorCall.getArguments()).addExpression(castX(superClass, nullX()));
+            }
+        }
+    }
+
+    private static void makeBridgeConstructor(final ClassNode c, final Parameter[] p) {
+        Parameter[] newP = new Parameter[p.length + 1];
+        for (int i = 0; i < p.length; i += 1) {
+            newP[i] = new Parameter(p[i].getType(), "p" + i);
+        }
+        newP[p.length] = new Parameter(c, "$anonymous");
+
+        if (c.getDeclaredConstructor(newP) == null) {
+            TupleExpression args = new TupleExpression();
+            for (int i = 0; i < p.length; i += 1) args.addExpression(varX(newP[i]));
+            addGeneratedConstructor(c, ACC_SYNTHETIC, newP, ClassNode.EMPTY_ARRAY, stmt(ctorThisX(args)));
+        }
     }
 
     private static String getTypeDescriptor(ClassNode node, boolean isStatic) {
diff --git a/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy b/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
index 1fb7aac..822a712 100644
--- a/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
+++ b/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
@@ -207,4 +207,21 @@ class AnonymousInnerClassSTCTest extends StaticTypeCheckingTestCase {
             }
         '''
     }
+
+    // GROOVY-5728
+    void testPrivateConstructorAndPublicStaticFactory() {
+        assertScript '''
+            abstract class A {
+                private A() { }
+                abstract answer()
+                static A create() {
+                    return new A() { // IllegalAccessError when A$1 calls private constructor
+                        def answer() { 42 }
+                    }
+                }
+            }
+
+            assert A.create().answer() == 42
+        '''
+    }
 }

[groovy] 02/02: GROOVY-8104: fix this$0 for closure with anon. inner class of inner type

Posted by em...@apache.org.
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()
         '''
     }