Статьи

Извлечение документации JavaDoc из исходных файлов с использованием JavaParser

Многие люди используют JavaParser для самых разных целей. Одним из них является извлечение документации. В этом коротком посте мы увидим, как вы можете распечатать все комментарии JavaDoc, связанные с классами или интерфейсами.

Код доступен на GitHub: https://github.com/ftomassetti/javadoc-extractor

Получение всех комментариев Javadoc для классов

Мы повторно используем DirExplorer , вспомогательный класс, представленный во введении к JavaParser . Этот класс позволяет рекурсивно обрабатывать каталог, анализируя все содержащиеся в нем файлы Java.

Мы можем начать с перебора всех классов и найти соответствующие комментарии Javadoc.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * Iterate over the classes and print their Javadoc.
 */
public class ClassesJavadocExtractor {
  
    public static void main(String[] args) {
        File projectDir = new File("source_to_parse/");
        new DirExplorer((level, path, file) -> path.endsWith(".java"), (level, path, file) -> {
            try {
                new VoidVisitorAdapter<Object>() {
                    @Override
                    public void visit(ClassOrInterfaceDeclaration n, Object arg) {
                        super.visit(n, arg);
                        if (n.getComment() != null && n.getComment() instanceof JavadocComment) {
                            String title = String.format("%s (%s)", n.getName(), path);
                            System.out.println(title);
                            System.out.println(Strings.repeat("=", title.length()));
                            System.out.println(n.getComment());
                        }
                    }
                }.visit(JavaParser.parse(file), null);
            } catch (IOException e) {
                new RuntimeException(e);
            }
        }).explore(projectDir);
    }
  
}

Как видите, получить комментарии к JavaDoc довольно просто. Это дает такой результат:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ASTParserConstants (/javaparser/javaparser-core/target/generated-sources/javacc/com/github/javaparser/ASTParserConstants.java)
==============================================================================================================================
/**
 * Token literal values and constants.
 * Generated by org.javacc.parser.OtherFilesGen#start()
 */
  
ParseException (/javaparser/javaparser-core/target/generated-sources/javacc/com/github/javaparser/ParseException.java)
======================================================================================================================
/**
 * This exception is thrown when parse errors are encountered.
 * You can explicitly create objects of this exception type by
 * calling the method generateParseException in the generated
 * parser.
 *
 * You can modify this class to customize your error reporting
 * mechanisms so long as you retain the public fields.
 */
  
ASTParser (/javaparser/javaparser-core/target/generated-sources/javacc/com/github/javaparser/ASTParser.java)
============================================================================================================
/**
 *
This class was generated automatically by javacc, do not edit.
 
*/ ASTParserTokenManager (/javaparser/javaparser-core/target/generated-sources/javacc/com/github/javaparser/ASTParserTokenManager.java) ==================================================================================================================================== /** Token Manager. */

Получение всех комментариев Javadoc и поиск документированных элементов.

В других случаях мы можем начать собирать все комментарии Javadoc и затем найти элемент, который комментируется. Мы также можем сделать это легко с Javaparser:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * Iterate over all the Javadoc comments and print them together with a description of the commented element.
 */
public class AllJavadocExtractor {
  
    public static void main(String[] args) {
        File projectDir = new File("source_to_parse/");
        new DirExplorer((level, path, file) -> path.endsWith(".java"), (level, path, file) -> {
            try {
                new VoidVisitorAdapter<Object>() {
                    @Override
                    public void visit(JavadocComment comment, Object arg) {
                        super.visit(comment, arg);
                        String title = null;
                        if (comment.getCommentedNode().isPresent()) {
                            title = String.format("%s (%s)", describe(comment.getCommentedNode().get()), path);
                        } else {
                            title = String.format("No element associated (%s)", path);
                        }
                        System.out.println(title);
                        System.out.println(Strings.repeat("=", title.length()));
                        System.out.println(comment);
                    }
                }.visit(JavaParser.parse(file), null);
            } catch (IOException e) {
                new RuntimeException(e);
            }
        }).explore(projectDir);
    }
  
    private static String describe(Node node) {
        if (node instanceof MethodDeclaration) {
            MethodDeclaration methodDeclaration = (MethodDeclaration)node;
            return "Method " + methodDeclaration.getDeclarationAsString();
        }
        if (node instanceof ConstructorDeclaration) {
            ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)node;
            return "Constructor " + constructorDeclaration.getDeclarationAsString();
        }
        if (node instanceof ClassOrInterfaceDeclaration) {
            ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration)node;
            if (classOrInterfaceDeclaration.isInterface()) {
                return "Interface " + classOrInterfaceDeclaration.getName();
            } else {
                return "Class " + classOrInterfaceDeclaration.getName();
            }
        }
        if (node instanceof EnumDeclaration) {
            EnumDeclaration enumDeclaration = (EnumDeclaration)node;
            return "Enum " + enumDeclaration.getName();
        }
        if (node instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration = (FieldDeclaration)node;
            List<String> varNames = fieldDeclaration.getVariables().stream().map(v -> v.getName().getId()).collect(Collectors.toList());
            return "Field " + String.join(", ", varNames);
        }
        return node.toString();
    }
  
}

Здесь большая часть кода посвящена описанию закомментированного узла (метод description).

Выводы

Управлять AST и найти комментарии Javadoc довольно легко. Однако одной отсутствующей функцией является возможность извлекать информацию, содержащуюся в Javadoc, в структурированной форме. Например, вы можете получить только часть Javadoc, связанную с определенным параметром или возвращаемым значением. Javaparser в настоящее время не имеет этой функции, но я работаю над ней, и она должна быть объединена в ближайшие 1-2 недели. Если вы хотите следить за развитием, взгляните на вопрос 433 .

Спасибо за чтение и счастливого разбора!