You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/04/04 04:34:17 UTC

[groovy] branch master updated: GROOVY-9452: Multiple Repeatable Annotations Container generated if an explicit container is present and an implicit one required

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

sunlan 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 8b4ef9b  GROOVY-9452: Multiple Repeatable Annotations Container generated if an explicit container is present and an implicit one required
8b4ef9b is described below

commit 8b4ef9bdb3383d111cabfbedc4b10b9d65a044bf
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Mar 31 00:34:58 2020 +1000

    GROOVY-9452: Multiple Repeatable Annotations Container generated if an explicit container is present and an implicit one required
---
 .../codehaus/groovy/classgen/ExtendedVerifier.java |  4 +++
 src/test/gls/annotations/AnnotationTest.groovy     | 34 ++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 57f13b1..4f29cbf 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -207,6 +207,10 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport {
                     }
                 }
                 if (repeatable != null) {
+                    if (nonSourceAnnotations.containsKey(repeatable.getName())) {
+                        addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName()
+                                + " found when creating implicit container for " + next.getKey(), node);
+                    }
                     AnnotationNode collector = new AnnotationNode(repeatable);
                     if (repeatee.hasRuntimeRetention()) {
                         collector.setRuntimeRetention(true);
diff --git a/src/test/gls/annotations/AnnotationTest.groovy b/src/test/gls/annotations/AnnotationTest.groovy
index c91078c..6122a1c 100644
--- a/src/test/gls/annotations/AnnotationTest.groovy
+++ b/src/test/gls/annotations/AnnotationTest.groovy
@@ -728,12 +728,20 @@ final class AnnotationTest extends CompilableTestSupport {
                 @MyAnnotation(value = "val2")
                 String method2() { 'method2' }
 
+                // another control (okay to mix one uncontained with one explicit container)
+                @MyAnnotationArray([@MyAnnotation("val1"), @MyAnnotation("val2")])
+                @MyAnnotation(value = "val3")
+                String method3() { 'method3' }
+
                 static void main(String... args) {
                     MyClass myc = new MyClass()
                     assert 'method1' == myc.method1()
                     assert 'method2' == myc.method2()
                     assert expected.contains(checkAnnos(myc, "method1"))
                     assert expected.contains(checkAnnos(myc, "method2"))
+                    assert 'method3' == myc.method3()
+                    def m3 = myc.getClass().getMethod('method3')
+                    assert m3.getAnnotationsByType(MyAnnotation).size() == 3
                 }
 
                 private static String checkAnnos(MyClass myc, String name) {
@@ -758,6 +766,32 @@ final class AnnotationTest extends CompilableTestSupport {
         '''
     }
 
+    // GROOVY-9452
+    void testDuplicationAnnotationOnClassWithParams() {
+        def err = shouldFail '''
+            import java.lang.annotation.*
+
+            @Target(ElementType.TYPE)
+            @Retention(RetentionPolicy.RUNTIME)
+            @Repeatable(As)
+            @interface A {
+                String value()
+            }
+
+            @Retention(RetentionPolicy.RUNTIME)
+            @interface As {
+                A[] value()
+            }
+
+            @A("a")
+            @A("b")
+            @As([@A("c")])
+            class Foo {}
+        '''
+
+        assert err =~ /Cannot specify duplicate annotation/
+    }
+
     void testVariableExpressionsReferencingConstantsSeenForAnnotationAttributes() {
         shouldCompile '''
             class C {