Den*_*søe 7 java annotation-processing
我正在编写一个AnnotationProcessor,它应该生成java代码.它应该从某些现有接口生成派生接口.
为此,我需要找到原始输入代码的import语句,以便我可以在生成的java文件中输出它.
如何才能做到这一点?
您无法使用注释处理器获取import 语句.你可以得到的是该类使用的类型,甚至更好.
源代码中的Import语句不足以分析类中使用的类型,因为并非所有使用的类型都具有import语句.如果您确实只需要实际语句,则可以直接读取源文件.
如果您只查看语句,则存在一些问题:
java.util.Date date;使用注释处理器和Mirror API,您可以获得属性类型,方法参数,方法返回类型等 - 基本上是不在方法或块中的每个声明的类型.这应该足够好了.
您应该分析类的每个元素并将其类型存储在Set中.有一些实用程序类可以帮助完成此任务.您可以忽略java.lang包中的任何类型,因为它始终是隐式导入的.
最小注释处理器可能如下所示:
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.TypeElement;
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes("*")
public class Processor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
ImportScanner scanner = new ImportScanner();
scanner.scan(roundEnv.getRootElements(), null);
Set<String> importedTypes = scanner.getImportedTypes();
// do something with the types
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这里的扫描仪扩展了ElementScanner7基于访客模式.我们只实现一些访问者方法并按类型过滤元素,因为并非所有元素都可以实际包含可导入类型.
import java.util.HashSet;
import java.util.Set;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementScanner7;
public class ImportScanner extends ElementScanner7<Void, Void> {
private Set<String> types = new HashSet<>();
public Set<String> getImportedTypes() {
return types;
}
@Override
public Void visitType(TypeElement e, Void p) {
for(TypeMirror interfaceType : e.getInterfaces()) {
types.add(interfaceType.toString());
}
types.add(e.getSuperclass().toString());
return super.visitType(e, p);
}
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
if(e.getReturnType().getKind() == TypeKind.DECLARED) {
types.add(e.getReturnType().toString());
}
return super.visitExecutable(e, p);
}
@Override
public Void visitTypeParameter(TypeParameterElement e, Void p) {
if(e.asType().getKind() == TypeKind.DECLARED) {
types.add(e.asType().toString());
}
return super.visitTypeParameter(e, p);
}
@Override
public Void visitVariable(VariableElement e, Void p) {
if(e.asType().getKind() == TypeKind.DECLARED) {
types.add(e.asType().toString());
}
return super.visitVariable(e, p);
}
}
Run Code Online (Sandbox Code Playgroud)
此扫描程序将一组类型作为完全限定的路径返回.还有一些事情需要考虑,有些事情要实施:
java.lang来自同一包的元素和类型java.util.List<String>TypeKind.DECLARED并不是唯一一种可导入类型的元素.还要检查TypeKind.ARRAY并获取它的实际声明类型.可以使用而不是else if(e.asType().getKind() == TypeKind.ARRAY) // ...在类中添加另一个TypeKindVisitor7ElementScanner6,TypeKindVisitor6等实现.