Tho*_*ung 9 java generics annotations annotation-processing
我正在编写一个工具,它使用注释处理器根据注释类的方法的返回类型生成源代码.返回类型始终A是定义类型变量的接口的某个子类型(接口或类)T.
interface A<T>{T m();};
Run Code Online (Sandbox Code Playgroud)
我想找到方法m()返回值类型变量的类型参数T.
返回类型由注释处理器表示为javax.lang.model.type.TypeMirror实例.最简单的情况是A<T>直接返回.
@SomeAnnotation
class SomeClass{
A<T> x();
}
Run Code Online (Sandbox Code Playgroud)
要找到的处理器代码T非常简单.(我会在这里投射而不是使用访问者API来保持代码简单.)
DeclaredType type = (DeclaredType) typeMirror;
TypeMirror t = type.getTypeArguments().get(0);
Run Code Online (Sandbox Code Playgroud)
在TypeMirror返回类型的是javax.lang.model.type.DeclaredType和T是第一个类型参数.其结果t是一javax.lang.model.type.TypeVariable对T.同样适用于具体的返回类型A<B>(B某种类型:) interface B{}.结果t是DeclaredType代表B.
其他结果类型开始变得复杂:
interface Subtype<T> extends A<T>{}
interface Concrete extends A<B>{};
interface Multiple<B,T> extends A<T>{}
interface Bounds<T extends B> extends A<T>{}
interface Hierarchy extends Concrete{}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
有没有办法在T不镜像整个java类型系统的情况下找到正确的类型参数?
我用它来解决这个问题,并在这个拉取请求中为WsDoc项目提供了解决方案:https://github.com/versly/wsdoc/pull/7
我做了这样的事情:
Type.MethodType methodType = (Type.MethodType) processingEnv.getTypeUtils().asMemberOf(declaredTypeThatExtendsSomeGenericParent, methodToGetReturnTypeForAsExecutableElement);
TypeMirror type = methodType.getReturnType();
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6426 次 |
| 最近记录: |