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

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


The following commit(s) were added to refs/heads/master by this push:
     new 84b03c4  GROOVY-10102: trait SelfType: continue checking self type for 
self types
84b03c4 is described below

commit 84b03c439fc4d5fa73f89210882b62a131588263
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Wed May 26 09:48:31 2021 -0500

    GROOVY-10102: trait SelfType: continue checking self type for self types
---
 .../codehaus/groovy/transform/trait/Traits.java    | 46 ++++++++---------
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 57 +++++++++++++++++-----
 2 files changed, 69 insertions(+), 34 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java 
b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
index 2dfb5e1..8edeb25 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
@@ -300,13 +300,12 @@ public abstract class Traits {
      * Collects all the self types that a type should extend or implement, 
given
      * the traits is implements. Collects from interfaces and superclasses too.
      * @param receiver a class node that may implement a trait
-     * @param selfTypes a collection where the list of self types will be 
written
-     * @return the selfTypes collection itself
+     * @param selfTypes a set where the self types will be put
+     * @return the {@code selfTypes} collection
+     *
      * @since 2.4.0
      */
-    public static LinkedHashSet<ClassNode> collectSelfTypes(
-            ClassNode receiver,
-            LinkedHashSet<ClassNode> selfTypes) {
+    public static LinkedHashSet<ClassNode> collectSelfTypes(final ClassNode 
receiver, final LinkedHashSet<ClassNode> selfTypes) {
         return collectSelfTypes(receiver, selfTypes, true, true);
     }
 
@@ -314,28 +313,30 @@ public abstract class Traits {
      * Collects all the self types that a type should extend or implement, 
given
      * the traits is implements.
      * @param receiver a class node that may implement a trait
-     * @param selfTypes a collection where the list of self types will be 
written
+     * @param selfTypes a set where the self types will be put
      * @param checkInterfaces should the interfaces that the node implements 
be collected too
-     * @param checkSuper should we collect from the superclass too
-     * @return the selfTypes collection itself
+     * @param checkSuperClass should we collect from the superclass too
+     * @return the {@code selfTypes} collection
+     *
      * @since 2.4.0
      */
-    public static LinkedHashSet<ClassNode> collectSelfTypes(
-            ClassNode receiver,
-            LinkedHashSet<ClassNode> selfTypes,
-            boolean checkInterfaces,
-            boolean checkSuper) {
+    public static LinkedHashSet<ClassNode> collectSelfTypes(final ClassNode 
receiver, final LinkedHashSet<ClassNode> selfTypes, final boolean 
checkInterfaces, final boolean checkSuperClass) {
         if (Traits.isTrait(receiver)) {
             List<AnnotationNode> annotations = 
receiver.getAnnotations(SELFTYPE_CLASSNODE);
             for (AnnotationNode annotation : annotations) {
                 Expression value = annotation.getMember("value");
                 if (value instanceof ClassExpression) {
-                    selfTypes.add(value.getType());
+                    ClassNode selfType = value.getType();
+                    if (selfTypes.add(selfType)) {
+                        collectSelfTypes(selfType, selfTypes, checkInterfaces, 
checkSuperClass);
+                    }
                 } else if (value instanceof ListExpression) {
-                    List<Expression> expressions = ((ListExpression) 
value).getExpressions();
-                    for (Expression expression : expressions) {
+                    for (Expression expression : ((ListExpression) 
value).getExpressions()) {
                         if (expression instanceof ClassExpression) {
-                            selfTypes.add(expression.getType());
+                            ClassNode selfType = expression.getType();
+                            if (selfTypes.add(selfType)) {
+                                collectSelfTypes(selfType, selfTypes, 
checkInterfaces, checkSuperClass);
+                            }
                         }
                     }
                 }
@@ -343,14 +344,15 @@ public abstract class Traits {
         }
         if (checkInterfaces) {
             ClassNode[] interfaces = receiver.getInterfaces();
-            for (ClassNode anInterface : interfaces) {
-                collectSelfTypes(anInterface, selfTypes, true, checkSuper);
+            for (ClassNode interFace : interfaces) {
+                if (!selfTypes.contains(interFace)) {
+                    collectSelfTypes(interFace, selfTypes, true, 
checkSuperClass);
+                }
             }
         }
-
-        if (checkSuper) {
+        if (checkSuperClass) {
             ClassNode superClass = receiver.getSuperClass();
-            if (superClass != null) {
+            if (superClass != null && !ClassHelper.isObjectType(superClass)) {
                 collectSelfTypes(superClass, selfTypes, checkInterfaces, true);
             }
         }
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy 
b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index d9ad1c9..0781a77 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -103,6 +103,39 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot find matching method <UnionType:C+T>#x'
     }
 
+    // GROOVY-10102
+    void 
testShouldDetectValidMethodUseWithinTraitWithCompileStaticAndSelfType() {
+        assertScript '''
+            import groovy.transform.*
+
+            trait A {
+                String foo = 'foo'
+                String m(String s, Closure x) {
+                    s + x()
+                }
+            }
+            @SelfType(A)
+            trait B {
+            }
+            @SelfType(B)
+            trait C {
+            }
+            @CompileStatic
+            @SelfType(C)
+            trait D {
+                def test() {
+                    String s = foo
+                    m(s) {
+                        s.toUpperCase()
+                    }
+                }
+            }
+
+            class E implements A, B, C, D { }
+            assert new E().test() == 'fooFOO'
+        '''
+    }
+
     // GROOVY-10106
     void testCallStaticOrPrivateMethodInTraitFieldInitializer() {
         ['private', 'static', 'private static'].each { mods ->
@@ -139,19 +172,19 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
 
     void testGroovy5444() {
         assertScript '''
-                def curr = { System.currentTimeMillis() }
-
-                5.times {
-                    @ASTTest(phase=INSTRUCTION_SELECTION, value= {
-                        assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE
-                    })
-                    def t0 = curr()
-                    100000.times {
-                        "echo"
-                    }
-                    println (curr() - t0)
-                }'''
+            def millis = { System.currentTimeMillis() }
 
+            5.times {
+                @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+                    assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE
+                })
+                def t0 = millis()
+                1000.times {
+                    "echo"
+                }
+                def elapsed = millis() - t0
+            }
+        '''
     }
 
     void testGroovy5487ReturnNull() {

Reply via email to