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'
+ '''
}
}