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/12/04 18:52:40 UTC

[groovy] 01/01: GROOVY-7549, GROOVY-9847: getOuterClass, getOuterClasses, getOuterField must check redirect

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

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

commit 45aeca7dc82accf1139d0fad18c3687b5ce86c82
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Dec 4 12:52:21 2020 -0600

    GROOVY-7549, GROOVY-9847: getOuterClass, getOuterClasses, getOuterField
    must check redirect
---
 .../java/org/codehaus/groovy/ast/ClassNode.java    | 27 +++++++++---------
 .../transform/stc/TypeInferenceSTCTest.groovy      | 33 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index 4840633..2e0dc08 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -772,32 +772,31 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
     }
 
     /**
-     * @return the field node on the outer class or null if this is not an
-     *         inner class
+     * @return outer class field or {@code null} if not found or this is not an inner class
      */
-    public FieldNode getOuterField(String name) {
+    public FieldNode getOuterField(final String name) {
+        if (redirect != null) {
+            return redirect.getOuterField(name);
+        }
         return null;
     }
 
-    /**
-     * Helper method to avoid casting to inner class
-     */
     public ClassNode getOuterClass() {
+        if (redirect != null) {
+            return redirect.getOuterClass();
+        }
         return null;
     }
 
     public List<ClassNode> getOuterClasses() {
-        if (!(this instanceof InnerClassNode)) {
+        ClassNode outer = getOuterClass();
+        if (outer == null) {
             return Collections.emptyList();
         }
-
-        List<ClassNode> result = new LinkedList<>();
-        ClassNode outestClass = ((InnerClassNode) this).getOuterMostClass();
-        ClassNode cn = this;
-
+        List<ClassNode> result = new ArrayList<>();
         do {
-            result.add(cn = cn.getOuterClass());
-        } while (!cn.equals(outestClass));
+            result.add(outer);
+        } while ((outer = outer.getOuterClass()) != null);
 
         return result;
     }
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index e81e5d5..2ae9b95 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -864,6 +864,39 @@ Thing.run()
         }
     }
 
+    // GROOVY-9847
+    void testShouldKeepInferredTypeWhenPrivateInnerClass() {
+        assertScript '''
+            class Test {
+                @groovy.transform.ToString(excludes='children')
+                private static class TreeAttr {
+                    String name
+                    Integer val = 0
+                    List<TreeAttr> children = []
+                }
+
+                static main(args) {
+                    new Test().test(1)
+                }
+
+                void test(Integer count) {
+                    TreeAttr root = new TreeAttr(name:'foo')
+                    List<TreeAttr> collector = root.children
+
+                    for (name in ['bar','baz']) { // tokens in a path
+                        def item = collector.find { it.name == name }
+                        if (!item) {
+                            item = new TreeAttr(name: name)
+                            collector.add(item)
+                        }
+                        collector = item.children
+                        if (count) item.val += count
+                    }
+                }
+            }
+        '''
+    }
+
     // GROOVY-9077
     void testInferredTypeForPropertyThatResolvesToMethod() {
         assertScript '''