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
54
55
56 public UnnecessarySemicolonAfterTypeMemberDeclarationCheck() {
57
58 }
59
60 @Override
61 public int[] getDefaultTokens() {
62 return getAcceptableTokens();
63 }
64
65 @Override
66 public int[] getAcceptableTokens() {
67 return new int[] {
68 TokenTypes.CLASS_DEF,
69 TokenTypes.INTERFACE_DEF,
70 TokenTypes.ENUM_DEF,
71 TokenTypes.ANNOTATION_DEF,
72 TokenTypes.VARIABLE_DEF,
73 TokenTypes.ANNOTATION_FIELD_DEF,
74 TokenTypes.STATIC_INIT,
75 TokenTypes.INSTANCE_INIT,
76 TokenTypes.CTOR_DEF,
77 TokenTypes.METHOD_DEF,
78 TokenTypes.ENUM_CONSTANT_DEF,
79 TokenTypes.COMPACT_CTOR_DEF,
80 TokenTypes.RECORD_DEF,
81 };
82 }
83
84 @Override
85 public int[] getRequiredTokens() {
86 return CommonUtil.EMPTY_INT_ARRAY;
87 }
88
89 @Override
90 public void visitToken(DetailAST ast) {
91 switch (ast.getType()) {
92 case TokenTypes.CLASS_DEF,
93 TokenTypes.INTERFACE_DEF,
94 TokenTypes.ENUM_DEF,
95 TokenTypes.ANNOTATION_DEF,
96 TokenTypes.RECORD_DEF -> checkTypeDefinition(ast);
97 case TokenTypes.VARIABLE_DEF -> checkVariableDefinition(ast);
98 case TokenTypes.ENUM_CONSTANT_DEF -> checkEnumConstant(ast);
99 default -> checkTypeMember(ast);
100 }
101 }
102
103
104
105
106
107
108 private void checkTypeMember(DetailAST ast) {
109 if (isSemicolon(ast.getNextSibling())) {
110 log(ast.getNextSibling(), MSG_SEMI);
111 }
112 }
113
114
115
116
117
118
119 private void checkTypeDefinition(DetailAST ast) {
120 if (!ScopeUtil.isOuterMostType(ast) && isSemicolon(ast.getNextSibling())) {
121 log(ast.getNextSibling(), MSG_SEMI);
122 }
123 final DetailAST firstMember =
124 ast.findFirstToken(TokenTypes.OBJBLOCK).getFirstChild().getNextSibling();
125 if (isSemicolon(firstMember) && !ScopeUtil.isInEnumBlock(firstMember)) {
126 log(firstMember, MSG_SEMI);
127 }
128 }
129
130
131
132
133
134
135 private void checkVariableDefinition(DetailAST variableDef) {
136 if (isSemicolon(variableDef.getLastChild()) && isSemicolon(variableDef.getNextSibling())) {
137 log(variableDef.getNextSibling(), MSG_SEMI);
138 }
139 }
140
141
142
143
144
145
146 private void checkEnumConstant(DetailAST ast) {
147 final DetailAST next = ast.getNextSibling();
148 if (isSemicolon(next) && isSemicolon(next.getNextSibling())) {
149 log(next.getNextSibling(), MSG_SEMI);
150 }
151 }
152
153
154
155
156
157
158
159 private static boolean isSemicolon(DetailAST ast) {
160 return ast != null && ast.getType() == TokenTypes.SEMI;
161 }
162
163 }