J'écris un outil qui utilise le processeur d'annotation pour générer du code source en fonction du type de retour des méthodes d'une classe annotée. Le type de retour est toujours un sous-type (interface ou classe) d'une interface je voudrais aime trouver le paramètre type pour la méthode Le type de retour est représenté par le processeur d'annotation en tant que A code> qui définit une variable de type
t code>.
m () code> Type de valeur de retour Variable
t code>. p>
javax.lang.model.type.typeMirror code> instance. Le cas le plus simple consiste à retourner
a
Subtype<B> -> DeclaredType B
Subtype<T> -> TypeVariable T
Concrete -> DeclaredType B
Multiple<B,T> -> TypeVariable T or DeclaredType B depeding on Multiple
Multiple<B,B> -> TypeVariable B
<T extends B> A<T> -> TypeVariable T with super class bound B
Bound<B> -> DeclaredType B
Bound<C> -> DeclaredType C (subtype of B)
Hierarchy -> TypeVariable T
3 Réponses :
public AnnotationProcessor getProcessorFor( Set<AnnotationTypeDeclaration> atds, AnnotationProcessorEnvironment env) { return new SomeAnnotationProcessor(env); } private static class SomeAnnotationProcessor implements AnnotationProcessor { private final AnnotationProcessorEnvironment env; SomeAnnotationProcessor(AnnotationProcessorEnvironment env) { this.env = env; } public void process() { for (TypeDeclaration typeDecl : env.getSpecifiedTypeDeclarations()) { System.out.println("in class: " + typeDecl); typeDecl.accept(getDeclarationScanner( new SomeClassVisitor(), NO_OP)); } } private static class SomeClassVisitor extends SimpleDeclarationVisitor { @Override public void visitMethodDeclaration( MethodDeclaration methodDeclaration) { System.out.println("visiting method: "+methodDeclaration + " -> "+methodDeclaration.getReturnType()); methodDeclaration.getReturnType().accept(new SomeTypeVisitor()); } } } private static class SomeTypeVisitor implements TypeVisitor { public void visitClassType(ClassType classType) { System.out.println("classType: " + classType + " -> "+classType.getClass()); } @Override public void visitInterfaceType(InterfaceType interfaceType) { Types types = annotationProcessorEnvironment.getTypeUtils(); TypeDeclaration typeDeclaration = annotationProcessorEnvironment .getTypeDeclaration("A"); Collection<InterfaceType> superinterfaces = interfaceType .getSuperinterfaces(); System.out.println("interfaceType: " + interfaceType + " -> " + superinterfaces); DeclaredType typeOfA = types.getDeclaredType(typeDeclaration); boolean isSubTypeOfA = types.isSubtype(interfaceType, typeOfA); if (isSubTypeOfA) { findTypeVariable(types, superinterfaces, typeOfA); } Iterator<TypeMirror> iterator = interfaceType .getActualTypeArguments().iterator(); while (iterator.hasNext()) { TypeMirror next = iterator.next(); next.accept(new SomeTypeVisitor()); } } public void visitTypeVariable(TypeVariable typeVariable) { System.out.println("typeVariable: " + typeVariable.getDeclaration() + " -> "+typeVariable.getClass()); } private void findTypeVariable(Types types, Collection<InterfaceType> superinterfaces, DeclaredType typeOfA) { for (InterfaceType superInterface : superinterfaces) { TypeMirror erasure = types.getErasure(superInterface); if (erasure.equals(typeOfA)) { System.out.println("true, "+superInterface.getActualTypeArguments()); } else { System.out.println("false: " + typeOfA + " =!= " + erasure); findTypeVariable(types, superInterface.getSuperinterfaces(), typeOfA); } } } }
Ceci est simple. Il retournera déclaré que le béton déclaré pour @someannotation Classe quelque chose {béton x () {}} et le béton d'interface étend un . Le résultat droit est B. La mise en œuvre doit déterminer que l'argument de type pour la variable de type T dans A est B pour le béton. Ou plus simple, la valeur de retour de la méthode de la méthode est un sous-type de A . La question est la suivante: quel est le paramètre de type T dans A pour un sous-type donné de A.
Votre code est fondamentalement identique à: type de type = (déclaréeTYPE) Typemirror; Typemirror t = type.getTypearguments (). Obtenez (0); d'en haut. Le visiteur ne peut que différencier entre le type de type variable et déclaré.
Bonjour, j'ai mis à jour le code. De côté, je reçois la déclaration B pour la hiérarchie, ce qui semble correct.
Je l'ai utilisé pour résoudre ce problème et contribué à la solution au projet WSDOC dans Cette demande de traction: https://github.com/versly/wsdoc/pull/7 P>
J'ai fait quelque chose comme ceci: p>
Cela semble être une question commune, pour ceux qui arrivent de Google: il y a de l'espoir.
Le Dagger di projet est sous licence Apache 2.0 et contient des méthodes utilitaires pour travailler avec des types dans un processeur d'annotation. P>
en particulier, la classe util code> peut être Vu entier sur github ( Util.java ) et définit une méthode
TypeTostring STATIC STATIQUE publique (type Typemirror) code>. Il utilise un type de typeVisitor et des appels récursifs pour créer une représentation de chaîne d'un type. Voici un extrait de référence: P>
public static TypeMirror getGenericType(final TypeMirror type)
{
final TypeMirror[] result = { null };
type.accept(new SimpleTypeVisitor6<Void, Void>()
{
@Override
public Void visitDeclared(DeclaredType declaredType, Void v)
{
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (!typeArguments.isEmpty())
{
result[0] = typeArguments.get(0);
}
return null;
}
@Override
public Void visitPrimitive(PrimitiveType primitiveType, Void v)
{
return null;
}
@Override
public Void visitArray(ArrayType arrayType, Void v)
{
return null;
}
@Override
public Void visitTypeVariable(TypeVariable typeVariable, Void v)
{
return null;
}
@Override
public Void visitError(ErrorType errorType, Void v)
{
return null;
}
@Override
protected Void defaultAction(TypeMirror typeMirror, Void v)
{
throw new UnsupportedOperationException();
}
}, null);
return result[0];
}