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