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.