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 2022/01/29 19:49:17 UTC

[groovy] 02/02: GROOVY-7033: visit AIC's field, method, and parameter annotations

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

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

commit 0e7e7e7a731da0cb588ad1d16d46b92a42acd542
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Jan 20 15:51:56 2022 -0600

    GROOVY-7033: visit AIC's field, method, and parameter annotations
    
    Conflicts:
    	src/test/gls/annotations/closures/AnnotationClosureTest.groovy
---
 .../groovy/classgen/VariableScopeVisitor.java      | 11 +--
 src/test/gls/annotations/AnnotationTest.groovy     | 17 ++++
 .../closures/AnnotationClosureTest.groovy          | 95 +++++++++++-----------
 3 files changed, 72 insertions(+), 51 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 07102bc..ac358dc 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -494,17 +494,18 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
         currentScope.setClassScope(innerClass);
         currentScope.setInStaticContext(false);
         for (MethodNode method : innerClass.getMethods()) {
+            visitAnnotations(method); // GROOVY-7033
             Parameter[] parameters = method.getParameters();
-            if (parameters.length == 0) {
-                parameters = null; // null means no implicit "it"
-            }
+            for (Parameter p : parameters) visitAnnotations(p); // GROOVY-7033
+            if (parameters.length == 0) parameters = null; // disable implicit "it"
             visitClosureExpression(new ClosureExpression(parameters, method.getCode()));
         }
 
         for (FieldNode field : innerClass.getFields()) {
+            visitAnnotations(field); // GROOVY-7033
             Expression initExpression = field.getInitialExpression();
-            pushState(field.isStatic());
             if (initExpression != null) {
+                pushState(field.isStatic());
                 if (initExpression.isSynthetic() && initExpression instanceof VariableExpression
                         && ((VariableExpression) initExpression).getAccessedVariable() instanceof Parameter) {
                     // GROOVY-6834: accessing a parameter which is not yet seen in scope
@@ -512,8 +513,8 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
                     continue;
                 }
                 initExpression.visit(this);
+                popState();
             }
-            popState();
         }
 
         for (Statement initStatement : innerClass.getObjectInitializerStatements()) {
diff --git a/src/test/gls/annotations/AnnotationTest.groovy b/src/test/gls/annotations/AnnotationTest.groovy
index aeb7e04..288869e 100644
--- a/src/test/gls/annotations/AnnotationTest.groovy
+++ b/src/test/gls/annotations/AnnotationTest.groovy
@@ -792,6 +792,23 @@ final class AnnotationTest extends CompilableTestSupport {
         assert err =~ /Cannot specify duplicate annotation/
     }
 
+    // GROOVY-7033
+    void testClassLiteralsRecognizedForAnonymousInnerClassAnnotationUsage() {
+        shouldCompile '''
+            @interface A {
+                Class value()
+            }
+
+            def obj = new Object() {
+                @A(String) def field
+                @A(String) @Override
+                boolean equals(@A(String) param) {
+                    def type = String
+                }
+            }
+        '''
+    }
+
     void testVariableExpressionsReferencingConstantsSeenForAnnotationAttributes() {
         shouldCompile '''
             class C {
diff --git a/src/test/gls/annotations/closures/AnnotationClosureTest.groovy b/src/test/gls/annotations/closures/AnnotationClosureTest.groovy
index d54befd..bb322d1 100644
--- a/src/test/gls/annotations/closures/AnnotationClosureTest.groovy
+++ b/src/test/gls/annotations/closures/AnnotationClosureTest.groovy
@@ -19,45 +19,45 @@
 package gls.annotations.closures
 
 import gls.CompilableTestSupport
-import groovy.test.NotYetImplemented
 
-import java.lang.annotation.RetentionPolicy
 import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
 import java.lang.reflect.Modifier
 
-class AnnotationClosureTest extends CompilableTestSupport {
+final class AnnotationClosureTest extends CompilableTestSupport {
+
     def answer = new Object() {
         def answer() { 42 }
     }
-    
+
     void testGep3InClosure() {
-        shouldCompile """
+        shouldCompile '''
             @interface Bar{Class value();}
             class Foo {
-              @Bar({ sleep 1 })
-              def baz() {}
+                @Bar({ sleep 1 })
+                def baz() {}
             }
-        """
+        '''
     }
 
     void testAllowedAsValueForAnnotationElementOfTypeClass() {
-        shouldCompile """
-import gls.annotations.closures.AnnWithClassElement
+        shouldCompile '''
+            import gls.annotations.closures.AnnWithClassElement
 
-@AnnWithClassElement(elem = { 1 + 2 })
-class Foo {}
-        """
+            @AnnWithClassElement(elem = { 1 + 2 })
+            class Foo {}
+        '''
     }
 
     // TODO: two compile errors instead of one, odd error message
 
     void testNotAllowedAsValueForAnnotationElementOfOtherType() {
-        shouldNotCompile """
-import gls.annotations.closures.AnnWithStringElement
+        shouldNotCompile '''
+            import gls.annotations.closures.AnnWithStringElement
 
-@AnnWithStringElement(elem = { 1 + 2 })
-class Foo {}
-        """
+            @AnnWithStringElement(elem = { 1 + 2 })
+            class Foo {}
+        '''
     }
 
     void testIsCompiledToPublicClass() {
@@ -127,47 +127,50 @@ class Foo {}
     }
 
     void testDoesNoHarmOnAnnotationWithSourceRetention() {
-        shouldCompile """
-import java.lang.annotation.*
+        shouldCompile '''
+            import java.lang.annotation.*
 
-@Retention(RetentionPolicy.SOURCE)
-@interface AnnWithSourceRetention {
-    Class elem()
-}
+            @Retention(RetentionPolicy.SOURCE)
+            @interface AnnWithSourceRetention {
+                Class elem()
+            }
 
-@AnnWithSourceRetention(elem = { 1 + 2 })
-class Foo {}
-        """
+            @AnnWithSourceRetention(elem = { 1 + 2 })
+            class Foo {}
+        '''
     }
 
     void testDoesNoHarmOnAnnotationWithClassRetention() {
-        shouldCompile """
-import java.lang.annotation.*
+        shouldCompile '''
+            import java.lang.annotation.*
 
-@Retention(RetentionPolicy.CLASS)
-@interface AnnWithClassRetention {
-    Class elem()
-}
+            @Retention(RetentionPolicy.CLASS)
+            @interface AnnWithClassRetention {
+                Class elem()
+            }
 
-@AnnWithClassRetention(elem = { 1 + 2 })
-class Foo {}
-        """
+            @AnnWithClassRetention(elem = { 1 + 2 })
+            class Foo {}
+        '''
     }
-    
-    @NotYetImplemented
-    void testAnnotationOnAnonymousMethod() {
-        shouldCompile """        
+
+    // GROOVY-7033
+    void testAnnotationOnAnonymousInnerClassMethod() {
+        assertScript '''
             import java.lang.annotation.*
 
-            @Retention(RetentionPolicy.RUNTIME)
             @Target(ElementType.METHOD)
-            @interface Bar{Class value();}
+            @Retention(RetentionPolicy.RUNTIME)
+            @interface Tag { Class<?> value() }
 
-            return new Object() {
-              @Bar({})
-              String toString() {}
+            def aic = new Object() {
+                @Tag(value = { -> })
+                String toString() {}
             }
-"""
+
+            def toStringMethod = aic.class.getMethod('toString')
+            assert toStringMethod.annotations[0].annotationType().name == 'Tag'
+        '''
     }
 }