JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/JavadocParser.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 The JavaParser Team.
4 *
5 * This file is part of JavaParser.
6 *
7 * JavaParser can be used either under the terms of
8 * a) the GNU Lesser General Public License as published by
9 *     the Free Software Foundation, either version 3 of the License, or
10 *     (at your option) any later version.
11 * b) the terms of the Apache License
12 *
13 * You should have received a copy of both licenses in LICENCE.LGPL and
14 * LICENCE.APACHE. Please refer to those files for details.
15 *
16 * JavaParser is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 */
21
22package com.github.javaparser;
23
24import com.github.javaparser.ast.comments.JavadocComment;
25import com.github.javaparser.javadoc.Javadoc;
26import com.github.javaparser.javadoc.JavadocBlockTag;
27import com.github.javaparser.javadoc.description.JavadocDescription;
28import java.util.Arrays;
29import java.util.Collections;
30import java.util.List;
31import java.util.regex.Pattern;
32import java.util.stream.Collectors;
33
34import static com.github.javaparser.utils.Utils.*;
35
36/**
37 * The class responsible for parsing the content of JavadocComments and producing JavadocDocuments.
38 * <a href="https://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javadoc.html">The Javadoc specification.</a>
39 */
40class JavadocParser {
41
42    private static String BLOCK_TAG_PREFIX = "@";
43    private static Pattern BLOCK_PATTERN = Pattern.compile("^\\s*" + BLOCK_TAG_PREFIXPattern.MULTILINE);
44
45    public static Javadoc parse(JavadocComment comment) {
46        return parse(comment.getContent());
47    }
48
49    public static Javadoc parse(String commentContent) {
50        List<StringcleanLines = cleanLines(normalizeEolInTextBlock(commentContentSYSTEM_EOL));
51        int indexOfFirstBlockTag = cleanLines.stream()
52                .filter(JavadocParser::isABlockLine)
53                .map(cleanLines::indexOf)
54                .findFirst()
55                .orElse(-1);
56        List<StringblockLines;
57        String descriptionText;
58        if (indexOfFirstBlockTag == -1) {
59            descriptionText = trimRight(String.join(SYSTEM_EOLcleanLines));
60            blockLines = Collections.emptyList();
61        } else {
62            descriptionText = trimRight(String.join(SYSTEM_EOLcleanLines.subList(0indexOfFirstBlockTag)));
63
64            //Combine cleaned lines, but only starting with the first block tag till the end
65            //In this combined string it is easier to handle multiple lines which actually belong together
66            String tagBlock = cleanLines.subList(indexOfFirstBlockTagcleanLines.size())
67                .stream()
68                .collect(Collectors.joining(SYSTEM_EOL));
69
70            //Split up the entire tag back again, considering now that some lines belong to the same block tag.
71            //The pattern splits the block at each new line starting with the '@' symbol, thus the symbol
72            //then needs to be added again so that the block parsers handles everything correctly.
73            blockLines = BLOCK_PATTERN
74                .splitAsStream(tagBlock)
75                .filter(s1 -> !s1.isEmpty())
76                .map(s -> BLOCK_TAG_PREFIX + s)
77                .collect(Collectors.toList());
78        }
79        Javadoc document = new Javadoc(JavadocDescription.parseText(descriptionText));
80        blockLines.forEach(l -> document.addBlockTag(parseBlockTag(l)));
81        return document;
82    }
83
84    private static JavadocBlockTag parseBlockTag(String line) {
85        line = line.trim().substring(1);
86        String tagName = nextWord(line);
87        String rest = line.substring(tagName.length()).trim();
88        return new JavadocBlockTag(tagNamerest);
89    }
90
91    private static boolean isABlockLine(String line) {
92        return line.trim().startsWith(BLOCK_TAG_PREFIX);
93    }
94
95    private static String trimRight(String string) {
96        while (!string.isEmpty() && Character.isWhitespace(string.charAt(string.length() - 1))) {
97            string = string.substring(0string.length() - 1);
98        }
99        return string;
100    }
101
102    private static List<StringcleanLines(String content) {
103        String[] lines = content.split(SYSTEM_EOL);
104        if (lines.length == 0) {
105            return Collections.emptyList();
106        }
107
108        List<StringcleanedLines = Arrays.stream(lines).map(l -> {
109            int asteriskIndex = startsWithAsterisk(l);
110            if (asteriskIndex == -1) {
111                return l;
112            } else {
113                // if a line starts with space followed by an asterisk drop to the asterisk
114                // if there is a space immediately after the asterisk drop it also
115                if (l.length() > (asteriskIndex + 1)) {
116
117                    char c = l.charAt(asteriskIndex + 1);
118                    if (c == ' ' || c == '\t') {
119                        return l.substring(asteriskIndex + 2);
120                    }
121                }
122                return l.substring(asteriskIndex + 1);
123            }
124        }).collect(Collectors.toList());
125        // lines containing only whitespace are normalized to empty lines
126        cleanedLines = cleanedLines.stream().map(l -> l.trim().isEmpty() ? "" : l).collect(Collectors.toList());
127        // if the first starts with a space, remove it
128        if (!cleanedLines.get(0).isEmpty() && (cleanedLines.get(0).charAt(0) == ' ' || cleanedLines.get(0).charAt(0) == '\t')) {
129            cleanedLines.set(0cleanedLines.get(0).substring(1));
130        }
131        // drop empty lines at the beginning and at the end
132        while (cleanedLines.size() > 0 && cleanedLines.get(0).trim().isEmpty()) {
133            cleanedLines = cleanedLines.subList(1cleanedLines.size());
134        }
135        while (cleanedLines.size() > 0 && cleanedLines.get(cleanedLines.size() - 1).trim().isEmpty()) {
136            cleanedLines = cleanedLines.subList(0cleanedLines.size() - 1);
137        }
138        return cleanedLines;
139    }
140
141    // Visible for testing
142    static int startsWithAsterisk(String line) {
143        if (line.startsWith("*")) {
144            return 0;
145        } else if ((line.startsWith(" ") || line.startsWith("\t")) && line.length() > 1) {
146            int res = startsWithAsterisk(line.substring(1));
147            if (res == -1) {
148                return -1;
149            } else {
150                return 1 + res;
151            }
152        } else {
153            return -1;
154        }
155    }
156}
157
MembersX
JavadocParser:parse:Block:descriptionText
JavadocParser:BLOCK_PATTERN
JavadocParser:parseBlockTag:Block:tagName
JavadocParser:parse:Block:indexOfFirstBlockTag
JavadocParser:parseBlockTag
JavadocParser:cleanLines:Block:cleanedLines
JavadocParser:startsWithAsterisk:Block:Block:res
JavadocParser:parseBlockTag:Block:rest
JavadocParser:cleanLines:Block:Block:asteriskIndex
JavadocParser:parse:Block:Block:tagBlock
JavadocParser:parse:Block:blockLines
JavadocParser:cleanLines:Block:lines
JavadocParser:isABlockLine
JavadocParser:parse:Block:document
JavadocParser:parse
JavadocParser:trimRight
JavadocParser:BLOCK_TAG_PREFIX
JavadocParser:cleanLines:Block:Block:Block:Block:c
JavadocParser:startsWithAsterisk
JavadocParser:cleanLines
JavadocParser:parse:Block:cleanLines
Members
X