我已经编写了一个注解处理器,它只是将注解类的列表转储到一个文本文件中,为了适应Eclipse中的增量构建,它还尝试重新读取文件并检查类是否仍然具有注解,如果没有,它将从列表中删除类。
问题是Eclipse在您删除注解时不会触发注解处理器,因此只有在您将注解添加到另一个类时,文本文件才会更新。
有没有一种方法可以将Eclipse配置为在删除注解时运行注解处理器?该项目正在使用Gradle/Buildship。
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) {
try {
generateAnnotationFiles(annotations, roundEnv);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
return false;
}
private void generateAnnotationFiles(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws IOException {
for (var i : annotations) {
var elements = roundEnv.getElementsAnnotatedWith(i);
var fileName = "META-INF/annotations/" + i.getQualifiedName();
var classBuilder = new HashSet<>(convertElementsToList(elements));
classBuilder.addAll(getPreviousListedClasses(fileName, i));
var classes = new ArrayList<>(classBuilder);
Collections.sort(classes);
try (var out =
new PrintWriter(
processingEnv
.getFiler()
.createResource(StandardLocation.SOURCE_OUTPUT, "", fileName)
.openWriter())) {
for (var clazz : classes) {
out.append(clazz);
out.append('\n');
}
}
}
}
private List<String> convertElementsToList(Set<? extends Element> elements) {
var ret = new ArrayList<String>();
for (var elem : elements) {
var packag = processingEnv.getElementUtils().getPackageOf(elem).getQualifiedName().toString();
var fullyQualifiedName = packag + "." + elem.getSimpleName();
ret.add(fullyQualifiedName);
}
return ret;
}
private List<String> getPreviousListedClasses(String fileName, TypeElement annotation)
throws IOException {
try {
var previousFile =
processingEnv.getFiler().getResource(StandardLocation.SOURCE_OUTPUT, "", fileName);
var classSplit = openPreviousFile(previousFile);
var ret = new ArrayList<String>();
for (var clazz : classSplit) {
if (classIsStillAnnotated(clazz, annotation)) {
ret.add(clazz);
}
}
return ret;
} catch (FilerException e) {
throw e;
} catch (IOException e) {
return Collections.emptyList();
}
}
private String[] openPreviousFile(FileObject previousFile) throws IOException {
try (var in = previousFile.openInputStream()) {
var fileContents = ByteStreams.toByteArray(in);
var fileString = new String(fileContents, StandardCharsets.UTF_8);
var classSplit = fileString.split("\n");
return classSplit;
}
}
private boolean classIsStillAnnotated(String clazz, TypeElement annotation) {
var prevTypeElement = processingEnv.getElementUtils().getTypeElement(clazz);
if (prevTypeElement == null) {
return false;
}
var annot = prevTypeElement.getAnnotationMirrors();
for (var i : annot) {
if (i.getAnnotationType().asElement().equals(annotation)) {
return true;
}
}
return false;
}
1条答案
按热度按时间cgyqldqp1#
问题是getSupportedAnnotationTypes()需要返回“*”,因为它需要能够对空的注解集进行操作。它还需要始终运行
writeAnnotationFile
,而不仅仅是在roundEnv.getElementsAnnotatedWith
返回结果时运行。现在,当注解被删除时,它会正确地更新文件。这意味着当你进行完全重建时,它会消耗所有的类,但是一个慢的处理器比一个根本不工作的处理器要好。它也有一个问题,它会创建空的文本文件,而不是删除它,但这不是什么大问题。
编辑
之前发布的解决方案在Eclipse中运行,但在使用Gradle构建时却无法运行。此解决方案在Eclipse和Gradle中都可以运行。
在Eclipse中可用但在Gradle中不可用的旧解决方案