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/02/22 20:31:18 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-7996: correct metadata for accessed variable and property owner

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

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


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new a001a0c  GROOVY-7996: correct metadata for accessed variable and property owner
a001a0c is described below

commit a001a0c3e9067eb4f4cd4bae2ebeb7130ad5adc3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Feb 22 12:32:16 2021 -0600

    GROOVY-7996: correct metadata for accessed variable and property owner
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 12 ++++---
 src/test/groovy/bugs/Groovy7996.groovy             | 41 +++++++++++++++++++++-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 819d9ff..4b97e96 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -264,6 +264,7 @@ import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCh
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.typeCheckMethodsWithGenerics;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DECLARATION_INFERRED_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DYNAMIC_RESOLUTION;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.IMPLICIT_RECEIVER;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PV_FIELDS_ACCESS;
@@ -721,8 +722,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             storeType(vexp, type != null ? type: pexp.getType());
 
             String receiver = vexp.getNodeMetaData(IMPLICIT_RECEIVER);
-            // GROOVY-7701: correct false assumption made by VariableScopeVisitor
-            if (receiver != null && !receiver.endsWith("owner") && !(vexp.getAccessedVariable() instanceof DynamicVariable)) {
+            Boolean dynamic = pexp.getNodeMetaData(DYNAMIC_RESOLUTION);
+            // GROOVY-7701, GROOVY-7996: correct false assumption made by VariableScopeVisitor
+            if (((receiver != null && !receiver.endsWith("owner")) || Boolean.TRUE.equals(dynamic))
+                    && !(vexp.getAccessedVariable() instanceof DynamicVariable)) {
                 vexp.setAccessedVariable(new DynamicVariable(dynName, false));
             }
             return true;
@@ -1602,9 +1605,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (mopMethod == null) mopMethod = receiverType.getMethod("propertyMissing", new Parameter[]{new Parameter(STRING_TYPE, "propertyName")});
 
                 if (mopMethod != null && !mopMethod.isStatic() && !mopMethod.isSynthetic()) {
-                    pexp.putNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION, Boolean.TRUE);
+                    pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
                     pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
                     pexp.removeNodeMetaData(INFERRED_TYPE);
+                    visitor.visitMethod(mopMethod);
                     return true;
                 }
             }
@@ -3398,7 +3402,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     mn = disambiguateMethods(mn, chosenReceiver != null ? chosenReceiver.getType() : null, args, call);
                     if (mn.size() == 1) {
                         MethodNode directMethodCallCandidate = mn.get(0);
-                        if (call.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION) == null &&
+                        if (call.getNodeMetaData(DYNAMIC_RESOLUTION) == null &&
                                 !directMethodCallCandidate.isStatic() && objectExpression instanceof ClassExpression &&
                                 !"java.lang.Class".equals(directMethodCallCandidate.getDeclaringClass().getName())) {
                             ClassNode owner = directMethodCallCandidate.getDeclaringClass();
diff --git a/src/test/groovy/bugs/Groovy7996.groovy b/src/test/groovy/bugs/Groovy7996.groovy
index 39de261..3c2d443 100644
--- a/src/test/groovy/bugs/Groovy7996.groovy
+++ b/src/test/groovy/bugs/Groovy7996.groovy
@@ -171,7 +171,7 @@ final class Groovy7996 {
     }
 
     @Test // GROOVY-8073
-    void testDelegatePropertyAccessFromClosure() {
+    void testDelegatePropertyAccessFromClosure1() {
         assertScript '''
             @groovy.transform.CompileStatic
             class Main {
@@ -184,4 +184,43 @@ final class Groovy7996 {
             }
         '''
     }
+
+    @Test
+    void testDelegatePropertyAccessFromClosure2() {
+        assertScript '''
+            import groovy.transform.*
+            import org.codehaus.groovy.ast.DynamicVariable
+            import org.codehaus.groovy.ast.expr.VariableExpression
+            import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE
+            import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE
+            import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PROPERTY_OWNER
+
+            class JSON {
+                def get(String name) {
+                    new JSON()
+                }
+            }
+
+            class POGO {
+                Number getAnswer() {
+                    42
+                }
+                @CompileStatic
+                void usage() {
+                    new JSON().with {
+                        @ASTTest(phase=CLASS_GENERATION, value={
+                            def vexp = node.rightExpression
+                            assert vexp instanceof VariableExpression
+                            assert vexp.accessedVariable instanceof DynamicVariable
+                            assert vexp.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
+                            assert vexp.getNodeMetaData(PROPERTY_OWNER).name == 'JSON'
+                        })
+                        def result = answer // "answer" accessed from JSON; "getAnswer()" invoked from POGO
+                    }
+                }
+            }
+
+            new POGO().usage()
+        '''
+    }
 }