在 Java 注释处理器中,我使用
DocTrees#getDocCommentTree(Element)
来获取 DocCommentTree
,我与访客一起走过它。为找到的 visitLink(LinkTree,C)
令牌调用访问者的
{@link
方法。对于
{@link Foo}
,LinkTree#getReference().getSignature()
返回 Foo
,尽管它不会提供完全限定的类名。也就是说,是java.lang.Foo
吗?是Foo
在同一个包裹里吗?是导入了一些 Foo
类吗?在解析 Javadoc 中的链接时如何获取参考文献的完全限定名称?
在注释处理器中解析Javadoc时,我们可以首先创建一个
ImportTree
,并用它来确定ReferenceTree
返回的LinkTree#getReference()
的FQCN,即{@link signature label}
中的FQCN。我已经在 this commit中为
log4j-docgen
实现了这个。伪代码如下:
public class ExampleProcessor extends AbstractProcessor {
private DocTrees docTrees;
private Trees trees;
@Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
super.init(processingEnv);
docTrees = DocTrees.instance(processingEnv);
trees = Trees.instance(processingEnv);
}
private void scanDocTree(Element element) {
Map<String, String> imports = collectElementImports(element);
ExampleContext context = new ExampleContext(imports);
DocCommentTree tree = docTrees.getDocCommentTree(element);
ExampleDocTreeVisitor visitor = new ExampleDocTreeVisitor();
tree.accept(visitor, context);
}
private static final class ExampleDocTreeVisitor<Void, ExampleContext>
extends SimpleDocTreeVisitor<Void, ExampleContext> {
@Override
public Void visitLink(LinkTree linkTree, final ExampleContext context) {
String signature = linkTree.getReference().getSignature();
String fqcn = context.imports.get(signature);
// ...
return super.visitLink(node, data);
}
}
private Map<String, String> collectElementImports(Element element) {
ImportCollectingTreeScanner scanner = new ImportCollectingTreeScanner();
TreePath treePath = trees.getPath(element);
scanner.scan(treePath.getCompilationUnit(), null);
return scanner.imports;
}
private static final class ImportCollectingScanner
extends TreeScanner<Object, Trees> {
private final Map<String, String> imports = new HashMap<>();
@Override
public Object visitImport(ImportTree importTree, Trees trees) {
Tree qualifiedIdentifier = importTree.getQualifiedIdentifier();
String qualifiedClassName = qualifiedIdentifier.toString();
String simpleClassName = qualifiedClassName.substring(qualifiedClassName.lastIndexOf('.') + 1);
imports.put(simpleClassName, qualifiedClassName);
return super.visitImport(importTree, trees);
}
}
}
ImportTree
提示ImportTree