Skip to content

Commit 62c0962

Browse files
yegor256claude
andcommitted
#554: detect annotation placed above javadoc
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b0b924c commit 62c0962

3 files changed

Lines changed: 72 additions & 11 deletions

File tree

src/main/java/com/qulice/checkstyle/JavadocLocationCheck.java

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
1010

1111
/**
12-
* Checks that there is no empty line between a javadoc and it's subject.
12+
* Checks that there is no empty line between a javadoc and it's subject,
13+
* and that no annotation is placed above the javadoc.
1314
*
1415
* <p>You can't have empty lines between javadoc block and
1516
* a class/method/variable. They should stay together, always.
1617
*
18+
* <p>Annotations must be placed after the javadoc, not before it,
19+
* so that the javadoc stays next to the subject it describes.
20+
*
1721
* @since 0.3
1822
*/
1923
public final class JavadocLocationCheck extends AbstractCheck {
@@ -45,6 +49,16 @@ public void visitToken(final DetailAST ast) {
4549
return;
4650
}
4751
final String[] lines = this.getLines();
52+
this.checkEmptyLines(ast, lines);
53+
this.checkAnnotationAboveJavadoc(ast, lines);
54+
}
55+
56+
/**
57+
* Check that there are no empty lines between the javadoc and the subject.
58+
* @param ast The AST node of the subject
59+
* @param lines The file lines
60+
*/
61+
private void checkEmptyLines(final DetailAST ast, final String[] lines) {
4862
int current = ast.getLineNo();
4963
boolean found = false;
5064
--current;
@@ -63,23 +77,55 @@ public void visitToken(final DetailAST ast) {
6377
--current;
6478
}
6579
if (found) {
66-
this.report(ast.getLineNo(), current);
80+
final int diff = ast.getLineNo() - current;
81+
if (diff > 1) {
82+
for (int pos = 1; pos < diff; pos += 1) {
83+
this.log(
84+
current + pos,
85+
"Empty line between javadoc and subject"
86+
);
87+
}
88+
}
6789
}
6890
}
6991

7092
/**
71-
* Report empty lines between current and end line.
72-
* @param current Current line
73-
* @param end Final line
93+
* Check that no annotation is placed above the javadoc of the subject.
94+
* @param ast The AST node of the subject
95+
* @param lines The file lines
7496
*/
75-
private void report(final int current, final int end) {
76-
final int diff = current - end;
77-
if (diff > 1) {
78-
for (int pos = 1; pos < diff; pos += 1) {
97+
private void checkAnnotationAboveJavadoc(
98+
final DetailAST ast, final String[] lines
99+
) {
100+
final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
101+
if (modifiers == null) {
102+
return;
103+
}
104+
final DetailAST after = modifiers.getNextSibling();
105+
if (after == null) {
106+
return;
107+
}
108+
final int signature = after.getLineNo();
109+
int annotation = Integer.MAX_VALUE;
110+
DetailAST child = modifiers.getFirstChild();
111+
while (child != null) {
112+
if (child.getType() == TokenTypes.ANNOTATION
113+
&& child.getLineNo() < annotation) {
114+
annotation = child.getLineNo();
115+
}
116+
child = child.getNextSibling();
117+
}
118+
if (annotation == Integer.MAX_VALUE) {
119+
return;
120+
}
121+
for (int pos = annotation + 1; pos < signature; pos += 1) {
122+
final String line = lines[pos - 1].trim();
123+
if (line.startsWith("/**") || line.endsWith("*/")) {
79124
this.log(
80-
end + pos,
81-
"Empty line between javadoc and subject"
125+
annotation,
126+
"Annotation must be placed after Javadoc"
82127
);
128+
break;
83129
}
84130
}
85131
}

src/test/resources/com/qulice/checkstyle/ChecksTest/JavadocLocationCheck/Invalid.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,17 @@ public void method3() {
4848
interface I2 {
4949

5050
}
51+
52+
class C3 {
53+
@Override
54+
/**
55+
* Some Javadoc.
56+
*/
57+
public void close() {
58+
int a = 1;
59+
int b = 2;
60+
int c = 3;
61+
int d = 4;
62+
int e = 5;
63+
}
64+
}

src/test/resources/com/qulice/checkstyle/ChecksTest/JavadocLocationCheck/violations.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
24:Empty line between javadoc and subject
66
35:Empty line between javadoc and subject
77
43:Empty line between javadoc and subject
8+
53:Annotation must be placed after Javadoc

0 commit comments

Comments
 (0)