Skip to content

Commit 3482231

Browse files
committed
Checkstyle rule for @SInCE on private classes
Update `SpringJavadocCheck` to optionally support checking that `@since` is not used on private classes. Closes gh-129
1 parent 5f1e007 commit 3482231

File tree

6 files changed

+100
-11
lines changed

6 files changed

+100
-11
lines changed

spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJavadocCheck.java

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@
3030
*/
3131
public class SpringJavadocCheck extends AbstractSpringCheck {
3232

33-
private static final Pattern[] PATTERNS = { Pattern.compile("@param\\s+\\S+\\s+(.*)"),
33+
private static final Pattern[] CASE_CHECKED_TAG_PATTERNS = { Pattern.compile("@param\\s+\\S+\\s+(.*)"),
3434
Pattern.compile("@throws\\s+\\S+\\s+(.*)"), Pattern.compile("@return\\s+(.*)") };
3535

36+
private static final Pattern SINCE_TAG_PATTERN = Pattern.compile("@since\\s+(.*)");
37+
38+
private boolean publicOnlySinceTags;
39+
3640
@Override
3741
public int[] getDefaultTokens() {
3842
return new int[] { TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF,
@@ -51,27 +55,63 @@ public void visitToken(DetailAST ast) {
5155
int lineNumber = ast.getLineNo();
5256
TextBlock javadoc = getFileContents().getJavadocBefore(lineNumber);
5357
if (javadoc != null) {
54-
checkParamTags(javadoc);
58+
checkParamTags(ast, javadoc);
5559
}
5660
}
5761

58-
private void checkParamTags(TextBlock javadoc) {
62+
private void checkParamTags(DetailAST ast, TextBlock javadoc) {
5963
String[] text = javadoc.getText();
6064
for (int i = 0; i < text.length; i++) {
61-
for (Pattern pattern : PATTERNS) {
62-
Matcher matcher = pattern.matcher(text[i]);
63-
if (matcher.find()) {
64-
String description = matcher.group(1).trim();
65-
if (startsWithUppercase(description)) {
66-
log(javadoc.getStartLineNo() + i, text[i].length() - description.length(), "javadoc.badCase");
67-
}
65+
String line = text[i];
66+
int lineNumber = javadoc.getStartLineNo() + i;
67+
checkCase(line, lineNumber);
68+
checkSinceTag(ast, line, lineNumber);
69+
}
70+
}
71+
72+
private void checkCase(String line, int lineNumber) {
73+
for (Pattern pattern : CASE_CHECKED_TAG_PATTERNS) {
74+
Matcher matcher = pattern.matcher(line);
75+
if (matcher.find()) {
76+
String description = matcher.group(1).trim();
77+
if (startsWithUppercase(description)) {
78+
log(lineNumber, line.length() - description.length(), "javadoc.badCase");
79+
}
80+
}
81+
}
82+
}
83+
84+
private void checkSinceTag(DetailAST ast, String line, int lineNumber) {
85+
if (this.publicOnlySinceTags) {
86+
Matcher matcher = SINCE_TAG_PATTERN.matcher(line);
87+
if (matcher.find()) {
88+
String description = matcher.group(1).trim();
89+
DetailAST classDef = getClassDef(ast);
90+
DetailAST classModifiers = classDef.findFirstToken(TokenTypes.MODIFIERS);
91+
if (classModifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) == null
92+
&& classModifiers.findFirstToken(TokenTypes.LITERAL_PROTECTED) == null) {
93+
log(lineNumber, line.length() - description.length(), "javadoc.publicSince");
6894
}
6995
}
7096
}
7197
}
7298

99+
private DetailAST getClassDef(DetailAST ast) {
100+
while (ast != null) {
101+
if (ast.getType() == TokenTypes.CLASS_DEF) {
102+
return ast;
103+
}
104+
ast = ast.getParent();
105+
}
106+
return null;
107+
}
108+
73109
private boolean startsWithUppercase(String description) {
74110
return description.length() > 0 && Character.isUpperCase(description.charAt(0));
75111
}
76112

113+
public void setPublicOnlySinceTags(boolean publicOnlySinceTags) {
114+
this.publicOnlySinceTags = publicOnlySinceTags;
115+
}
116+
77117
}

spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ternary.missingParen=Ternary operation missing parentheses.
55
ternary.equalOperator=Ternary operation should use != when testing.
66
catch.singleLetter=Single letter catch variable (use "ex" instead).
77
javadoc.badCase=Javadoc element descriptions should not start with an uppercase letter.
8+
javadoc.publicSince=Javadoc @since tag should not be used on private classes.
89
header.unexpected=Unexpected header.
910
nothis.unexpected=Reference to instance variable ''{0}'' should not use \"this.\".
1011
methodorder.outOfOrder=Method ''{0}'' is out of order, expected {1}.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
+JavadocNonPublicSince.java:21:11: Javadoc @since tag should not be used on private classes. [SpringJavadoc]
2+
+JavadocNonPublicSince.java:28:19: Javadoc @since tag should not be used on private classes. [SpringJavadoc]
3+
+2 errors
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0"?>
2+
<!DOCTYPE module PUBLIC
3+
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
4+
"https://checkstyle.org/dtds/configuration_1_3.dtd">
5+
<module name="com.puppycrawl.tools.checkstyle.Checker">
6+
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
7+
<module name="io.spring.javaformat.checkstyle.check.SpringJavadocCheck">
8+
<property name="publicOnlySinceTags" value="true"/>
9+
</module>
10+
</module>
11+
</module>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2017-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Javadoc with a bad since tag.
19+
*
20+
* @author Phillip Webb
21+
* @since 1.2.3
22+
*/
23+
class JavadocNonPublicSince {
24+
25+
/**
26+
* Inner class.
27+
*
28+
* @since 1.2.3
29+
*/
30+
private static class Inner {
31+
32+
}
33+
34+
}

spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JavadocValid.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
/**
18-
* Javadoc with a bad author tag.
18+
* Valid Javadoc.
1919
*
2020
* @param <T> this is a valid param
2121
* @author Phillip Webb

0 commit comments

Comments
 (0)