Skip to content

Commit 5f1e007

Browse files
committed
Add method visibility checkstyle rule
closes gh-128
1 parent 5dc6bff commit 5f1e007

File tree

10 files changed

+227
-1
lines changed

10 files changed

+227
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
package io.spring.javaformat.checkstyle.check;
18+
19+
import com.puppycrawl.tools.checkstyle.api.DetailAST;
20+
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
21+
22+
/**
23+
* Checks that protected, package-private and private classes to not have public methods
24+
* unless they are also annotated with {@link Override @Override}.
25+
*
26+
* @author Phillip Webb
27+
*/
28+
public class SpringMethodVisibilityCheck extends AbstractSpringCheck {
29+
30+
@Override
31+
public int[] getAcceptableTokens() {
32+
return new int[] { TokenTypes.METHOD_DEF };
33+
}
34+
35+
@Override
36+
public void visitToken(DetailAST ast) {
37+
DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
38+
if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null) {
39+
visitPublicMethod(modifiers, ast);
40+
}
41+
}
42+
43+
private void visitPublicMethod(DetailAST modifiers, DetailAST method) {
44+
if (hasOverrideAnnotation(modifiers)) {
45+
return;
46+
}
47+
DetailAST classDef = getClassDef(method.getParent());
48+
if (classDef == null) {
49+
return;
50+
}
51+
DetailAST classModifiers = classDef.findFirstToken(TokenTypes.MODIFIERS);
52+
if (classModifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
53+
|| classModifiers.findFirstToken(TokenTypes.LITERAL_PROTECTED) != null) {
54+
return;
55+
}
56+
DetailAST ident = method.findFirstToken(TokenTypes.IDENT);
57+
log(ident.getLineNo(), ident.getColumnNo(), "methodvisibility.publicMethod", ident.getText());
58+
}
59+
60+
private boolean hasOverrideAnnotation(DetailAST modifiers) {
61+
DetailAST candidate = modifiers.getFirstChild();
62+
while (candidate != null) {
63+
if (candidate.getType() == TokenTypes.ANNOTATION) {
64+
DetailAST dot = candidate.findFirstToken(TokenTypes.DOT);
65+
String name = (dot != null ? dot : candidate).findFirstToken(TokenTypes.IDENT).getText();
66+
if ("Override".equals(name)) {
67+
return true;
68+
}
69+
}
70+
candidate = candidate.getNextSibling();
71+
}
72+
return false;
73+
}
74+
75+
private DetailAST getClassDef(DetailAST ast) {
76+
while (ast != null) {
77+
if (ast.getType() == TokenTypes.CLASS_DEF) {
78+
return ast;
79+
}
80+
ast = ast.getParent();
81+
}
82+
return null;
83+
}
84+
85+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ junit5.lifecyclePublicMethod="Lifecycle method ''{0}'' should not be public."
1414
junit5.lifecyclePrivateMethod="Lifecycle method ''{0}'' should not be private."
1515
junit5.testPublicMethod="Test method ''{0}'' should not be public."
1616
junit5.testPrivateMethod="Test method ''{0}'' should not be private."
17+
methodvisibility.publicMethod="Method ''{0}'' in private class should not be public."

spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/spring-checkstyle.xml

+1
Original file line numberDiff line numberDiff line change
@@ -169,5 +169,6 @@
169169
<module name="io.spring.javaformat.checkstyle.check.SpringCatchCheck" />
170170
<module name="io.spring.javaformat.checkstyle.check.SpringJavadocCheck" />
171171
<module name="io.spring.javaformat.checkstyle.check.SpringMethodOrderCheck" />
172+
<module name="io.spring.javaformat.checkstyle.check.SpringMethodVisibilityCheck" />
172173
</module>
173174
</module>

spring-javaformat/spring-javaformat-checkstyle/src/test/java/io/spring/javaformat/checkstyle/SpringChecksTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private void printDebugInfo(File file) throws CheckstyleException {
117117

118118
@Parameters(name = "{0}")
119119
public static Collection<Parameter> files() throws IOException {
120-
return Arrays.stream(SOURCES_DIR.list((dir, name) -> !name.startsWith("."))).map(Parameter::new)
120+
return Arrays.stream(SOURCES_DIR.list((dir, name) -> !name.startsWith("."))).sorted().map(Parameter::new)
121121
.collect(Collectors.toList());
122122
}
123123

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
+Method 'badPrivateInner' in private class should not be public.
2+
+Method 'badDefaultInner' in private class should not be public.
3+
+2 errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
+Method 'bad' in private class should not be public.
2+
+Method 'badStatic' in private class should not be public.
3+
+2 errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
+0 errors
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
* Bad visibility because of public method.
19+
*
20+
* @author Phillip Webb
21+
*/
22+
public class MethodVisibilityInnerClassesWithPublicMethod {
23+
24+
private static class PrivateInnerClass {
25+
26+
public void badPrivateInner() {
27+
}
28+
29+
}
30+
31+
protected static class ProtectedInnerClass {
32+
33+
public void okProtectedInner() {
34+
}
35+
36+
}
37+
38+
static class DefaultInnerClass {
39+
40+
public void badDefaultInner() {
41+
}
42+
43+
}
44+
45+
public static class PublicInnerClass {
46+
47+
public void okPublicInner() {
48+
}
49+
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
* Bad visibility because of public method.
19+
*
20+
* @author Phillip Webb
21+
*/
22+
class MethodVisibilityPackagePrivateWithPublicMethod {
23+
24+
MethodVisibilityPackagePrivateWithPublicMethod() {
25+
}
26+
27+
public void bad() {
28+
}
29+
30+
public static void badStatic() {
31+
}
32+
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
* Bad visibility because of public method.
19+
*
20+
* @author Phillip Webb
21+
*/
22+
public class MethodVisibilityWithOverride {
23+
24+
private static class PrivateInnerClass {
25+
26+
@Override
27+
public void okPrivateInner() {
28+
}
29+
30+
}
31+
32+
protected static class ProtectedInnerClass {
33+
34+
@Override
35+
public void okProtectedInner() {
36+
}
37+
38+
}
39+
40+
static class DefaultInnerClass {
41+
42+
@Override
43+
public void okDefaultInner() {
44+
}
45+
46+
}
47+
48+
}

0 commit comments

Comments
 (0)