Mat*_*ARD 7 java annotation-processing
我有几个使用 java 注释处理器执行的检查,但我也想对未注释的类型进行检查。
例如,如果我们假设我有一个注释,例如@Responsible(name="xyz")挂钩编译过程的最佳方法是什么,以强制所有顶级类型都存在该注释。
在我当前的实现中,我依赖于两个注释,预期的注释(Responsible)和包级别的注释。后者用于“触发”注释处理器,即使不存在预期的注释。然后,在触发的注释处理器内,我搜索并过滤磁盘上的 java 文件(使用传递给编译器的参数)以收集我想要处理的所有文件,并在 java 文件对应于处理器正在处理的注释类型时过滤它们。如果有人在未指定注释的情况下提交新文件,则构建会失败。
是否有更干净的方法来查找“无注释”类型?
您不必依赖注释来运行处理器。正如文档中所解释的:
\n\n\n\n\n如果不存在注释类型,注释处理仍然会发生,但只有支持处理“*”的通用处理器才能声明注释类型的(空)集。
\n
你寻找课程的方法有点笨拙。相反,您可以依赖包和类之间的父子关系:找出包含有趣的类的顶级包元素的名称,然后使用 . 深入到该包(和/或其子包)Element#getEnclosedElements。或者,您可以在该包 \xe2\x80\x94 中找到单个类,然后使用 升到最顶层的包Element#getEnclosingElement。包对象可以使用Elements#getPackageElement通过名称获取,类对象可以使用Elements#getTypeElement通过名称获取。
与与文件和目录的手动交互相比,脆弱性要小得多,并且如果源文件在目录之间移动或拆分,也不会损坏。
\n\n请注意,包含顺序是"a single package" -> "class" -> "method" -> ...,每个包的父包都是包本身,而不是它的“父”包(net.example不包含在 中net)。
为了处理所有元素,我错过了RoundEnvironment#getRootElements()如果处理器被声明为使用 来处理所有内容,那么我正在寻找的元素列表*。
因此,为了检查所有类型是否都用 a 进行了注释,@Responsible我最终得到了
@AutoService(Processor.class)
public class ResponsibleAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
List<ElementKind> typeKinds = Arrays.asList(ElementKind.ENUM, ElementKind.INTERFACE, ElementKind.CLASS);
// let's gather all types we are interrested in
Set<String> allElements = env.getRootElements()
.stream()
.filter(e -> typeKinds.contains(e.getKind())) // keep only interesting elements
.map(e -> e.asType().toString()) // get their full name
.collect(Collectors.toCollection(() -> new HashSet<>()));
Set<String> typesWithResponsible = new HashSet<>();
annotations.forEach(te -> {
if (Responsible.class.getName().equals(te.asType().toString())) {
// We collect elements with an already declared ownership
env.getElementsAnnotatedWith(te).forEach(e -> typesWithResponsible.add(e.asType().toString()));
}
});
allElements.removeAll(typesWithResponsible);
allElements.forEach(cname -> processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, cname + " must be annotated with @" + Responsible.class.getName() + " to declare a ownership"));
return false;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
// We want to process all elements
return Collections.singleton("*");
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
895 次 |
| 最近记录: |