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.TokenTypes;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public final class JavadocEmptyLineCheck extends AbstractCheck {
34
35 @Override
36 public int[] getDefaultTokens() {
37 return new int[] {
38 TokenTypes.PACKAGE_DEF,
39 TokenTypes.CLASS_DEF,
40 TokenTypes.INTERFACE_DEF,
41 TokenTypes.ANNOTATION_DEF,
42 TokenTypes.ANNOTATION_FIELD_DEF,
43 TokenTypes.ENUM_DEF,
44 TokenTypes.ENUM_CONSTANT_DEF,
45 TokenTypes.VARIABLE_DEF,
46 TokenTypes.CTOR_DEF,
47 TokenTypes.METHOD_DEF,
48 };
49 }
50
51 @Override
52 public int[] getAcceptableTokens() {
53 return this.getDefaultTokens();
54 }
55
56 @Override
57 public int[] getRequiredTokens() {
58 return this.getDefaultTokens();
59 }
60
61 @Override
62 public void visitToken(final DetailAST ast) {
63 final String[] lines = this.getLines();
64 final int current = ast.getLineNo();
65 final int start =
66 JavadocEmptyLineCheck.findCommentStart(lines, current) + 1;
67 if (JavadocEmptyLineCheck.isNodeHavingJavadoc(ast, start)
68 && start < lines.length) {
69 if (JavadocEmptyLineCheck.isJavadocLineEmpty(lines[start])) {
70 this.log(start + 1, "Empty Javadoc line at the beginning");
71 }
72 final int end =
73 JavadocEmptyLineCheck.findCommentEnd(lines, current) - 1;
74 if (end >= start
75 && JavadocEmptyLineCheck.isJavadocLineEmpty(lines[end])) {
76 this.log(end + 1, "Empty Javadoc line at the end");
77 }
78 for (int pos = start + 1; pos <= end; pos += 1) {
79 if (JavadocEmptyLineCheck.isJavadocLineEmpty(lines[pos])
80 && JavadocEmptyLineCheck.isJavadocLineEmpty(lines[pos - 1])
81 ) {
82 this.log(pos + 1, "Two consecutive empty Javadoc lines");
83 }
84 }
85 }
86 }
87
88
89
90
91
92
93 private static boolean isJavadocLineEmpty(final String line) {
94 return "*".equals(line.trim());
95 }
96
97
98
99
100
101
102
103 private static boolean isNodeHavingJavadoc(final DetailAST node,
104 final int start) {
105 return start > getLineNoOfPreviousNode(node);
106 }
107
108
109
110
111
112
113 private static int getLineNoOfPreviousNode(final DetailAST node) {
114 int start = 0;
115 final DetailAST previous = node.getPreviousSibling();
116 if (previous != null) {
117 start = previous.getLineNo();
118 }
119 return start;
120 }
121
122
123
124
125
126
127
128 private static int findCommentStart(final String[] lines, final int start) {
129 return JavadocEmptyLineCheck.findTrimmedTextUp(lines, start, "/**");
130 }
131
132
133
134
135
136
137
138 private static int findCommentEnd(final String[] lines, final int start) {
139 int found = -1;
140 for (int pos = start - 1; pos >= 0; pos -= 1) {
141 final String trimmed = lines[pos].trim();
142 if ("*/".equals(trimmed) || "**/".equals(trimmed)) {
143 found = pos;
144 break;
145 }
146 }
147 return found;
148 }
149
150
151
152
153
154
155
156
157 private static int findTrimmedTextUp(final String[] lines,
158 final int start, final String text) {
159 int found = -1;
160 for (int pos = start - 1; pos >= 0; pos -= 1) {
161 if (lines[pos].trim().equals(text)) {
162 found = pos;
163 break;
164 }
165 }
166 return found;
167 }
168 }