好的,我找到了解决方法:
在处理器中,将 rootElements 存储在某处:
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("*")
public class AnnotationProcessor extends AbstractProcessor {
private Trees trees;
private List<TreeScanner<?, Trees>> scanners = new LinkedList<>();
public void addScanner(TreeScanner<?, Trees> scanner) {
scanners.add(scanner);
}
public void removeScanner(TreeScanner<?, Trees> scanner) {
scanners.remove(scanner);
}
@Override
public synchronized void init(final ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
trees = Trees.instance(processingEnvironment);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) {
ASTUtils.setRootElements(roundEnv.getRootElements());
for (final Element element : roundEnv.getRootElements()) {
CompilationUnitTree compilationUnit = trees.getPath(element).getCompilationUnit();
for (TreeScanner<?, Trees> scanner : scanners) {
scanner.scan(compilationUnit, trees);
}
}
}
return true;
}
}
就我而言,我将它们存储在一个辅助类 ASTUtils 中:
public class ASTUtils {
private static Set<? extends Element> rootElements = new HashSet<>();
public static Set<? extends Element> getRootElements() {
return rootElements;
}
public static void setRootElements(Set<? extends Element> rootElements) {
ASTUtils.rootElements = rootElements;
}
}
然后你可以确定TreePath:
public static TreePath find(Tree tree, Trees trees) {
for (Element e : ASTUtils.getRootElements()) {
CompilationUnitTree compilationUnit = trees.getPath(e).getCompilationUnit();
TreePath path = TreePath.getPath(compilationUnit, tree);
if (path != null) {
Tree classTree = trees.getTree(trees.getElement(path));
if (classTree != null && classTree.getKind() == kind) {
return path;
}
}
}
return null;
}
现在可以使用超类的 TreePath 来获取对应的 CompilationUnitTree 并读取包或获取 TypeElement 并读取限定名称(参见之前的答案/初始帖子)。