Repeatable Annotations
December 17, 2013 Leave a comment
It looks like the annotations can repeat according to Repeating Annotations.
I am still using
java version "1.8.0-ea" Java(TM) SE Runtime Environment (build 1.8.0-ea-b113) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b55, mixed mode)
This code has a problem.
- Arrays.asList(typeMirror.getAnnotationsByType(RepeatableAnnotation.TypeUse.class))
This does not print anything. There are two annotations.
This could be a problem with the particular JDK 8 build. The latest is b120. I have to try the latest build.
Update: This is most likely a code problem because even b120 does not help.
Update 1: This is not a code problem but b120 has some bugs according to the type-annotations-dev list.
The result is this.
Annotation [@com.test.RepeatableAnnotation.TypeUses({@com.test.RepeatableAnnotation.TypeUse(0), @com.test.RepeatableAnnotation.TypeUse(1)})] [com.test.RepeatableAnnotation.Test1]
[value()][{@com.test.RepeatableAnnotation.TypeUse(0), @com.test.RepeatableAnnotation.TypeUse(1)}]
Annotation [[]] [java.lang.Integer]
I am not able to get the annotations applied on the bound Integer
package com.test; import java.lang.annotation.*; public class RepeatableAnnotation { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) public @interface TypeUses { TypeUse[] value(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @Repeatable(value = TypeUses.class) protected @interface TypeUse { int value(); } @TypeUse(value = 0) @TypeUse(value = 1)class Test1< T extends @TypeUse(value = 2) @TypeUse(value = 3) Integer> { /** * A type annotation is permitted in front of a constructor declaration, where declaration annotations are already permitted. */ @TypeUse(value = 0) <S> Test1(String s){ } } }
Annotation Processor
package com.test; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.*; import javax.lang.model.type.ExecutableType; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVisitor; import javax.lang.model.util.SimpleTypeVisitor8; import java.util.*; import static javax.lang.model.util.ElementFilter.typesIn; @SupportedAnnotationTypes("*") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class RepeatableAnnotationFinder extends AbstractProcessor{ public RepeatableAnnotationFinder(){ super(); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { TypeElement tye = null; if( !roundEnv.processingOver()){ Iterator<? extends Element> te = annotations.iterator(); for (TypeElement element : typesIn(roundEnv.getRootElements()) ) { processEnclosedElements(element.getEnclosedElements(), roundEnv); } } return false; } private void processEnclosedElements(List<? extends Element> enclosedElements, RoundEnvironment roundEnv) { for( Element e : enclosedElements ){ if (e.getKind() == ElementKind.CLASS){ System.out.println( "Annotation [" + e.getAnnotationMirrors() + "] [" + e + "]"); processClassTypeParameters(e); } } } private void processClassTypeParameters(Element e) { for (TypeParameterElement typeParameterElement : ((TypeElement) e).getTypeParameters()) { for( AnnotationMirror am : typeParameterElement.getAnnotationMirrors() ){ System.out.println( "Annotation [" + am + "] [" + typeParameterElement + "]"); for(Map.Entry< ? extends ExecutableElement, ? extends AnnotationValue> m : am.getElementValues().entrySet()){ System.out.println( "[" + m.getKey() +"][" + m.getValue() + "]"); } } for (TypeMirror typeMirror : typeParameterElement.getBounds()) { System.out.println( "Annotation [" + Arrays.asList(typeMirror.getAnnotationsByType(RepeatableAnnotation.TypeUse.class)) + "] [" + typeMirror + "]"); } } } }
So I will wait for a newer build before trying this again.