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 2016/08/28 05:22:02 UTC

groovy git commit: GROOVY-7916: MissingPropertyException when accessing a static inner class member from a sub class (closes #397)

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_4_X e37394599 -> 895684334


GROOVY-7916: MissingPropertyException when accessing a static inner class member from a sub class (closes #397)


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

Branch: refs/heads/GROOVY_2_4_X
Commit: 895684334d0b8766d116bda83f347850f5b66c91
Parents: e373945
Author: paulk <pa...@asert.com.au>
Authored: Fri Aug 26 12:25:56 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Aug 28 15:20:59 2016 +1000

----------------------------------------------------------------------
 .../codehaus/groovy/control/ResolveVisitor.java | 30 ++++++++--
 src/test/groovy/bugs/Groovy7916Bug.groovy       | 60 ++++++++++++++++++++
 2 files changed, 84 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/89568433/src/main/org/codehaus/groovy/control/ResolveVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/org/codehaus/groovy/control/ResolveVisitor.java
index 370da8e..7e426aa 100644
--- a/src/main/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/org/codehaus/groovy/control/ResolveVisitor.java
@@ -837,13 +837,19 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
             }
         }
         if (objectExpression instanceof ClassExpression && pe.getPropertyAsString() != null) {
-            // possibly an inner class
+            // possibly an inner class (or inherited inner class)
             ClassExpression ce = (ClassExpression) objectExpression;
-            ClassNode type = new ConstructedNestedClass(ce.getType(), pe.getPropertyAsString());
-            if (resolve(type, false, false, false)) {
-                Expression ret = new ClassExpression(type);
-                ret.setSourcePosition(ce);
-                return ret;
+            ClassNode classNode = ce.getType();
+            while (classNode != null) {
+                ClassNode type = new ConstructedNestedClass(classNode, pe.getPropertyAsString());
+                if (resolve(type, false, false, false)) {
+                    if (classNode == ce.getType() || isVisibleNestedClass(type, ce.getType())) {
+                        Expression ret = new ClassExpression(type);
+                        ret.setSourcePosition(ce);
+                        return ret;
+                    }
+                }
+                classNode = classNode.getSuperClass();
             }
         }
         Expression ret = pe;
@@ -852,6 +858,18 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
         return ret;
     }
 
+    private boolean isVisibleNestedClass(ClassNode type, ClassNode ceType) {
+        if (!type.isRedirectNode()) return false;
+        ClassNode redirect = type.redirect();
+        if (Modifier.isPublic(redirect.getModifiers()) || Modifier.isProtected(redirect.getModifiers())) return true;
+        // package local
+        PackageNode classPackage = ceType.getPackage();
+        PackageNode nestedPackage = redirect.getPackage();
+        return (redirect.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC | Modifier.PRIVATE)) == 0 &&
+                ((classPackage == null && nestedPackage == null) ||
+                        classPackage != null && nestedPackage != null && classPackage.getName().equals(nestedPackage.getName()));
+    }
+
     private boolean directlyImplementsTrait(ClassNode trait) {
         ClassNode[] interfaces = currentClass.getInterfaces();
         if (interfaces==null) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/89568433/src/test/groovy/bugs/Groovy7916Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7916Bug.groovy b/src/test/groovy/bugs/Groovy7916Bug.groovy
new file mode 100644
index 0000000..4a7ebcf
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7916Bug.groovy
@@ -0,0 +1,60 @@
+/*
+ *  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 Groovy7916Bug extends GroovyTestCase {
+    void testShouldBeAbleToOverrideStaticConstantProperties() {
+        assertScript '''
+            import groovy.transform.PackageScope
+            import static groovy.test.GroovyAssert.shouldFail
+
+            class Base {
+                static class Inner1 {
+                    static final String CONST = 'Hello1'
+                }
+
+                protected static class Inner2 {
+                    static final String CONST = 'Hello2'
+                }
+
+                @PackageScope static class Inner3 {
+                    static final String CONST = 'Hello3'
+                }
+
+                private static class Inner4 {
+                    static final String CONST = 'Hello4'
+                }
+            }
+
+            class Derived extends Base { }
+
+            assert Base.Inner1.CONST == 'Hello1'
+            assert Base.Inner2.CONST == 'Hello2'
+            assert Base.Inner3.CONST == 'Hello3'
+            assert Base.Inner4.CONST == 'Hello4'
+
+            assert Derived.Inner1.CONST == 'Hello1'
+            assert Derived.Inner2.CONST == 'Hello2'
+            assert Derived.Inner3.CONST == 'Hello3'
+            shouldFail(MissingPropertyException) {
+                assert Derived.Inner4.CONST == 'Hello4'
+            }
+        '''
+    }
+}