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 99af5dfacc GROOVY-10937: check for adding type annotation to
non-redirect type node
99af5dfacc is described below
commit 99af5dfacce807e7ba95fa2dff5e505cd489f610
Author: Eric Milles <[email protected]>
AuthorDate: Fri Feb 24 10:52:28 2023 -0600
GROOVY-10937: check for adding type annotation to non-redirect type node
---
.../java/org/codehaus/groovy/ast/ClassNode.java | 27 +--
.../groovy/classgen/AsmClassGenerator.java | 3 +-
.../codehaus/groovy/classgen/ExtendedVerifier.java | 9 +-
.../groovy/ast/decompiled/AsmDecompilerTest.groovy | 211 ++++++++++++---------
.../ast/decompiled/AsmDecompilerTestData.java | 28 ++-
.../groovy/classgen/asm/TypeAnnotationsTest.groovy | 45 ++---
6 files changed, 190 insertions(+), 133 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index fa1d770513..95e84fd6c2 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -48,6 +48,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
import static org.codehaus.groovy.ast.ClassHelper.SEALED_TYPE;
@@ -1606,29 +1607,31 @@ public class ClassNode extends AnnotatedNode {
}
public List<AnnotationNode> getTypeAnnotations() {
- return typeAnnotations;
+ return new ArrayList<>(typeAnnotations);
}
- public List<AnnotationNode> getTypeAnnotations(ClassNode type) {
- List<AnnotationNode> ret = new ArrayList<>(typeAnnotations.size());
+ public List<AnnotationNode> getTypeAnnotations(final ClassNode type) {
+ List<AnnotationNode> annotations = new ArrayList<>();
for (AnnotationNode node : typeAnnotations) {
if (type.equals(node.getClassNode())) {
- ret.add(node);
+ annotations.add(node);
}
}
- return ret;
+ return annotations;
}
- public void addTypeAnnotation(AnnotationNode annotation) {
- if (annotation != null) {
- if (typeAnnotations == Collections.EMPTY_LIST) {
- typeAnnotations = new ArrayList<>(3);
- }
- typeAnnotations.add(annotation);
+ public void addTypeAnnotation(final AnnotationNode annotation) {
+ if (!isPrimaryClassNode() && !isRedirectNode() && isResolved()) {
+ throw new GroovyBugError("Adding type annotation @" +
annotation.getClassNode().getNameWithoutPackage() + " to non-primary,
non-redirect node: " + getName());
+ }
+ if (typeAnnotations == Collections.EMPTY_LIST) {
+ typeAnnotations = new ArrayList<>(3);
}
+ typeAnnotations.add(requireNonNull(annotation));
+ setAnnotated(true);
}
- public void addTypeAnnotations(List<AnnotationNode> annotations) {
+ public void addTypeAnnotations(final List<AnnotationNode> annotations) {
for (AnnotationNode annotation : annotations) {
addTypeAnnotation(annotation);
}
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 8dc6932706..18104fb6a8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -506,8 +506,7 @@ public class AsmClassGenerator extends ClassGenerator {
visitAnnotations(node, mv);
visitTypeParameters(node, mv);
- // ideally following statement would be in visitMethod but mv not
visible there
- if (!(node instanceof ConstructorNode)) {
+ if (!node.isConstructor() || node.getReturnType().isAnnotated()) {
visitType(node.getReturnType(), mv,
newTypeReference(METHOD_RETURN), "", true);
}
diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 4b26543d7d..8d0d2b435c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -35,7 +35,6 @@ import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.DeclarationExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.AnnotationConstantsVisitor;
@@ -160,6 +159,9 @@ public class ExtendedVerifier extends
ClassCodeVisitorSupport {
@Override
public void visitConstructor(ConstructorNode node) {
visitConstructorOrMethod(node, CONSTRUCTOR_TARGET);
+ if (!node.getReturnType().isRedirectNode() &&
node.getAnnotations().stream().anyMatch(anno ->
anno.isTargetAllowed(TYPE_USE_TARGET))) {
+
node.setReturnType(node.getReturnType().getPlainNodeReference(false)); //
GROOVY-10937
+ }
extractTypeUseAnnotations(node.getAnnotations(), node.getReturnType(),
CONSTRUCTOR_TARGET);
}
@@ -207,7 +209,7 @@ public class ExtendedVerifier extends
ClassCodeVisitorSupport {
}
}
- private void extractTypeUseAnnotations(List<AnnotationNode> mixed,
ClassNode targetType, Integer keepTarget) {
+ private void extractTypeUseAnnotations(final List<AnnotationNode> mixed,
final ClassNode targetType, final int keepTarget) {
List<AnnotationNode> typeUseAnnos = new ArrayList<>();
for (AnnotationNode anno : mixed) {
if (anno.isTargetAllowed(TYPE_USE_TARGET)) {
@@ -216,9 +218,8 @@ public class ExtendedVerifier extends
ClassCodeVisitorSupport {
}
if (!typeUseAnnos.isEmpty()) {
targetType.addTypeAnnotations(typeUseAnnos);
- targetType.setAnnotated(true);
for (AnnotationNode anno : typeUseAnnos) {
- if (keepTarget != null && !anno.isTargetAllowed(keepTarget)) {
+ if (!anno.isTargetAllowed(keepTarget)) {
mixed.remove(anno);
}
}
diff --git
a/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTest.groovy
b/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTest.groovy
index a02ae19abd..69e5b7ccad 100644
--- a/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTest.groovy
@@ -18,7 +18,6 @@
*/
package org.codehaus.groovy.ast.decompiled
-import junit.framework.TestCase
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
@@ -26,14 +25,17 @@ import org.codehaus.groovy.ast.decompiled.support.*
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.control.ClassNodeResolver
import org.codehaus.groovy.control.CompilationUnit
-import org.objectweb.asm.Opcodes
+import org.junit.Test
-final class AsmDecompilerTest extends TestCase {
+import static java.lang.reflect.Modifier.*
- void "test decompile class"() {
+final class AsmDecompilerTest {
+
+ @Test
+ void "basic class"() {
ClassNode node = decompile()
assert AsmDecompilerTestData.name == node.name
- assert (node.modifiers & Opcodes.ACC_PUBLIC) != 0
+ assert isPublic(node.modifiers)
assert !node.genericsPlaceHolder
assert node.usingGenerics
@@ -67,20 +69,23 @@ final class AsmDecompilerTest extends TestCase {
assert v.upperBounds[0].toString() == Object.name
}
- void "test method object return type"() {
- def method = decompile().getDeclaredMethod("objectMethod")
+ @Test
+ void "method object return type"() {
+ def method = decompile().getDeclaredMethod('objectMethod')
assert method.returnType.name == ClassNode.name
}
- void "test method primitive array return type"() {
- def method = decompile().getDeclaredMethod("primitiveArrayMethod")
+ @Test
+ void "method primitive array return type"() {
+ def method = decompile().getDeclaredMethod('primitiveArrayMethod')
assert method.returnType.array
assert method.returnType.componentType.array
assert method.returnType.componentType.componentType ==
ClassHelper.int_TYPE
}
- void "test method parameters and exceptions"() {
- def method =
decompile().getDeclaredMethods("withParametersThrowing")[0]
+ @Test
+ void "method parameters and exceptions"() {
+ def method =
decompile().getDeclaredMethods('withParametersThrowing')[0]
assert method.parameters.length == 2
assert method.parameters[0].type == ClassHelper.int_TYPE
@@ -90,17 +95,20 @@ final class AsmDecompilerTest extends TestCase {
assert method.exceptions[0].name == IOException.name
}
- void "test field"() {
- def field = decompile().getDeclaredField("aField")
+ @Test
+ void "basic field"() {
+ def field = decompile().getDeclaredField('aField')
assert field.type.name == Object.name
}
- void "test constructor"() {
+ @Test
+ void "constructor"() {
def constructor = decompile().getDeclaredConstructors()[0]
assert constructor.parameters[0].type == ClassHelper.boolean_TYPE
}
- void "test supers"() {
+ @Test
+ void "supers"() {
def node = decompile()
assert node.superClass.name == SuperClass.name
assert !node.superClass.usingGenerics
@@ -126,12 +134,13 @@ final class AsmDecompilerTest extends TestCase {
assert !string.type.usingGenerics
}
- void "test simple class annotations"() {
+ @Test
+ void "simple class annotations"() {
def node = decompile().annotations[0]
assert node.classNode.name == Anno.name
- assert ((ConstantExpression) node.members.stringAttr).value == "s"
+ assert ((ConstantExpression) node.members.stringAttr).value == 's'
assert !node.members.booleanAttr
assert ((ClassExpression) node.members.clsAttr).type.name ==
String.name
@@ -139,35 +148,40 @@ final class AsmDecompilerTest extends TestCase {
assert ((PropertyExpression)
node.members.enumAttr).objectExpression.type.name == SomeEnum.name
}
- void "test member annotations"() {
+ @Test
+ void "member annotations"() {
def node = decompile()
- assert node.getDeclaredField("aField").annotations[0].classNode.name
== Anno.name
- assert
node.getDeclaredMethod("objectMethod").annotations[0].classNode.name ==
Anno.name
- assert
!node.getDeclaredMethods("withParametersThrowing")[0].annotations
+ assert node.getDeclaredField('aField').annotations[0].classNode.name
== Anno.name
+ assert
node.getDeclaredMethod('objectMethod').annotations[0].classNode.name ==
Anno.name
+ assert
!node.getDeclaredMethods('withParametersThrowing')[0].annotations
}
- void "test parameter annotations"() {
+ @Test
+ void "parameter annotations"() {
def node = decompile()
- def params =
node.getDeclaredMethods("withParametersThrowing")[0].parameters
+ def params =
node.getDeclaredMethods('withParametersThrowing')[0].parameters
assert params[0].annotations.collect { it.classNode.name } ==
[Anno.name]
assert !params[1].annotations
}
- void "test primitive array attribute"() {
+ @Test
+ void "primitive array attribute"() {
def node = decompile().annotations[0]
def list = ((ListExpression) node.members.intArrayAttr).expressions
assert list.collect { ((ConstantExpression) it).value } == [4, 2]
}
- void "test class array attribute"() {
+ @Test
+ void "class array attribute"() {
def node = decompile().annotations[0]
def list = ((ListExpression) node.members.classArrayAttr).expressions
assert list.collect { ((ClassExpression) it).type.name } ==
[AsmDecompilerTestData.name]
}
- void "test annotation array attribute"() {
+ @Test
+ void "annotation array attribute"() {
def node = decompile().annotations[0]
def list = ((ListExpression) node.members.annoArrayAttr).expressions
@@ -181,14 +195,16 @@ final class AsmDecompilerTest extends TestCase {
assert ((ConstantExpression) annotationNode.members.booleanAttr).value
== false
}
- void "test annotation default method"() {
- def method = decompile(Anno.name).getDeclaredMethod('booleanAttr')
+ @Test
+ void "annotation default method"() {
+ def method = decompile(Anno).getDeclaredMethod('booleanAttr')
assert method.hasAnnotationDefault()
assert method.code
}
- void "test annotation retention and targets"() {
- def anno = decompile().getAnnotations(decompile(Anno.name))[0]
+ @Test
+ void "annotation retention and targets"() {
+ def anno = decompile().getAnnotations(decompile(Anno))[0]
assert anno.hasRuntimeRetention()
assert !anno.hasClassRetention()
assert !anno.hasSourceRetention()
@@ -198,8 +214,9 @@ final class AsmDecompilerTest extends TestCase {
assert !anno.isTargetAllowed(AnnotationNode.LOCAL_VARIABLE_TARGET)
}
- void "test enum field"() {
- def node = decompile(SomeEnum.name).plainNodeReference
+ @Test
+ void "enum field"() {
+ def node = decompile(SomeEnum).plainNodeReference
for (s in ['FOO', 'BAR']) {
def field = node.getDeclaredField(s)
assert field
@@ -207,8 +224,9 @@ final class AsmDecompilerTest extends TestCase {
}
}
- void "test generic method"() {
- def method = decompile().getDeclaredMethods("genericMethod")[0]
+ @Test
+ void "generic method"() {
+ def method = decompile().getDeclaredMethods('genericMethod')[0]
assert method.genericsTypes.size() == 2
assert method.genericsTypes[0].name == 'A'
@@ -240,18 +258,21 @@ final class AsmDecompilerTest extends TestCase {
assert wildcard.upperBounds == null
}
- void "test non-generic exceptions"() {
- def method = decompile().getDeclaredMethods("nonGenericExceptions")[0]
+ @Test
+ void "non-generic exceptions"() {
+ def method = decompile().getDeclaredMethods('nonGenericExceptions')[0]
assert method.exceptions[0].name == IOException.name
}
- void "test non-generic parameters"() {
- def method = decompile().getDeclaredMethods("nonGenericParameters")[0]
+ @Test
+ void "non-generic parameters"() {
+ def method = decompile().getDeclaredMethods('nonGenericParameters')[0]
assert method.parameters[0].type == ClassHelper.boolean_TYPE
}
- void "test generic field"() {
- def type = decompile().getDeclaredField("genericField").type
+ @Test
+ void "generic field"() {
+ def type = decompile().getDeclaredField('genericField').type
assert type.name == List.name
assert type.usingGenerics
@@ -262,83 +283,101 @@ final class AsmDecompilerTest extends TestCase {
assert tRef.genericsTypes[0].name == 'T'
}
- void "test non-trivial erasure"() {
- def cls = decompile(NonTrivialErasure.name)
+ @Test
+ void "non-trivial erasure"() {
+ def cls = decompile(NonTrivialErasure)
- def method = cls.getDeclaredMethods("method")[0]
+ def method = cls.getDeclaredMethods('method')[0]
assert method.returnType.toString() == 'V ->
java.lang.RuntimeException'
assert method.parameters[0].type.toString() == 'V ->
java.lang.RuntimeException'
assert method.exceptions[0].toString() == 'V ->
java.lang.RuntimeException'
- def field = cls.getDeclaredField("field")
+ def field = cls.getDeclaredField('field')
assert field.type.toString() == 'V -> java.lang.RuntimeException'
}
- void "test static inner class"() {
- ClassNode cn = decompile(AsmDecompilerTestData.InnerStatic.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) != 0
+ @Test
+ void "static inner class"() {
+ ClassNode cn = decompile(AsmDecompilerTestData.InnerStatic)
+ assert isStatic(cn.modifiers)
}
- void "test static inner with dollar"() {
- ClassNode cn = decompile(AsmDecompilerTestData.Inner$WithDollar.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) != 0
+ @Test
+ void "static inner with dollar"() {
+ ClassNode cn = decompile(AsmDecompilerTestData.Inner$WithDollar)
+ assert isStatic(cn.modifiers)
}
- void "test static inner classes with same name"() {
- ClassNode cn = decompile(Groovy8632Abstract.Builder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) != 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) != 0
+ @Test
+ void "static inner classes with same name"() {
+ ClassNode cn = decompile(Groovy8632Abstract.Builder)
+ assert isStatic(cn.modifiers)
+ assert isAbstract(cn.modifiers)
- cn = decompile(Groovy8632.Builder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) != 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) == 0
+ cn = decompile(Groovy8632.Builder)
+ assert isStatic(cn.modifiers)
+ assert !isAbstract(cn.modifiers)
- cn = decompile(Groovy8632Groovy.Builder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) != 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) == 0
+ cn = decompile(Groovy8632Groovy.Builder)
+ assert isStatic(cn.modifiers)
+ assert !isAbstract(cn.modifiers)
}
- void "test inner classes with same name"() {
- ClassNode cn = decompile(Groovy8632Abstract.InnerBuilder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) == 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) != 0
+ @Test
+ void "inner classes with same name"() {
+ ClassNode cn = decompile(Groovy8632Abstract.InnerBuilder)
+ assert !isStatic(cn.modifiers)
+ assert isAbstract(cn.modifiers)
- cn = decompile(Groovy8632.InnerBuilder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) == 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) == 0
+ cn = decompile(Groovy8632.InnerBuilder)
+ assert !isStatic(cn.modifiers)
+ assert !isAbstract(cn.modifiers)
- cn = decompile(Groovy8632Groovy.InnerBuilder.name)
- assert (cn.modifiers & Opcodes.ACC_STATIC) == 0
- assert (cn.modifiers & Opcodes.ACC_ABSTRACT) == 0
+ cn = decompile(Groovy8632Groovy.InnerBuilder)
+ assert !isStatic(cn.modifiers)
+ assert !isAbstract(cn.modifiers)
}
- void "test private inner class"() {
- ClassNode cn = decompile(Groovy8632.InnerPrivate.name)
- assert (cn.modifiers & Opcodes.ACC_PRIVATE) != 0
- assert (cn.modifiers & Opcodes.ACC_PUBLIC) == 0
+ @Test
+ void "private inner class"() {
+ ClassNode cn = decompile(Groovy8632.InnerPrivate)
+ assert isPrivate(cn.modifiers)
+ assert !isPublic(cn.modifiers)
}
- void "test protected inner class"() {
- ClassNode cn = decompile(Groovy8632.InnerProtected.name)
- assert (cn.modifiers & Opcodes.ACC_PROTECTED) != 0
- assert (cn.modifiers & Opcodes.ACC_PUBLIC) == 0
+ @Test
+ void "protected inner class"() {
+ ClassNode cn = decompile(Groovy8632.InnerProtected)
+ assert isProtected(cn.modifiers)
+ assert !isPublic(cn.modifiers)
}
- void "test non-parameterized generics"() {
- assert
decompile().getDeclaredMethod("nonParameterizedGenerics").genericsTypes == null
+ @Test
+ void "non-parameterized generics"() {
+ assert
decompile().getDeclaredMethod('nonParameterizedGenerics').genericsTypes == null
}
- void "test non-static parameterized inner"() {
- def asmType = decompile().getDeclaredMethod("returnInner").returnType
- def jvmType = new
ClassNode(AsmDecompilerTestData).getDeclaredMethod("returnInner").returnType
+ @Test
+ void "non-static parameterized inner"() {
+ def asmType = decompile().getDeclaredMethod('returnInner').returnType
+ def jvmType = new
ClassNode(AsmDecompilerTestData).getDeclaredMethod('returnInner').returnType
assert asmType == jvmType
- assert asmType.genericsTypes.collect { it.name } ==
jvmType.genericsTypes.collect { it.name }
+ assert asmType.genericsTypes*.name == jvmType.genericsTypes*.name
+ }
+
+ // GROOVY-10937
+ @Test
+ void "type annotations everywhere"() {
+ def asmType = decompile(WithTypeAnnotations)
+ def methods = asmType.declaredConstructors
+ assert !ClassHelper.OBJECT_TYPE.annotated
+ assert !ClassHelper.VOID_TYPE.annotated
}
//--------------------------------------------------------------------------
- private static ClassNode decompile(String className =
AsmDecompilerTestData.name) {
- def classFileName = className.replace('.', '/') + '.class'
+ private static ClassNode decompile(Class clazz = AsmDecompilerTestData) {
+ def classFileName = clazz.name.replace('.', '/') + '.class'
def resource = AsmDecompilerTest.classLoader.getResource(classFileName)
def stub = AsmDecompiler.parseClass(resource)
diff --git
a/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTestData.java
b/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTestData.java
index fcd81ffbde..a4e639ba41 100644
--- a/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTestData.java
+++ b/src/test/org/codehaus/groovy/ast/decompiled/AsmDecompilerTestData.java
@@ -77,17 +77,14 @@ public class AsmDecompilerTestData<T extends List<? super
T>, V> extends SuperCl
static class Inner$WithDollar {}
static <T extends List<? super T>> AsmDecompilerTestData<T,
Integer>.Inner<String> returnInner() { return null; }
-
}
-@SuppressWarnings("unused")
+class SuperClass { }
+
interface Intf<S> { }
enum SomeEnum { FOO, BAR }
-class SuperClass { }
-
-@SuppressWarnings("unused")
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD,
ElementType.PARAMETER})
@interface Anno {
@@ -100,7 +97,11 @@ class SuperClass { }
InnerAnno[] annoArrayAttr() default {};
}
-@SuppressWarnings("unused")
+@Target(ElementType.TYPE_USE)
+@Retention(RetentionPolicy.RUNTIME)
+@interface TypeAnno {
+}
+
@Retention(RetentionPolicy.RUNTIME)
@interface InnerAnno {
boolean booleanAttr() default true;
@@ -110,4 +111,17 @@ class SuperClass { }
abstract class NonTrivialErasure<V extends RuntimeException> {
abstract V method(V param) throws V;
V field;
-}
\ No newline at end of file
+}
+
+@SuppressWarnings("unused")
+abstract class WithTypeAnnotations extends @TypeAnno Object implements
@TypeAnno Cloneable, @TypeAnno List<@TypeAnno Object> {
+ @TypeAnno Object method(@TypeAnno Object param) throws @TypeAnno Exception
{
+ return null;
+ }
+ <T extends @TypeAnno Object> @TypeAnno T parameterizedMethod() {
+ return null;
+ }
+ @TypeAnno WithTypeAnnotations() {
+ }
+ @TypeAnno Object field;
+}
diff --git
a/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
b/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
index 6e806ae38b..6fc4b0c0c7 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
@@ -18,7 +18,29 @@
*/
package org.codehaus.groovy.classgen.asm
-class TypeAnnotationsTest extends AbstractBytecodeTestCase {
+final class TypeAnnotationsTest extends AbstractBytecodeTestCase {
+
+ void testTypeAnnotationsForConstructor() {
+ assert compile(method: '<init>', classNamePattern: 'HasConstructor',
'''
+ import java.lang.annotation.*
+ import static java.lang.annotation.RetentionPolicy.RUNTIME
+ import static java.lang.annotation.ElementType.*
+
+ @Retention(RUNTIME) @Target(CONSTRUCTOR) @interface CtorAnno { }
+ @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno0 { }
+ @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno1 { }
+
+ class HasConstructor {
+ @CtorAnno @TypeAnno0 @TypeAnno1 HasConstructor() { }
+ }
+ ''').hasSequence([
+ 'public <init>()V',
+ '@LCtorAnno;()',
+ '@LTypeAnno0;() : METHOD_RETURN',
+ '@LTypeAnno1;() : METHOD_RETURN'
+ ])
+ }
+
void testTypeAnnotationsForMethod1() {
assert compile(method: 'foo','''
import java.lang.annotation.*
@@ -142,27 +164,6 @@ class TypeAnnotationsTest extends AbstractBytecodeTestCase
{
])
}
- void testTypeAnnotationsForConstructor() {
- assert compile(method: '<init>', classNamePattern: 'HasCons', '''
- import java.lang.annotation.*
- import static java.lang.annotation.RetentionPolicy.RUNTIME
- import static java.lang.annotation.ElementType.*
-
- @Retention(RUNTIME) @Target([CONSTRUCTOR]) @interface ConstructorAnno
{ }
- @Retention(RUNTIME) @Target([TYPE_USE]) @interface TypeAnno0 { }
- @Retention(RUNTIME) @Target([TYPE_USE]) @interface TypeAnno1 { }
-
- class HasCons {
- @ConstructorAnno @TypeAnno0 @TypeAnno1 HasCons() { }
- }
- ''').hasSequence([
- 'public <init>()V',
- '@LConstructorAnno;()',
- '@LTypeAnno0;() : METHOD_RETURN',
- '@LTypeAnno1;() : METHOD_RETURN'
- ])
- }
-
void testTypeAnnotationsForField1() {
assert compile(field: 'documents', classNamePattern: 'Foo', '''
import java.lang.annotation.*