【问题标题】:Java Compiler Tree API: Get fully qualified superclass nameJava Compiler Tree API:获取完全限定的超类名称
【发布时间】:2017-06-10 20:33:42
【问题描述】:

我正在尝试获取 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);
    }
}

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

谢谢

【问题讨论】:

  • 现在哪个部分对您来说似乎不是面向未来的?
  • 使用“toString”-方法。当然,“toString”方法将存在于未来的版本中。但是返回的 String 的语义和语法会一样吗?
  • 好的,那就看看getQualifiedName()吧。
  • getQualifiedName 可用于 TypeElement。但超类是 Tree 或 TypeMirror。

标签: java tree compiler-construction qualified


【解决方案1】:

怎么样

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

(借自here:))

【讨论】:

  • 谢谢,但我还必须使用 toString() 方法并分析输出。我想避免任何 toString() 方法。我希望有一种或多种方法可以合理记录和/或命名。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 2021-08-14
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    相关资源
    最近更新 更多