Javaparser Goodness II - Find undocumented interfaces!
Mar 10, 2017
2 minute read

Good documentation is essential not only for open source software. It is often a criteria in picking the right library/framework for companies. So documenting your interfaces should be equally prioritised as writting readable code. Javaparser can help you with this task. Not by writing the documentation for us :), but to find undocumented interfaces for instance.

Javaparser lets us define visitors where we can hook up into different parts of our source code, for example into class or interface declarations. We define two visitors as inner classes. One visits ClassOrInterfaceDeclaration’s and checks for javadoc if it is a public interface. The other visits methods and checks there for javadoc comments.

private class InterfaceVisitor extends VoidVisitorAdapter<CompilationUnit> {
    @Override
    public void visit(ClassOrInterfaceDeclaration n, CompilationUnit arg) {
        if (n.isInterface()) {
            if (n.getModifiers().contains(Modifier.PUBLIC)) {
                String packageName = arg.getPackageDeclaration()
                        .map(NodeWithName::getNameAsString)
                        .orElse("<default>");
                if (!n.getJavadocComment().isPresent()) {
                    Out.println(packageName + "." + n.getNameAsString() + " at " +
                            n.getRange().map(Range::toString).orElse("-1/-1") + " misses javadoc!");
                }
                InterfaceMethodVisitor visitor = new InterfaceMethodVisitor(packageName);
                n.accept(visitor, n);
            }
        }
        super.visit(n, arg);
    }
}

private class InterfaceMethodVisitor extends VoidVisitorAdapter<ClassOrInterfaceDeclaration> {
    private String packageName;

    public InterfaceMethodVisitor(String packageName) {
        this.packageName = packageName;
    }

    @Override
    public void visit(MethodDeclaration n, ClassOrInterfaceDeclaration arg) {
        if (!n.getJavadocComment().isPresent()) {
            String signature = packageName + "." + arg.getNameAsString() + "#" + n.getDeclarationAsString();
            Out.println(signature + " at " + n.getRange().map(Range::toString).orElse("-1/-1") + " misses javadoc!");
        }
        super.visit(n, arg);
    }
}

The main method looks a bit different this time. I extracted all the parsing and validation code into a new Inspection class. TEMPLATE is a TriConsumer (see Consumer, BiConsumer) which takes care of the argument vector and inner validation.

public class InterfaceDocumentation {

    public static void main(String[] args) throws IOException {
        Inspection.TEMPLATE.accept(args, /*saveModification*/false,
                sourceRoot -> new InterfaceDocumentation().run(sourceRoot.getCompilationUnits()));
    }

    private void run(List<CompilationUnit> units) {
        InterfaceVisitor visitor = new InterfaceVisitor();
        units.forEach(unit -> unit.accept(visitor, unit));
    }
...
}

Check out the whole javaparser-goodness project on github.