1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2018 the original author or authors. | |
4 | // | |
5 | // This library is free software; you can redistribute it and/or | |
6 | // modify it under the terms of the GNU Lesser General Public | |
7 | // License as published by the Free Software Foundation; either | |
8 | // version 2.1 of the License, or (at your option) any later version. | |
9 | // | |
10 | // This library is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | // Lesser General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU Lesser General Public | |
16 | // License along with this library; if not, write to the Free Software | |
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | //////////////////////////////////////////////////////////////////////////////// | |
19 | ||
20 | package com.puppycrawl.tools.checkstyle.checks.coding; | |
21 | ||
22 | import java.util.HashSet; | |
23 | import java.util.Locale; | |
24 | import java.util.Objects; | |
25 | import java.util.Set; | |
26 | import java.util.regex.Pattern; | |
27 | ||
28 | import com.puppycrawl.tools.checkstyle.FileStatefulCheck; | |
29 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
30 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
31 | import com.puppycrawl.tools.checkstyle.api.Scope; | |
32 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
33 | import com.puppycrawl.tools.checkstyle.utils.CheckUtils; | |
34 | import com.puppycrawl.tools.checkstyle.utils.ScopeUtils; | |
35 | ||
36 | /** | |
37 | * Checks that a local variable or a parameter does not shadow | |
38 | * a field that is defined in the same class. | |
39 | * | |
40 | * <p>An example of how to configure the check is: | |
41 | * <pre> | |
42 | * <module name="HiddenField"/> | |
43 | * </pre> | |
44 | * | |
45 | * <p>An example of how to configure the check so that it checks variables but not | |
46 | * parameters is: | |
47 | * <pre> | |
48 | * <module name="HiddenField"> | |
49 | * <property name="tokens" value="VARIABLE_DEF"/> | |
50 | * </module> | |
51 | * </pre> | |
52 | * | |
53 | * <p>An example of how to configure the check so that it ignores the parameter of | |
54 | * a setter method is: | |
55 | * <pre> | |
56 | * <module name="HiddenField"> | |
57 | * <property name="ignoreSetter" value="true"/> | |
58 | * </module> | |
59 | * </pre> | |
60 | * | |
61 | * <p>A method is recognized as a setter if it is in the following form | |
62 | * <pre> | |
63 | * ${returnType} set${Name}(${anyType} ${name}) { ... } | |
64 | * </pre> | |
65 | * where ${anyType} is any primitive type, class or interface name; | |
66 | * ${name} is name of the variable that is being set and ${Name} its | |
67 | * capitalized form that appears in the method name. By default it is expected | |
68 | * that setter returns void, i.e. ${returnType} is 'void'. For example | |
69 | * <pre> | |
70 | * void setTime(long time) { ... } | |
71 | * </pre> | |
72 | * Any other return types will not let method match a setter pattern. However, | |
73 | * by setting <em>setterCanReturnItsClass</em> property to <em>true</em> | |
74 | * definition of a setter is expanded, so that setter return type can also be | |
75 | * a class in which setter is declared. For example | |
76 | * <pre> | |
77 | * class PageBuilder { | |
78 | * PageBuilder setName(String name) { ... } | |
79 | * } | |
80 | * </pre> | |
81 | * Such methods are known as chain-setters and a common when Builder-pattern | |
82 | * is used. Property <em>setterCanReturnItsClass</em> has effect only if | |
83 | * <em>ignoreSetter</em> is set to true. | |
84 | * | |
85 | * <p>An example of how to configure the check so that it ignores the parameter | |
86 | * of either a setter that returns void or a chain-setter. | |
87 | * <pre> | |
88 | * <module name="HiddenField"> | |
89 | * <property name="ignoreSetter" value="true"/> | |
90 | * <property name="setterCanReturnItsClass" value="true"/> | |
91 | * </module> | |
92 | * </pre> | |
93 | * | |
94 | * <p>An example of how to configure the check so that it ignores constructor | |
95 | * parameters is: | |
96 | * <pre> | |
97 | * <module name="HiddenField"> | |
98 | * <property name="ignoreConstructorParameter" value="true"/> | |
99 | * </module> | |
100 | * </pre> | |
101 | * | |
102 | * <p>An example of how to configure the check so that it ignores variables and parameters | |
103 | * named 'test': | |
104 | * <pre> | |
105 | * <module name="HiddenField"> | |
106 | * <property name="ignoreFormat" value="^test$"/> | |
107 | * </module> | |
108 | * </pre> | |
109 | * | |
110 | * <pre> | |
111 | * {@code | |
112 | * class SomeClass | |
113 | * { | |
114 | * private List<String> test; | |
115 | * | |
116 | * private void addTest(List<String> test) // no violation | |
117 | * { | |
118 | * this.test.addAll(test); | |
119 | * } | |
120 | * | |
121 | * private void foo() | |
122 | * { | |
123 | * final List<String> test = new ArrayList<>(); // no violation | |
124 | * ... | |
125 | * } | |
126 | * } | |
127 | * } | |
128 | * </pre> | |
129 | * | |
130 | * @author Dmitri Priimak | |
131 | */ | |
132 | @FileStatefulCheck | |
133 | public class HiddenFieldCheck | |
134 | extends AbstractCheck { | |
135 | ||
136 | /** | |
137 | * A key is pointing to the warning message text in "messages.properties" | |
138 | * file. | |
139 | */ | |
140 | public static final String MSG_KEY = "hidden.field"; | |
141 | ||
142 | /** Stack of sets of field names, | |
143 | * one for each class of a set of nested classes. | |
144 | */ | |
145 | private FieldFrame frame; | |
146 | ||
147 | /** Pattern for names of variables and parameters to ignore. */ | |
148 | private Pattern ignoreFormat; | |
149 | ||
150 | /** Controls whether to check the parameter of a property setter method. */ | |
151 | private boolean ignoreSetter; | |
152 | ||
153 | /** | |
154 | * If ignoreSetter is set to true then this variable controls what | |
155 | * the setter method can return By default setter must return void. | |
156 | * However, is this variable is set to true then setter can also | |
157 | * return class in which is declared. | |
158 | */ | |
159 | private boolean setterCanReturnItsClass; | |
160 | ||
161 | /** Controls whether to check the parameter of a constructor. */ | |
162 | private boolean ignoreConstructorParameter; | |
163 | ||
164 | /** Controls whether to check the parameter of abstract methods. */ | |
165 | private boolean ignoreAbstractMethods; | |
166 | ||
167 | @Override | |
168 | public int[] getDefaultTokens() { | |
169 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getAcceptableTokens(); |
170 | } | |
171 | ||
172 | @Override | |
173 | public int[] getAcceptableTokens() { | |
174 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
175 | TokenTypes.VARIABLE_DEF, | |
176 | TokenTypes.PARAMETER_DEF, | |
177 | TokenTypes.CLASS_DEF, | |
178 | TokenTypes.ENUM_DEF, | |
179 | TokenTypes.ENUM_CONSTANT_DEF, | |
180 | TokenTypes.LAMBDA, | |
181 | }; | |
182 | } | |
183 | ||
184 | @Override | |
185 | public int[] getRequiredTokens() { | |
186 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
187 | TokenTypes.CLASS_DEF, | |
188 | TokenTypes.ENUM_DEF, | |
189 | TokenTypes.ENUM_CONSTANT_DEF, | |
190 | }; | |
191 | } | |
192 | ||
193 | @Override | |
194 | public void beginTree(DetailAST rootAST) { | |
195 | frame = new FieldFrame(null, true, null); | |
196 | } | |
197 | ||
198 | @Override | |
199 | public void visitToken(DetailAST ast) { | |
200 | final int type = ast.getType(); | |
201 | switch (type) { | |
202 | case TokenTypes.VARIABLE_DEF: | |
203 | case TokenTypes.PARAMETER_DEF: | |
204 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::processVariable → KILLED |
processVariable(ast); |
205 | break; | |
206 | case TokenTypes.LAMBDA: | |
207 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::processLambda → KILLED |
processLambda(ast); |
208 | break; | |
209 | default: | |
210 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::visitOtherTokens → KILLED |
visitOtherTokens(ast, type); |
211 | } | |
212 | } | |
213 | ||
214 | /** | |
215 | * Process a lambda token. | |
216 | * Checks whether a lambda parameter shadows a field. | |
217 | * Note, that when parameter of lambda expression is untyped, | |
218 | * ANTLR parses the parameter as an identifier. | |
219 | * @param ast the lambda token. | |
220 | */ | |
221 | private void processLambda(DetailAST ast) { | |
222 | final DetailAST firstChild = ast.getFirstChild(); | |
223 |
1
1. processLambda : negated conditional → KILLED |
if (firstChild.getType() == TokenTypes.IDENT) { |
224 | final String untypedLambdaParameterName = firstChild.getText(); | |
225 |
1
1. processLambda : negated conditional → KILLED |
if (frame.containsStaticField(untypedLambdaParameterName) |
226 |
1
1. processLambda : negated conditional → KILLED |
|| isInstanceField(firstChild, untypedLambdaParameterName)) { |
227 |
1
1. processLambda : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::log → KILLED |
log(firstChild, MSG_KEY, untypedLambdaParameterName); |
228 | } | |
229 | } | |
230 | else { | |
231 | // Type of lambda parameter is not omitted. | |
232 |
1
1. processLambda : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::processVariable → SURVIVED |
processVariable(ast); |
233 | } | |
234 | } | |
235 | ||
236 | /** | |
237 | * Called to process tokens other than {@link TokenTypes#VARIABLE_DEF} | |
238 | * and {@link TokenTypes#PARAMETER_DEF}. | |
239 | * | |
240 | * @param ast token to process | |
241 | * @param type type of the token | |
242 | */ | |
243 | private void visitOtherTokens(DetailAST ast, int type) { | |
244 | //A more thorough check of enum constant class bodies is | |
245 | //possible (checking for hidden fields against the enum | |
246 | //class body in addition to enum constant class bodies) | |
247 | //but not attempted as it seems out of the scope of this | |
248 | //check. | |
249 | final DetailAST typeMods = ast.findFirstToken(TokenTypes.MODIFIERS); | |
250 |
1
1. visitOtherTokens : negated conditional → KILLED |
final boolean isStaticInnerType = |
251 | typeMods != null | |
252 |
1
1. visitOtherTokens : negated conditional → KILLED |
&& typeMods.findFirstToken(TokenTypes.LITERAL_STATIC) != null; |
253 | final String frameName; | |
254 | ||
255 |
2
1. visitOtherTokens : negated conditional → KILLED 2. visitOtherTokens : negated conditional → KILLED |
if (type == TokenTypes.CLASS_DEF || type == TokenTypes.ENUM_DEF) { |
256 | frameName = ast.findFirstToken(TokenTypes.IDENT).getText(); | |
257 | } | |
258 | else { | |
259 | frameName = null; | |
260 | } | |
261 | final FieldFrame newFrame = new FieldFrame(frame, isStaticInnerType, frameName); | |
262 | ||
263 | //add fields to container | |
264 | final DetailAST objBlock = ast.findFirstToken(TokenTypes.OBJBLOCK); | |
265 | // enum constants may not have bodies | |
266 |
1
1. visitOtherTokens : negated conditional → KILLED |
if (objBlock != null) { |
267 | DetailAST child = objBlock.getFirstChild(); | |
268 |
1
1. visitOtherTokens : negated conditional → KILLED |
while (child != null) { |
269 |
1
1. visitOtherTokens : negated conditional → KILLED |
if (child.getType() == TokenTypes.VARIABLE_DEF) { |
270 | final String name = | |
271 | child.findFirstToken(TokenTypes.IDENT).getText(); | |
272 | final DetailAST mods = | |
273 | child.findFirstToken(TokenTypes.MODIFIERS); | |
274 |
1
1. visitOtherTokens : negated conditional → KILLED |
if (mods.findFirstToken(TokenTypes.LITERAL_STATIC) == null) { |
275 |
1
1. visitOtherTokens : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck$FieldFrame::addInstanceField → KILLED |
newFrame.addInstanceField(name); |
276 | } | |
277 | else { | |
278 |
1
1. visitOtherTokens : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck$FieldFrame::addStaticField → KILLED |
newFrame.addStaticField(name); |
279 | } | |
280 | } | |
281 | child = child.getNextSibling(); | |
282 | } | |
283 | } | |
284 | // push container | |
285 | frame = newFrame; | |
286 | } | |
287 | ||
288 | @Override | |
289 | public void leaveToken(DetailAST ast) { | |
290 |
1
1. leaveToken : negated conditional → KILLED |
if (ast.getType() == TokenTypes.CLASS_DEF |
291 |
1
1. leaveToken : negated conditional → KILLED |
|| ast.getType() == TokenTypes.ENUM_DEF |
292 |
1
1. leaveToken : negated conditional → KILLED |
|| ast.getType() == TokenTypes.ENUM_CONSTANT_DEF) { |
293 | //pop | |
294 | frame = frame.getParent(); | |
295 | } | |
296 | } | |
297 | ||
298 | /** | |
299 | * Process a variable token. | |
300 | * Check whether a local variable or parameter shadows a field. | |
301 | * Store a field for later comparison with local variables and parameters. | |
302 | * @param ast the variable token. | |
303 | */ | |
304 | private void processVariable(DetailAST ast) { | |
305 |
1
1. processVariable : negated conditional → KILLED |
if (!ScopeUtils.isInInterfaceOrAnnotationBlock(ast) |
306 |
1
1. processVariable : negated conditional → KILLED |
&& !CheckUtils.isReceiverParameter(ast) |
307 |
1
1. processVariable : negated conditional → KILLED |
&& (ScopeUtils.isLocalVariableDef(ast) |
308 |
1
1. processVariable : negated conditional → KILLED |
|| ast.getType() == TokenTypes.PARAMETER_DEF)) { |
309 | // local variable or parameter. Does it shadow a field? | |
310 | final DetailAST nameAST = ast.findFirstToken(TokenTypes.IDENT); | |
311 | final String name = nameAST.getText(); | |
312 | ||
313 |
2
1. processVariable : negated conditional → KILLED 2. processVariable : negated conditional → KILLED |
if ((frame.containsStaticField(name) || isInstanceField(ast, name)) |
314 |
1
1. processVariable : negated conditional → KILLED |
&& !isMatchingRegexp(name) |
315 |
1
1. processVariable : negated conditional → KILLED |
&& !isIgnoredParam(ast, name)) { |
316 |
1
1. processVariable : removed call to com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::log → KILLED |
log(nameAST, MSG_KEY, name); |
317 | } | |
318 | } | |
319 | } | |
320 | ||
321 | /** | |
322 | * Checks whether method or constructor parameter is ignored. | |
323 | * @param ast the parameter token. | |
324 | * @param name the parameter name. | |
325 | * @return true if parameter is ignored. | |
326 | */ | |
327 | private boolean isIgnoredParam(DetailAST ast, String name) { | |
328 |
2
1. isIgnoredParam : negated conditional → KILLED 2. isIgnoredParam : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isIgnoredSetterParam(ast, name) |
329 |
1
1. isIgnoredParam : negated conditional → KILLED |
|| isIgnoredConstructorParam(ast) |
330 |
1
1. isIgnoredParam : negated conditional → KILLED |
|| isIgnoredParamOfAbstractMethod(ast); |
331 | } | |
332 | ||
333 | /** | |
334 | * Check for instance field. | |
335 | * @param ast token | |
336 | * @param name identifier of token | |
337 | * @return true if instance field | |
338 | */ | |
339 | private boolean isInstanceField(DetailAST ast, String name) { | |
340 |
3
1. isInstanceField : negated conditional → KILLED 2. isInstanceField : negated conditional → KILLED 3. isInstanceField : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return !isInStatic(ast) && frame.containsInstanceField(name); |
341 | } | |
342 | ||
343 | /** | |
344 | * Check name by regExp. | |
345 | * @param name string value to check | |
346 | * @return true is regexp is matching | |
347 | */ | |
348 | private boolean isMatchingRegexp(String name) { | |
349 |
3
1. isMatchingRegexp : negated conditional → KILLED 2. isMatchingRegexp : negated conditional → KILLED 3. isMatchingRegexp : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return ignoreFormat != null && ignoreFormat.matcher(name).find(); |
350 | } | |
351 | ||
352 | /** | |
353 | * Determines whether an AST node is in a static method or static | |
354 | * initializer. | |
355 | * @param ast the node to check. | |
356 | * @return true if ast is in a static method or a static block; | |
357 | */ | |
358 | private static boolean isInStatic(DetailAST ast) { | |
359 | DetailAST parent = ast.getParent(); | |
360 | boolean inStatic = false; | |
361 | ||
362 |
2
1. isInStatic : negated conditional → KILLED 2. isInStatic : negated conditional → KILLED |
while (parent != null && !inStatic) { |
363 |
1
1. isInStatic : negated conditional → KILLED |
if (parent.getType() == TokenTypes.STATIC_INIT) { |
364 | inStatic = true; | |
365 | } | |
366 |
1
1. isInStatic : negated conditional → KILLED |
else if (parent.getType() == TokenTypes.METHOD_DEF |
367 |
1
1. isInStatic : negated conditional → KILLED |
&& !ScopeUtils.isInScope(parent, Scope.ANONINNER) |
368 |
1
1. isInStatic : negated conditional → KILLED |
|| parent.getType() == TokenTypes.VARIABLE_DEF) { |
369 | final DetailAST mods = | |
370 | parent.findFirstToken(TokenTypes.MODIFIERS); | |
371 |
1
1. isInStatic : negated conditional → KILLED |
inStatic = mods.findFirstToken(TokenTypes.LITERAL_STATIC) != null; |
372 | break; | |
373 | } | |
374 | else { | |
375 | parent = parent.getParent(); | |
376 | } | |
377 | } | |
378 |
1
1. isInStatic : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return inStatic; |
379 | } | |
380 | ||
381 | /** | |
382 | * Decides whether to ignore an AST node that is the parameter of a | |
383 | * setter method, where the property setter method for field 'xyz' has | |
384 | * name 'setXyz', one parameter named 'xyz', and return type void | |
385 | * (default behavior) or return type is name of the class in which | |
386 | * such method is declared (allowed only if | |
387 | * {@link #setSetterCanReturnItsClass(boolean)} is called with | |
388 | * value <em>true</em>). | |
389 | * | |
390 | * @param ast the AST to check. | |
391 | * @param name the name of ast. | |
392 | * @return true if ast should be ignored because check property | |
393 | * ignoreSetter is true and ast is the parameter of a setter method. | |
394 | */ | |
395 | private boolean isIgnoredSetterParam(DetailAST ast, String name) { | |
396 | boolean isIgnoredSetterParam = false; | |
397 |
2
1. isIgnoredSetterParam : negated conditional → KILLED 2. isIgnoredSetterParam : negated conditional → KILLED |
if (ignoreSetter && ast.getType() == TokenTypes.PARAMETER_DEF) { |
398 | final DetailAST parametersAST = ast.getParent(); | |
399 | final DetailAST methodAST = parametersAST.getParent(); | |
400 |
1
1. isIgnoredSetterParam : negated conditional → KILLED |
if (parametersAST.getChildCount() == 1 |
401 |
1
1. isIgnoredSetterParam : negated conditional → KILLED |
&& methodAST.getType() == TokenTypes.METHOD_DEF |
402 |
1
1. isIgnoredSetterParam : negated conditional → KILLED |
&& isSetterMethod(methodAST, name)) { |
403 | isIgnoredSetterParam = true; | |
404 | } | |
405 | } | |
406 |
1
1. isIgnoredSetterParam : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isIgnoredSetterParam; |
407 | } | |
408 | ||
409 | /** | |
410 | * Determine if a specific method identified by methodAST and a single | |
411 | * variable name aName is a setter. This recognition partially depends | |
412 | * on mSetterCanReturnItsClass property. | |
413 | * | |
414 | * @param aMethodAST AST corresponding to a method call | |
415 | * @param aName name of single parameter of this method. | |
416 | * @return true of false indicating of method is a setter or not. | |
417 | */ | |
418 | private boolean isSetterMethod(DetailAST aMethodAST, String aName) { | |
419 | final String methodName = | |
420 | aMethodAST.findFirstToken(TokenTypes.IDENT).getText(); | |
421 | boolean isSetterMethod = false; | |
422 | ||
423 |
1
1. isSetterMethod : negated conditional → KILLED |
if (("set" + capitalize(aName)).equals(methodName)) { |
424 | // method name did match set${Name}(${anyType} ${aName}) | |
425 | // where ${Name} is capitalized version of ${aName} | |
426 | // therefore this method is potentially a setter | |
427 | final DetailAST typeAST = aMethodAST.findFirstToken(TokenTypes.TYPE); | |
428 | final String returnType = typeAST.getFirstChild().getText(); | |
429 |
2
1. isSetterMethod : negated conditional → KILLED 2. isSetterMethod : negated conditional → KILLED |
if (typeAST.findFirstToken(TokenTypes.LITERAL_VOID) != null |
430 |
1
1. isSetterMethod : negated conditional → KILLED |
|| setterCanReturnItsClass && frame.isEmbeddedIn(returnType)) { |
431 | // this method has signature | |
432 | // | |
433 | // void set${Name}(${anyType} ${name}) | |
434 | // | |
435 | // and therefore considered to be a setter | |
436 | // | |
437 | // or | |
438 | // | |
439 | // return type is not void, but it is the same as the class | |
440 | // where method is declared and and mSetterCanReturnItsClass | |
441 | // is set to true | |
442 | isSetterMethod = true; | |
443 | } | |
444 | } | |
445 | ||
446 |
1
1. isSetterMethod : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isSetterMethod; |
447 | } | |
448 | ||
449 | /** | |
450 | * Capitalizes a given property name the way we expect to see it in | |
451 | * a setter name. | |
452 | * @param name a property name | |
453 | * @return capitalized property name | |
454 | */ | |
455 | private static String capitalize(final String name) { | |
456 | String setterName = name; | |
457 | // we should not capitalize the first character if the second | |
458 | // one is a capital one, since according to JavaBeans spec | |
459 | // setXYzz() is a setter for XYzz property, not for xYzz one. | |
460 |
2
1. capitalize : negated conditional → KILLED 2. capitalize : negated conditional → KILLED |
if (name.length() == 1 || !Character.isUpperCase(name.charAt(1))) { |
461 | setterName = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1); | |
462 | } | |
463 |
1
1. capitalize : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck::capitalize to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return setterName; |
464 | } | |
465 | ||
466 | /** | |
467 | * Decides whether to ignore an AST node that is the parameter of a | |
468 | * constructor. | |
469 | * @param ast the AST to check. | |
470 | * @return true if ast should be ignored because check property | |
471 | * ignoreConstructorParameter is true and ast is a constructor parameter. | |
472 | */ | |
473 | private boolean isIgnoredConstructorParam(DetailAST ast) { | |
474 | boolean result = false; | |
475 |
1
1. isIgnoredConstructorParam : negated conditional → KILLED |
if (ignoreConstructorParameter |
476 |
1
1. isIgnoredConstructorParam : negated conditional → KILLED |
&& ast.getType() == TokenTypes.PARAMETER_DEF) { |
477 | final DetailAST parametersAST = ast.getParent(); | |
478 | final DetailAST constructorAST = parametersAST.getParent(); | |
479 |
1
1. isIgnoredConstructorParam : negated conditional → KILLED |
result = constructorAST.getType() == TokenTypes.CTOR_DEF; |
480 | } | |
481 |
1
1. isIgnoredConstructorParam : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
482 | } | |
483 | ||
484 | /** | |
485 | * Decides whether to ignore an AST node that is the parameter of an | |
486 | * abstract method. | |
487 | * @param ast the AST to check. | |
488 | * @return true if ast should be ignored because check property | |
489 | * ignoreAbstractMethods is true and ast is a parameter of abstract methods. | |
490 | */ | |
491 | private boolean isIgnoredParamOfAbstractMethod(DetailAST ast) { | |
492 | boolean result = false; | |
493 |
1
1. isIgnoredParamOfAbstractMethod : negated conditional → KILLED |
if (ignoreAbstractMethods |
494 |
1
1. isIgnoredParamOfAbstractMethod : negated conditional → KILLED |
&& ast.getType() == TokenTypes.PARAMETER_DEF) { |
495 | final DetailAST method = ast.getParent().getParent(); | |
496 |
1
1. isIgnoredParamOfAbstractMethod : negated conditional → KILLED |
if (method.getType() == TokenTypes.METHOD_DEF) { |
497 | final DetailAST mods = method.findFirstToken(TokenTypes.MODIFIERS); | |
498 |
1
1. isIgnoredParamOfAbstractMethod : negated conditional → KILLED |
result = mods.findFirstToken(TokenTypes.ABSTRACT) != null; |
499 | } | |
500 | } | |
501 |
1
1. isIgnoredParamOfAbstractMethod : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
502 | } | |
503 | ||
504 | /** | |
505 | * Set the ignore format for the specified regular expression. | |
506 | * @param pattern a pattern. | |
507 | */ | |
508 | public void setIgnoreFormat(Pattern pattern) { | |
509 | ignoreFormat = pattern; | |
510 | } | |
511 | ||
512 | /** | |
513 | * Set whether to ignore the parameter of a property setter method. | |
514 | * @param ignoreSetter decide whether to ignore the parameter of | |
515 | * a property setter method. | |
516 | */ | |
517 | public void setIgnoreSetter(boolean ignoreSetter) { | |
518 | this.ignoreSetter = ignoreSetter; | |
519 | } | |
520 | ||
521 | /** | |
522 | * Controls if setter can return only void (default behavior) or it | |
523 | * can also return class in which it is declared. | |
524 | * | |
525 | * @param aSetterCanReturnItsClass if true then setter can return | |
526 | * either void or class in which it is declared. If false then | |
527 | * in order to be recognized as setter method (otherwise | |
528 | * already recognized as a setter) must return void. Later is | |
529 | * the default behavior. | |
530 | */ | |
531 | public void setSetterCanReturnItsClass( | |
532 | boolean aSetterCanReturnItsClass) { | |
533 | setterCanReturnItsClass = aSetterCanReturnItsClass; | |
534 | } | |
535 | ||
536 | /** | |
537 | * Set whether to ignore constructor parameters. | |
538 | * @param ignoreConstructorParameter decide whether to ignore | |
539 | * constructor parameters. | |
540 | */ | |
541 | public void setIgnoreConstructorParameter( | |
542 | boolean ignoreConstructorParameter) { | |
543 | this.ignoreConstructorParameter = ignoreConstructorParameter; | |
544 | } | |
545 | ||
546 | /** | |
547 | * Set whether to ignore parameters of abstract methods. | |
548 | * @param ignoreAbstractMethods decide whether to ignore | |
549 | * parameters of abstract methods. | |
550 | */ | |
551 | public void setIgnoreAbstractMethods( | |
552 | boolean ignoreAbstractMethods) { | |
553 | this.ignoreAbstractMethods = ignoreAbstractMethods; | |
554 | } | |
555 | ||
556 | /** | |
557 | * Holds the names of static and instance fields of a type. | |
558 | * @author Rick Giles | |
559 | */ | |
560 | private static class FieldFrame { | |
561 | ||
562 | /** Name of the frame, such name of the class or enum declaration. */ | |
563 | private final String frameName; | |
564 | ||
565 | /** Is this a static inner type. */ | |
566 | private final boolean staticType; | |
567 | ||
568 | /** Parent frame. */ | |
569 | private final FieldFrame parent; | |
570 | ||
571 | /** Set of instance field names. */ | |
572 | private final Set<String> instanceFields = new HashSet<>(); | |
573 | ||
574 | /** Set of static field names. */ | |
575 | private final Set<String> staticFields = new HashSet<>(); | |
576 | ||
577 | /** | |
578 | * Creates new frame. | |
579 | * @param parent parent frame. | |
580 | * @param staticType is this a static inner type (class or enum). | |
581 | * @param frameName name associated with the frame, which can be a | |
582 | */ | |
583 | FieldFrame(FieldFrame parent, boolean staticType, String frameName) { | |
584 | this.parent = parent; | |
585 | this.staticType = staticType; | |
586 | this.frameName = frameName; | |
587 | } | |
588 | ||
589 | /** | |
590 | * Adds an instance field to this FieldFrame. | |
591 | * @param field the name of the instance field. | |
592 | */ | |
593 | public void addInstanceField(String field) { | |
594 | instanceFields.add(field); | |
595 | } | |
596 | ||
597 | /** | |
598 | * Adds a static field to this FieldFrame. | |
599 | * @param field the name of the instance field. | |
600 | */ | |
601 | public void addStaticField(String field) { | |
602 | staticFields.add(field); | |
603 | } | |
604 | ||
605 | /** | |
606 | * Determines whether this FieldFrame contains an instance field. | |
607 | * @param field the field to check. | |
608 | * @return true if this FieldFrame contains instance field field. | |
609 | */ | |
610 | public boolean containsInstanceField(String field) { | |
611 |
4
1. containsInstanceField : negated conditional → KILLED 2. containsInstanceField : negated conditional → KILLED 3. containsInstanceField : negated conditional → KILLED 4. containsInstanceField : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return instanceFields.contains(field) |
612 | || parent != null | |
613 | && !staticType | |
614 |
1
1. containsInstanceField : negated conditional → KILLED |
&& parent.containsInstanceField(field); |
615 | } | |
616 | ||
617 | /** | |
618 | * Determines whether this FieldFrame contains a static field. | |
619 | * @param field the field to check. | |
620 | * @return true if this FieldFrame contains static field field. | |
621 | */ | |
622 | public boolean containsStaticField(String field) { | |
623 |
3
1. containsStaticField : negated conditional → KILLED 2. containsStaticField : negated conditional → KILLED 3. containsStaticField : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return staticFields.contains(field) |
624 | || parent != null | |
625 |
1
1. containsStaticField : negated conditional → KILLED |
&& parent.containsStaticField(field); |
626 | } | |
627 | ||
628 | /** | |
629 | * Getter for parent frame. | |
630 | * @return parent frame. | |
631 | */ | |
632 | public FieldFrame getParent() { | |
633 |
1
1. getParent : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck$FieldFrame::getParent to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return parent; |
634 | } | |
635 | ||
636 | /** | |
637 | * Check if current frame is embedded in class or enum with | |
638 | * specific name. | |
639 | * | |
640 | * @param classOrEnumName name of class or enum that we are looking | |
641 | * for in the chain of field frames. | |
642 | * | |
643 | * @return true if current frame is embedded in class or enum | |
644 | * with name classOrNameName | |
645 | */ | |
646 | private boolean isEmbeddedIn(String classOrEnumName) { | |
647 | FieldFrame currentFrame = this; | |
648 | boolean isEmbeddedIn = false; | |
649 |
1
1. isEmbeddedIn : negated conditional → KILLED |
while (currentFrame != null) { |
650 |
1
1. isEmbeddedIn : negated conditional → KILLED |
if (Objects.equals(currentFrame.frameName, classOrEnumName)) { |
651 | isEmbeddedIn = true; | |
652 | break; | |
653 | } | |
654 | currentFrame = currentFrame.parent; | |
655 | } | |
656 |
1
1. isEmbeddedIn : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isEmbeddedIn; |
657 | } | |
658 | ||
659 | } | |
660 | ||
661 | } | |
Mutations | ||
169 |
1.1 |
|
174 |
1.1 |
|
186 |
1.1 |
|
204 |
1.1 |
|
207 |
1.1 |
|
210 |
1.1 |
|
223 |
1.1 |
|
225 |
1.1 |
|
226 |
1.1 |
|
227 |
1.1 |
|
232 |
1.1 |
|
250 |
1.1 |
|
252 |
1.1 |
|
255 |
1.1 2.2 |
|
266 |
1.1 |
|
268 |
1.1 |
|
269 |
1.1 |
|
274 |
1.1 |
|
275 |
1.1 |
|
278 |
1.1 |
|
290 |
1.1 |
|
291 |
1.1 |
|
292 |
1.1 |
|
305 |
1.1 |
|
306 |
1.1 |
|
307 |
1.1 |
|
308 |
1.1 |
|
313 |
1.1 2.2 |
|
314 |
1.1 |
|
315 |
1.1 |
|
316 |
1.1 |
|
328 |
1.1 2.2 |
|
329 |
1.1 |
|
330 |
1.1 |
|
340 |
1.1 2.2 3.3 |
|
349 |
1.1 2.2 3.3 |
|
362 |
1.1 2.2 |
|
363 |
1.1 |
|
366 |
1.1 |
|
367 |
1.1 |
|
368 |
1.1 |
|
371 |
1.1 |
|
378 |
1.1 |
|
397 |
1.1 2.2 |
|
400 |
1.1 |
|
401 |
1.1 |
|
402 |
1.1 |
|
406 |
1.1 |
|
423 |
1.1 |
|
429 |
1.1 2.2 |
|
430 |
1.1 |
|
446 |
1.1 |
|
460 |
1.1 2.2 |
|
463 |
1.1 |
|
475 |
1.1 |
|
476 |
1.1 |
|
479 |
1.1 |
|
481 |
1.1 |
|
493 |
1.1 |
|
494 |
1.1 |
|
496 |
1.1 |
|
498 |
1.1 |
|
501 |
1.1 |
|
611 |
1.1 2.2 3.3 4.4 |
|
614 |
1.1 |
|
623 |
1.1 2.2 3.3 |
|
625 |
1.1 |
|
633 |
1.1 |
|
649 |
1.1 |
|
650 |
1.1 |
|
656 |
1.1 |