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/08/19 20:52:30 UTC

[groovy] 01/01: GROOVY-10200: do not retain static for outer member checking of variable

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

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

commit f59509af7dd754e7c7fd92cd25a9124a5816902a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 19 15:45:38 2021 -0500

    GROOVY-10200: do not retain static for outer member checking of variable
---
 .../groovy/classgen/VariableScopeVisitor.java      |  12 +-
 src/test/groovy/lang/MixinAnnotationTest.groovy    | 152 ++++++++++++---------
 .../stc/FieldsAndPropertiesSTCTest.groovy          |   2 +-
 3 files changed, 92 insertions(+), 74 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 7067b78..70fb8ad 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -238,19 +238,19 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
             ClassNode node = scope.getClassScope();
             if (node != null) {
                 Variable member = findClassMember(node, name);
+                boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
                 while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
-                    crossingStaticContext = (crossingStaticContext || isStatic(node.getModifiers()));
+                    requireStatic = requireStatic || isStatic(node.getModifiers());
                     member = findClassMember((node = node.getOuterClass()), name);
                 }
                 if (member != null) {
-                    boolean staticScope = (crossingStaticContext || inSpecialConstructorCall), staticMember = member.isInStaticContext();
-                    // prevent a static context (e.g. a static method) from accessing a non-static variable (e.g. a non-static field)
-                    if (!(staticScope ? !staticMember : node.isScript())) {
+                    // prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
+                    if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
                         variable = member;
                     }
                 }
-                // GROOVY-5961
-                if (!isAnonymous(scope.getClassScope())) break;
+
+                if (!isAnonymous(scope.getClassScope())) break; // GROOVY-5961
             }
             scope = scope.getParent();
         }
diff --git a/src/test/groovy/lang/MixinAnnotationTest.groovy b/src/test/groovy/lang/MixinAnnotationTest.groovy
index 6aa66ef..49df14f 100644
--- a/src/test/groovy/lang/MixinAnnotationTest.groovy
+++ b/src/test/groovy/lang/MixinAnnotationTest.groovy
@@ -18,81 +18,99 @@
  */
 package groovy.lang
 
-import groovy.test.GroovyShellTestCase
 import org.codehaus.groovy.reflection.ReflectionCache
-
-class MixinAnnotationTest extends GroovyShellTestCase {
-
-    void testSingleMixinAnnotation () {
-        evaluate """
-
-interface Mixed {
-  def getA ()
-}
-
-@Category(Mixed)
-class CategoryToUse {
-    static def msg = "under category: "
-
-    def asText () {
-        msg + this + ": " + a
-    }
-}
-
-@Mixin(CategoryToUse)
-class ClassToExtend implements Mixed{
-    String toString () {
-        "object of ClassToExtend"
-    }
-
-    def a = "blah"
-}
-
-        groovy.test.GroovyTestCase.assertEquals("under category: object of ClassToExtend: blah", new ClassToExtend().asText ())
-
-        boolean failed = false;
-        try {
-            new Object().asText ()
-        }
-        catch (MissingMethodException e) {
-          failed = true;
-        }
-        assert failed
-
-        """
+import org.junit.After
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class MixinAnnotationTest {
+
+    @Test
+    void testSingleMixinAnnotation() {
+        assertScript '''
+            interface Mixed {
+                def getA()
+            }
+
+            @Category(Mixed)
+            class CategoryToUse {
+                private static String msg = 'under category: '
+                String asText() {
+                    msg + this + ': ' + a
+                }
+            }
+
+            @Mixin(CategoryToUse)
+            class ClassToExtend implements Mixed {
+                String toString() {
+                    'object of ClassToExtend'
+                }
+                def a = 'blah'
+            }
+
+            def result = new ClassToExtend().asText()
+            assert result == 'under category: object of ClassToExtend: blah'
+            groovy.test.GroovyAssert.shouldFail(MissingMethodException) {
+                new Object().asText()
+            }
+        '''
     }
 
+    @Test
     void testMultipleMixinAnnotation () {
-        evaluate """
-@Category(Object)
-class CategoryToUse1 {
-    def asText () {
-        "under category: " + asBiggerText ()
+        assertScript '''
+            @Category(Object)
+            class CategoryToUse1 {
+                def asText() {
+                    'under category: ' + asBiggerText()
+                }
+            }
+
+            @Category(Object)
+            class CategoryToUse2 {
+                def asBiggerText() {
+                    'under BIG category: ' + this
+                }
+            }
+
+            @Mixin([CategoryToUse1, CategoryToUse2])
+            class ClassToExtend {
+                String toString() {
+                    'object of ClassToExtend'
+                }
+            }
+
+            def result = new ClassToExtend().asText()
+            assert result == 'under category: under BIG category: object of ClassToExtend'
+        '''
     }
-}
-
-@Category(Object)
-class CategoryToUse2 {
-    def asBiggerText () {
-        "under BIG category: " + this
-    }
-}
-
-@Mixin([CategoryToUse1, CategoryToUse2])
-class ClassToExtend {
-    String toString () {
-        "object of ClassToExtend"
-    }
-}
 
-        groovy.test.GroovyTestCase.assertEquals("under category: under BIG category: object of ClassToExtend", new ClassToExtend().asText ())
-        """
+    @Test // GROOVY-10200
+    void testStaticInnerMixinAnnotation() {
+        assertScript '''
+            class A {
+                def getB() {
+                    'works'
+                }
+            }
+            class C {
+                @Mixin(A)
+                static class D {
+                    def test() {
+                        return b
+                    }
+                }
+            }
+            def result = new C.D().test()
+            assert result == 'works'
+        '''
     }
 
-    protected void tearDown() {
-        super.tearDown()
-        ReflectionCache.getCachedClass(ArrayList).setNewMopMethods (null)
-        ReflectionCache.getCachedClass(List).setNewMopMethods (null)
+    @After
+    void tearDown() {
+        ReflectionCache.getCachedClass(ArrayList).setNewMopMethods(null)
+        ReflectionCache.getCachedClass(List).setNewMopMethods(null)
     }
 
 //    void testOneClass () {
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index be5b8c2..bddafa0 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -562,7 +562,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
             }
             def i = new Outer.Inner()
             def x = i.m()
-        ''', "Apparent variable 'p' was found in a static scope but doesn't refer to a local variable, static field or class."
+        ''', 'The variable [p] is undeclared.'
     }
 
     void testOuterPropertyAccess3() {