1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.coding;
21
22 import com.puppycrawl.tools.checkstyle.StatelessCheck;
23 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
24 import com.puppycrawl.tools.checkstyle.api.DetailAST;
25 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
27 import com.puppycrawl.tools.checkstyle.utils.ScopeUtil;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @StatelessCheck
45 public final class UnnecessarySemicolonAfterTypeMemberDeclarationCheck extends AbstractCheck {
46
47
48
49
50
51 public static final String MSG_SEMI = "unnecessary.semicolon";
52
53 @Override
54 public int[] getDefaultTokens() {
55 return getAcceptableTokens();
56 }
57
58 @Override
59 public int[] getAcceptableTokens() {
60 return new int[] {
61 TokenTypes.CLASS_DEF,
62 TokenTypes.INTERFACE_DEF,
63 TokenTypes.ENUM_DEF,
64 TokenTypes.ANNOTATION_DEF,
65 TokenTypes.VARIABLE_DEF,
66 TokenTypes.ANNOTATION_FIELD_DEF,
67 TokenTypes.STATIC_INIT,
68 TokenTypes.INSTANCE_INIT,
69 TokenTypes.CTOR_DEF,
70 TokenTypes.METHOD_DEF,
71 TokenTypes.ENUM_CONSTANT_DEF,
72 TokenTypes.COMPACT_CTOR_DEF,
73 TokenTypes.RECORD_DEF,
74 };
75 }
76
77 @Override
78 public int[] getRequiredTokens() {
79 return CommonUtil.EMPTY_INT_ARRAY;
80 }
81
82 @Override
83 public void visitToken(DetailAST ast) {
84 switch (ast.getType()) {
85 case TokenTypes.CLASS_DEF,
86 TokenTypes.INTERFACE_DEF,
87 TokenTypes.ENUM_DEF,
88 TokenTypes.ANNOTATION_DEF,
89 TokenTypes.RECORD_DEF -> checkTypeDefinition(ast);
90 case TokenTypes.VARIABLE_DEF -> checkVariableDefinition(ast);
91 case TokenTypes.ENUM_CONSTANT_DEF -> checkEnumConstant(ast);
92 default -> checkTypeMember(ast);
93 }
94 }
95
96
97
98
99
100
101 private void checkTypeMember(DetailAST ast) {
102 if (isSemicolon(ast.getNextSibling())) {
103 log(ast.getNextSibling(), MSG_SEMI);
104 }
105 }
106
107
108
109
110
111
112 private void checkTypeDefinition(DetailAST ast) {
113 if (!ScopeUtil.isOuterMostType(ast) && isSemicolon(ast.getNextSibling())) {
114 log(ast.getNextSibling(), MSG_SEMI);
115 }
116 final DetailAST firstMember =
117 ast.findFirstToken(TokenTypes.OBJBLOCK).getFirstChild().getNextSibling();
118 if (isSemicolon(firstMember) && !ScopeUtil.isInEnumBlock(firstMember)) {
119 log(firstMember, MSG_SEMI);
120 }
121 }
122
123
124
125
126
127
128 private void checkVariableDefinition(DetailAST variableDef) {
129 if (isSemicolon(variableDef.getLastChild()) && isSemicolon(variableDef.getNextSibling())) {
130 log(variableDef.getNextSibling(), MSG_SEMI);
131 }
132 }
133
134
135
136
137
138
139 private void checkEnumConstant(DetailAST ast) {
140 final DetailAST next = ast.getNextSibling();
141 if (isSemicolon(next) && isSemicolon(next.getNextSibling())) {
142 log(next.getNextSibling(), MSG_SEMI);
143 }
144 }
145
146
147
148
149
150
151
152 private static boolean isSemicolon(DetailAST ast) {
153 return ast != null && ast.getType() == TokenTypes.SEMI;
154 }
155 }