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 import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil;
11 import java.util.ArrayList;
12 import java.util.List;
13
14
15
16
17
18
19 public final class ProtectedMethodInFinalClassCheck extends AbstractCheck {
20
21 @Override
22 public int[] getDefaultTokens() {
23 return new int[] {
24 TokenTypes.CLASS_DEF,
25 };
26 }
27
28 @Override
29 public int[] getAcceptableTokens() {
30 return this.getDefaultTokens();
31 }
32
33 @Override
34 public int[] getRequiredTokens() {
35 return this.getDefaultTokens();
36 }
37
38 @Override
39 public void visitToken(final DetailAST ast) {
40 if (ast.getType() == TokenTypes.CLASS_DEF) {
41 final DetailAST modifiers = ast.findFirstToken(
42 TokenTypes.MODIFIERS
43 );
44 if (modifiers.findFirstToken(TokenTypes.FINAL) != null) {
45 this.checkMethods(ast);
46 }
47 }
48 }
49
50
51
52
53
54 private void checkMethods(final DetailAST ast) {
55 final DetailAST objblock = ast.findFirstToken(TokenTypes.OBJBLOCK);
56 for (final DetailAST method
57 : ProtectedMethodInFinalClassCheck.findAllChildren(
58 objblock, TokenTypes.METHOD_DEF
59 )
60 ) {
61 if (method
62 .findFirstToken(TokenTypes.MODIFIERS)
63 .findFirstToken(TokenTypes.LITERAL_PROTECTED) != null) {
64 if (AnnotationUtil.containsAnnotation(method, "Override")) {
65 this.log(
66 method.getLineNo(),
67 "Protected method is overriding default scoped method"
68 );
69 } else {
70 this.log(
71 method.getLineNo(),
72 "Final class should not contain protected methods"
73 );
74 }
75 }
76 }
77 }
78
79
80
81
82
83
84
85 private static Iterable<DetailAST> findAllChildren(final DetailAST base,
86 final int type) {
87 final List<DetailAST> children = new ArrayList<>(base.getChildCount());
88 DetailAST child = base.getFirstChild();
89 while (child != null) {
90 if (child.getType() == type) {
91 children.add(child);
92 }
93 child = child.getNextSibling();
94 }
95 return children;
96 }
97 }