3

In a Java annotation processor, I use DocTrees#getDocCommentTree(Element) to obtain a DocCommentTree, which I walk over with a visitor. Visitor's visitLink(LinkTree,C) method is invoked for found {@link tokens. For a {@link Foo}, LinkTree#getReference().getSignature() returns Foo, though it doesn't give you the fully-qualified class name. That is, is it java.lang.Foo? Is it Foo in the same package? Is it some Foo class imported? How can I get the fully qualified name of the reference while parsing links in Javadoc?

5
  • It means the current package. Commented Mar 8, 2024 at 21:09
  • Did you mean to link to Processor and DocTreeVisitor.visitLink? Log4J source code doesn’t seem like a useful reference. Commented Mar 9, 2024 at 17:17
  • @user207421, no, it doesn't necessary mean the current package. If you import com.foo.Bar, you can link to it using {@link Bar}. Commented Mar 10, 2024 at 19:30
  • @VGR, it is not an arbitrary piece of code I referenced, it is the Log4j Tools code base I am working on, hence the link. (See my name in the commits there.) Commented Mar 10, 2024 at 19:31
  • I see. I believe the answer is that import statements which don’t end with an asterisk take precedence over everything else. If no import statement specifies the class name, the doclet will look in the same package as the referencing class. Commented Mar 10, 2024 at 19:55

1 Answer 1

1

While parsing Javadoc in an annotation processor, we can first create an ImportTree and use it to determine the FQCN of a ReferenceTree returned by LinkTree#getReference(), that is, the FQCN in {@link signature label}. I have already implemented this for log4j-docgen in this commit. The pseudo-code is as follows:

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);
        }

    }

}

Credits

  • @piotr-p-karwasz for the ImportTree hint
  • Andi's blog on how to extract ImportTree in an annotation processor
Sign up to request clarification or add additional context in comments.

1 Comment

DocTrees extends Trees, so you can use a single field in your example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.