1
2
3
4
5 package com.qulice.checkstyle;
6
7 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8 import com.puppycrawl.tools.checkstyle.api.DetailAST;
9 import com.puppycrawl.tools.checkstyle.api.TextBlock;
10 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
11 import java.util.Locale;
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 public final class JavadocStrayAsteriskCheck extends AbstractCheck {
48
49
50
51
52 public JavadocStrayAsteriskCheck() {
53
54 }
55
56 @Override
57 public int[] getDefaultTokens() {
58 return new int[] {
59 TokenTypes.PACKAGE_DEF,
60 TokenTypes.CLASS_DEF,
61 TokenTypes.INTERFACE_DEF,
62 TokenTypes.ANNOTATION_DEF,
63 TokenTypes.ANNOTATION_FIELD_DEF,
64 TokenTypes.ENUM_DEF,
65 TokenTypes.ENUM_CONSTANT_DEF,
66 TokenTypes.VARIABLE_DEF,
67 TokenTypes.CTOR_DEF,
68 TokenTypes.METHOD_DEF,
69 };
70 }
71
72 @Override
73 public int[] getAcceptableTokens() {
74 return this.getDefaultTokens();
75 }
76
77 @Override
78 public int[] getRequiredTokens() {
79 return this.getDefaultTokens();
80 }
81
82 @Override
83 @SuppressWarnings("deprecation")
84 public void visitToken(final DetailAST ast) {
85 final TextBlock doc =
86 this.getFileContents().getJavadocBefore(ast.getLineNo());
87 if (doc != null) {
88 this.check(doc);
89 }
90 }
91
92 private void check(final TextBlock doc) {
93 final String[] lines = doc.getText();
94 boolean pre = false;
95 int depth = 0;
96 for (int pos = 0; pos < lines.length; pos += 1) {
97 final String body = JavadocStrayAsteriskCheck.body(lines[pos]);
98 final String low = body.toLowerCase(Locale.ENGLISH);
99 if (depth > 0) {
100 depth += JavadocStrayAsteriskCheck.braces(body);
101 } else if (low.contains("{@snippet")) {
102 depth = Math.max(0, JavadocStrayAsteriskCheck.braces(body));
103 } else if (pre) {
104 pre = !low.contains("</pre>");
105 } else if (low.contains("<pre>")) {
106 pre = !low.contains("</pre>");
107 } else if (body.endsWith("*")) {
108 this.log(
109 doc.getStartLineNo() + pos,
110 "Javadoc line must not end with a stray asterisk"
111 );
112 }
113 }
114 }
115
116 private static String body(final String line) {
117 String trimmed = line.trim();
118 if (trimmed.endsWith("*/")) {
119 trimmed = trimmed.substring(0, trimmed.length() - 2).trim();
120 }
121 if (trimmed.startsWith("/**")) {
122 trimmed = trimmed.substring(3).trim();
123 } else if (trimmed.startsWith("*")) {
124 trimmed = trimmed.substring(1).trim();
125 }
126 return trimmed;
127 }
128
129 private static int braces(final String body) {
130 int delta = 0;
131 for (int pos = 0; pos < body.length(); pos += 1) {
132 final char chr = body.charAt(pos);
133 if (chr == '{') {
134 delta += 1;
135 } else if (chr == '}') {
136 delta -= 1;
137 }
138 }
139 return delta;
140 }
141 }