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/20 21:59:31 UTC

[groovy] branch master updated: 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 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 92ea8d9  GROOVY-7033: visit AIC's field, method, and parameter annotations
92ea8d9 is described below

commit 92ea8d9615c174d9b113740ce3dca0a723549597
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
---
 .../groovy/classgen/VariableScopeVisitor.java      | 11 +--
 src/test/gls/annotations/AnnotationTest.groovy     | 17 +++++
 .../closures/AnnotationClosureTest.groovy          | 86 +++++++++++-----------
 3 files changed, 66 insertions(+), 48 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index b605b63..6c1f1c6 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -498,17 +498,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
@@ -516,8 +517,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 e815a39..6597b25 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 0f86caf..dee473a 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,47 @@ 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() {
+        shouldCompile '''
             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() {}
+                @Tag(value = { -> })
+                String toString() {}
             }
-"""
+        '''
     }
 }