1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.site;
21
22 import java.util.Optional;
23 import java.util.Set;
24 import java.util.regex.Pattern;
25
26 import org.apache.maven.doxia.macro.MacroExecutionException;
27 import org.apache.maven.doxia.sink.Sink;
28
29 import com.puppycrawl.tools.checkstyle.api.DetailNode;
30 import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
31 import com.puppycrawl.tools.checkstyle.meta.JavadocMetadataScraper;
32 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
33
34
35
36
37 public final class ModuleJavadocParsingUtil {
38
39 public static final String NEWLINE = System.lineSeparator();
40
41 public static final String INDENT_LEVEL_8 = SiteUtil.getNewlineAndIndentSpaces(8);
42
43 public static final String INDENT_LEVEL_10 = SiteUtil.getNewlineAndIndentSpaces(10);
44
45 public static final String INDENT_LEVEL_12 = SiteUtil.getNewlineAndIndentSpaces(12);
46
47 public static final String INDENT_LEVEL_14 = SiteUtil.getNewlineAndIndentSpaces(14);
48
49 public static final String INDENT_LEVEL_16 = SiteUtil.getNewlineAndIndentSpaces(16);
50
51 public static final String INDENT_LEVEL_18 = SiteUtil.getNewlineAndIndentSpaces(18);
52
53 public static final String INDENT_LEVEL_20 = SiteUtil.getNewlineAndIndentSpaces(20);
54
55 public static final Set<String> HTML_TEXT_FORMAT_TAGS = Set.of("<code>", "<a", "</a>", "<b>",
56 "</b>", "<strong>", "</strong>", "<i>", "</i>", "<em>", "</em>", "<small>", "</small>",
57 "<ins>", "<sub>", "<sup>");
58
59 public static final String NOTES = "Notes:";
60
61 public static final Pattern NOTES_LINE = Pattern.compile("\\s*" + NOTES + "$");
62
63
64
65
66 private ModuleJavadocParsingUtil() {
67 }
68
69
70
71
72
73
74
75
76 public static Set<String> getPropertyNames(String moduleName)
77 throws MacroExecutionException {
78 final Object instance = SiteUtil.getModuleInstance(moduleName);
79 final Class<?> clss = instance.getClass();
80
81 return SiteUtil.getPropertiesForDocumentation(clss, instance);
82 }
83
84
85
86
87
88
89
90 public static int getParentSectionStartIndex(DetailNode moduleJavadoc) {
91 int parentStartIndex = -1;
92
93 for (DetailNode node : moduleJavadoc.getChildren()) {
94 if (node.getType() == JavadocTokenTypes.HTML_ELEMENT) {
95 final DetailNode paragraphNode = JavadocUtil.findFirstToken(
96 node, JavadocTokenTypes.PARAGRAPH);
97 if (paragraphNode != null && JavadocMetadataScraper.isParentText(paragraphNode)) {
98 parentStartIndex = node.getIndex();
99 break;
100 }
101 }
102 }
103
104 return parentStartIndex;
105 }
106
107
108
109
110
111
112
113 public static int getNotesSectionStartIndex(DetailNode moduleJavadoc) {
114 int notesStartIndex = -1;
115
116 for (DetailNode node : moduleJavadoc.getChildren()) {
117 if (node.getType() == JavadocTokenTypes.HTML_ELEMENT
118 && isStartOfNotesSection(node)) {
119
120 notesStartIndex += node.getIndex();
121 break;
122 }
123 }
124
125 return notesStartIndex;
126 }
127
128
129
130
131
132
133
134 private static boolean isStartOfNotesSection(DetailNode htmlElement) {
135 final DetailNode paragraphNode = JavadocUtil.findFirstToken(
136 htmlElement, JavadocTokenTypes.PARAGRAPH);
137 final Optional<DetailNode> liNode = getLiTagNode(htmlElement);
138
139 return paragraphNode != null && JavadocMetadataScraper.isChildNodeTextMatches(
140 paragraphNode, NOTES_LINE)
141 || liNode.isPresent() && JavadocMetadataScraper.isChildNodeTextMatches(
142 liNode.get(), NOTES_LINE);
143 }
144
145
146
147
148
149
150
151 public static Optional<DetailNode> getLiTagNode(DetailNode htmlElement) {
152 return Optional.of(htmlElement)
153 .map(element -> JavadocUtil.findFirstToken(element, JavadocTokenTypes.HTML_TAG))
154 .map(element -> JavadocUtil.findFirstToken(element, JavadocTokenTypes.HTML_ELEMENT))
155 .map(element -> JavadocUtil.findFirstToken(element, JavadocTokenTypes.LI));
156 }
157
158
159
160
161
162
163
164
165 public static int getPropertySectionStartIndex(DetailNode moduleJavadoc,
166 Set<String> propertyNames) {
167 int propertySectionStartIndex = -1;
168
169 final String somePropertyName = propertyNames.iterator().next();
170 final Optional<DetailNode> somePropertyModuleNode =
171 SiteUtil.getPropertyJavadocNodeInModule(somePropertyName, moduleJavadoc);
172
173 if (somePropertyModuleNode.isPresent()) {
174 propertySectionStartIndex = JavadocMetadataScraper.getParentIndexOf(
175 somePropertyModuleNode.get());
176 }
177
178 return propertySectionStartIndex;
179 }
180
181
182
183
184
185
186
187 public static void writeOutJavadocPortion(String javadocPortion, Sink sink) {
188 final String[] javadocPortionLinesSplit = javadocPortion.split(NEWLINE
189 .replace("\r", ""));
190
191 sink.rawText(javadocPortionLinesSplit[0]);
192 String lastHtmlTag = javadocPortionLinesSplit[0];
193
194 for (int index = 1; index < javadocPortionLinesSplit.length; index++) {
195 final String currentLine = javadocPortionLinesSplit[index].trim();
196 final String processedLine;
197
198 if (currentLine.isEmpty()) {
199 processedLine = NEWLINE;
200 }
201 else if (currentLine.startsWith("<")
202 && !startsWithTextFormattingHtmlTag(currentLine)) {
203
204 processedLine = INDENT_LEVEL_8 + currentLine;
205 lastHtmlTag = currentLine;
206 }
207 else if (lastHtmlTag.contains("<pre")) {
208 final String currentLineWithPreservedIndent = javadocPortionLinesSplit[index]
209 .substring(1);
210
211 processedLine = NEWLINE + currentLineWithPreservedIndent;
212 }
213 else {
214 processedLine = INDENT_LEVEL_10 + currentLine;
215 }
216
217 sink.rawText(processedLine);
218 }
219
220 }
221
222
223
224
225
226
227
228 public static boolean startsWithTextFormattingHtmlTag(String line) {
229 boolean result = false;
230
231 for (String tag : HTML_TEXT_FORMAT_TAGS) {
232 if (line.startsWith(tag)) {
233 result = true;
234 break;
235 }
236 }
237
238 return result;
239 }
240
241 }