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 2020/05/23 16:52:29 UTC

[groovy] branch GROOVY-9569 updated: GROOVY-5259: refactor handling of "this" reference in special ctor call

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

emilles pushed a commit to branch GROOVY-9569
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY-9569 by this push:
     new afb9a3e  GROOVY-5259: refactor handling of "this" reference in special ctor call
afb9a3e is described below

commit afb9a3e7deea247c604575fd450be0c3db4df536
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat May 23 11:34:20 2020 -0500

    GROOVY-5259: refactor handling of "this" reference in special ctor call
---
 .../groovy/classgen/AsmClassGenerator.java         | 64 ++++++++++------------
 src/test/gls/innerClass/InnerClassTest.groovy      | 28 +++++-----
 2 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 0f23e08..15fe90d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1078,7 +1078,7 @@ public class AsmClassGenerator extends ClassGenerator {
                 } else {
                     field = classNode.getDeclaredField(name);
                     if (field == null && !isValidFieldNodeForByteCodeAccess(classNode.getField(name), classNode)) {
-                        // GROOVY-5259, GROOVY-9501, GROOVY-9569
+                        // GROOVY-9501, GROOVY-9569
                         if (checkStaticOuterField(expression, name)) return;
                     }
                 }
@@ -1275,28 +1275,29 @@ public class AsmClassGenerator extends ClassGenerator {
 
     @Override
     public void visitVariableExpression(final VariableExpression expression) {
-        String variableName = expression.getName();
-
-        //-----------------------------------------------------------------------
-        // SPECIAL CASES
-
-        // "this" for static methods is the Class instance
-        ClassNode classNode = controller.getClassNode();
+        final String variableName = expression.getName();
 
         if (expression.isThisExpression()) {
-            if (controller.isStaticMethod() || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
-                if (controller.isInGeneratedFunction()) classNode = controller.getOutermostClass();
-                visitClassExpression(new ClassExpression(classNode));
+            // "this" in static context is Class instance
+            if (controller.isStaticMethod() || controller.getCompileStack().isInSpecialConstructorCall()
+                    || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
+                ClassNode thisType = controller.getClassNode();
+                if (controller.isInGeneratedFunction()) {
+                    do { thisType = thisType.getOuterClass();
+                    } while (ClassHelper.isGeneratedFunction(thisType));
+                }
+                classX(thisType).visit(this);
             } else {
                 loadThis(expression);
             }
             return;
         }
 
-        // "super" also requires special handling
         if (expression.isSuperExpression()) {
+            // "super" in static context is Class instance
             if (controller.isStaticMethod()) {
-                visitClassExpression(new ClassExpression(classNode.getSuperClass()));
+                ClassNode superType = controller.getClassNode().getSuperClass();
+                classX(superType).visit(this);
             } else {
                 loadThis(expression);
             }
@@ -1304,11 +1305,22 @@ public class AsmClassGenerator extends ClassGenerator {
         }
 
         BytecodeVariable variable = controller.getCompileStack().getVariable(variableName, false);
-        if (variable == null) {
-            processClassVariable(expression);
-        } else {
+        if (variable != null) {
             controller.getOperandStack().loadOrStoreVariable(variable, expression.isUseReferenceDirectly());
+        } else if (passingParams && controller.isInScriptBody()) {
+            MethodVisitor mv = controller.getMethodVisitor();
+            mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/ScriptReference");
+            mv.visitInsn(DUP);
+            loadThisOrOwner();
+            mv.visitLdcInsn(variableName);
+            mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/ScriptReference", "<init>", "(Lgroovy/lang/Script;Ljava/lang/String;)V", false);
+        } else {
+            PropertyExpression pexp = thisPropX(true, variableName);
+            pexp.getObjectExpression().setSourcePosition(expression);
+            pexp.getProperty().setSourcePosition(expression);
+            pexp.visit(this);
         }
+
         if (!controller.getCompileStack().isLHS()) {
             controller.getAssertionWriter().record(expression);
         }
@@ -1331,26 +1343,6 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    private void processClassVariable(final VariableExpression expression) {
-        if (passingParams && controller.isInScriptBody()) {
-            // TODO: check if this part is actually used
-            MethodVisitor mv = controller.getMethodVisitor();
-            // create a ScriptReference to pass into the closure
-            mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/ScriptReference");
-            mv.visitInsn(DUP);
-
-            loadThisOrOwner();
-            mv.visitLdcInsn(expression.getName());
-
-            mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/ScriptReference", "<init>", "(Lgroovy/lang/Script;Ljava/lang/String;)V", false);
-        } else {
-            PropertyExpression pexp = thisPropX(true, expression.getName());
-            pexp.getObjectExpression().setSourcePosition(expression);
-            pexp.getProperty().setSourcePosition(expression);
-            visitPropertyExpression(pexp);
-        }
-    }
-
     protected void createInterfaceSyntheticStaticFields() {
         ClassNode icl =  controller.getInterfaceClassLoadingClass();
 
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 9b5fa33..44b5ad2 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -594,31 +594,33 @@ final class InnerClassTest {
         '''
     }
 
-    /*@Test
+    @Test
     void testUsageOfOuterField_WrongCallToSuper() {
         shouldFail '''
-            class InnerAccessOuter {
+            class Outer {
                 protected static final String OUTER_CONSTANT = 'Constant Value'
 
-                class InnerClass {
-                    InnerClass() {
-                        // there's no Object#<init>(String) method, but it throws a VerifyError when a new instance
-                        // is created, meaning a wrong super call is generated
+                class Inner {
+                    Inner() {
+                        // there is no Object#<init>(String) method, but it throws a VerifyError for uninitialized this
                         super(OUTER_CONSTANT)
                     }
-                    String m() {
-                         OUTER_CONSTANT
+
+                    String access() {
+                        return OUTER_CONSTANT
                     }
                 }
 
-                void testInnerClassAccessOuter() {
-                    def inner = new InnerClass()
-                    inner.m()
+                void testInnerClassAccessOuterConst() {
+                    def inner = new Inner()
+                    inner.access()
                 }
             }
-            new InnerAccessOuter().testInnerClassAccessOuter()
+
+            def outer = new Outer()
+            outer.testInnerClassAccessOuterConst()
         '''
-    }*/
+    }
 
     @Test
     void testUsageOfOuterFieldOverridden() {