1

我正在尝试获取 ClassTree-Object 的超类的完全限定名称。目前我正在使用 toString() 方法:

public class ClassScanner extends TreePathScanner<Object, Trees> {

    @Override
    public Object visitClass(ClassTree ct, Trees trees) {
        TreePath currentPath = getCurrentPath();
        TypeElement typeElement = (TypeElement) trees.getElement(currentPath);
        String s = typeElement.getSuperclass().toString();
        System.out.println(s);
        return super.visitClass(ct, trees);
    }
}

但这似乎不是一种面向未来的方法。我还必须自己提取名称、包、泛型类型……。有替代方案吗?

谢谢

4

2 回答 2

0

怎么样

    Tree extendsClassTree = classTree.getExtendsClause();
    if (extendsClassTree != null) {
        superClassName = extendsClassTree.toString();
    } else {
        superClassName = "java.lang.Object";
    }

(从这里借来的:))

于 2017-06-09T10:23:52.367 回答
0

好的,我找到了解决方法:

在处理器中,将 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 并读取限定名称(参见之前的答案/初始帖子)。

于 2017-06-09T18:01:42.087 回答