You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2018/10/09 05:00:14 UTC

groovy git commit: GROOVY-8764: Closure inside an anonymous class uses wrong outside class instance with @CS

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_5_X 484adf6fc -> eee7844bb


GROOVY-8764: Closure inside an anonymous class uses wrong outside class instance with @CS


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/eee7844b
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/eee7844b
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/eee7844b

Branch: refs/heads/GROOVY_2_5_X
Commit: eee7844bb8ecf0f2b66d58cea328c5b9aadde75c
Parents: 484adf6
Author: Paul King <pa...@asert.com.au>
Authored: Tue Oct 9 16:00:05 2018 +1100
Committer: Paul King <pa...@asert.com.au>
Committed: Tue Oct 9 16:00:05 2018 +1100

----------------------------------------------------------------------
 .../groovy/classgen/asm/ClosureWriter.java      |  4 +-
 .../classgen/asm/sc/StaticInvocationWriter.java | 22 +++++++++-
 src/test/groovy/bugs/Groovy8764Bug.groovy       | 44 ++++++++++++++++++++
 3 files changed, 67 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/eee7844b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
index 60fe447..6c896c0 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -253,10 +253,10 @@ public class ClosureWriter {
         BlockStatement block = new BlockStatement();
         // this block does not get a source position, because we don't
         // want this synthetic constructor to show up in corbertura reports
-        VariableExpression outer = new VariableExpression("_outerInstance");
+        VariableExpression outer = new VariableExpression("_outerInstance", outerClass);
         outer.setSourcePosition(expression);
         block.getVariableScope().putReferencedLocalVariable(outer);
-        VariableExpression thisObject = new VariableExpression("_thisObject");
+        VariableExpression thisObject = new VariableExpression("_thisObject", classNode);
         thisObject.setSourcePosition(expression);
         block.getVariableScope().putReferencedLocalVariable(thisObject);
         TupleExpression conArgs = new TupleExpression(outer, thisObject);

http://git-wip-us.apache.org/repos/asf/groovy/blob/eee7844b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index d7f4884..d480578 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -283,7 +283,27 @@ public class StaticInvocationWriter extends InvocationWriter {
                 // it's a static extension method
                 argumentList.add(0, ConstantExpression.NULL);
             } else {
-                argumentList.add(0, receiver);
+                ClassNode classNode = controller.getClassNode();
+                boolean isThisOrSuper = false;
+                if (receiver instanceof VariableExpression) {
+                    isThisOrSuper = ((VariableExpression) receiver).isThisExpression() || ((VariableExpression) receiver).isSuperExpression();
+                }
+                Expression fixedReceiver = null;
+                if (isThisOrSuper && classNode instanceof InnerClassNode && controller.isInClosure()) {
+                    ClassNode current = classNode.getOuterClass();
+                    fixedReceiver = new VariableExpression("thisObject", current);
+                    // adjust for multiple levels of nesting if needed
+                    while (current instanceof InnerClassNode && !classNode.equals(current)) {
+                        FieldNode thisField = current.getField("this$0");
+                        current = current.getOuterClass();
+                        if (thisField != null) {
+                            fixedReceiver = new PropertyExpression(fixedReceiver, "this$0");
+                            fixedReceiver.setType(current);
+                        }
+                    }
+                }
+
+                argumentList.add(0, fixedReceiver != null ? fixedReceiver : receiver);
             }
 
             Parameter[] parameters = node.getParameters();

http://git-wip-us.apache.org/repos/asf/groovy/blob/eee7844b/src/test/groovy/bugs/Groovy8764Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy8764Bug.groovy b/src/test/groovy/bugs/Groovy8764Bug.groovy
new file mode 100644
index 0000000..7248667
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8764Bug.groovy
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+class Groovy8764Bug extends GroovyTestCase {
+    void testDgmMethodInClosureInInnerClass() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileStatic
+            class GroovyTest {
+                public boolean hasMeta = false
+                void test() {
+                    new Runnable() {
+                        void run() {
+                            def c = { hasMeta = hasProperty('metaClass') /* implicit this for hasProperty DGM method */ }
+                            c()
+                        }
+                    }.run()
+                }
+            }
+
+            def gt = new GroovyTest()
+            gt.test()
+            assert gt.hasMeta
+        '''
+    }
+}