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.CheckUtil;
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 @StatelessCheck
70 public class ExplicitInitializationCheck extends AbstractCheck {
71
72
73
74
75
76 public static final String MSG_KEY = "explicit.init";
77
78
79
80
81 private boolean onlyObjectReferences;
82
83 @Override
84 public final int[] getDefaultTokens() {
85 return getRequiredTokens();
86 }
87
88 @Override
89 public final int[] getRequiredTokens() {
90 return new int[] {TokenTypes.VARIABLE_DEF};
91 }
92
93 @Override
94 public final int[] getAcceptableTokens() {
95 return getRequiredTokens();
96 }
97
98
99
100
101
102
103
104
105
106 public void setOnlyObjectReferences(boolean onlyObjectReferences) {
107 this.onlyObjectReferences = onlyObjectReferences;
108 }
109
110 @Override
111 public void visitToken(DetailAST ast) {
112 if (!isSkipCase(ast)) {
113 final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
114 final DetailAST exprStart =
115 assign.getFirstChild().getFirstChild();
116 if (exprStart.getType() == TokenTypes.LITERAL_NULL) {
117 final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
118 log(ident, MSG_KEY, ident.getText(), "null");
119 }
120 if (!onlyObjectReferences) {
121 validateNonObjects(ast);
122 }
123 }
124 }
125
126
127
128
129
130
131 private void validateNonObjects(DetailAST ast) {
132 final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
133 final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
134 final DetailAST exprStart =
135 assign.getFirstChild().getFirstChild();
136 final DetailAST type = ast.findFirstToken(TokenTypes.TYPE);
137 final int primitiveType = type.getFirstChild().getType();
138 if (primitiveType == TokenTypes.LITERAL_BOOLEAN
139 && exprStart.getType() == TokenTypes.LITERAL_FALSE) {
140 log(ident, MSG_KEY, ident.getText(), "false");
141 }
142 if (isNumericType(primitiveType) && isZero(exprStart)) {
143 log(ident, MSG_KEY, ident.getText(), "0");
144 }
145 if (primitiveType == TokenTypes.LITERAL_CHAR
146 && isZeroChar(exprStart)) {
147 log(ident, MSG_KEY, ident.getText(), "\\0");
148 }
149 }
150
151
152
153
154
155
156
157 private static boolean isZeroChar(DetailAST exprStart) {
158 return isZero(exprStart)
159 || "'\\0'".equals(exprStart.getText());
160 }
161
162
163
164
165
166
167
168 private static boolean isSkipCase(DetailAST ast) {
169 boolean skipCase = true;
170
171
172
173 if (!ScopeUtil.isLocalVariableDef(ast)
174 && !ScopeUtil.isInInterfaceOrAnnotationBlock(ast)) {
175 final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
176
177 if (assign != null) {
178 final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
179 skipCase = modifiers.findFirstToken(TokenTypes.FINAL) != null;
180 }
181 }
182 return skipCase;
183 }
184
185
186
187
188
189
190
191
192 private static boolean isNumericType(int type) {
193 return type == TokenTypes.LITERAL_BYTE
194 || type == TokenTypes.LITERAL_SHORT
195 || type == TokenTypes.LITERAL_INT
196 || type == TokenTypes.LITERAL_FLOAT
197 || type == TokenTypes.LITERAL_LONG
198 || type == TokenTypes.LITERAL_DOUBLE;
199 }
200
201
202
203
204
205
206
207 private static boolean isZero(DetailAST expr) {
208 final int type = expr.getType();
209 final boolean isZero;
210 switch (type) {
211 case TokenTypes.NUM_FLOAT:
212 case TokenTypes.NUM_DOUBLE:
213 case TokenTypes.NUM_INT:
214 case TokenTypes.NUM_LONG:
215 final String text = expr.getText();
216 isZero = Double.compare(CheckUtil.parseDouble(text, type), 0.0) == 0;
217 break;
218 default:
219 isZero = false;
220 }
221 return isZero;
222 }
223
224 }