1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2017 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.metrics; | |
21 | ||
22 | import java.util.ArrayDeque; | |
23 | import java.util.ArrayList; | |
24 | import java.util.Arrays; | |
25 | import java.util.Collections; | |
26 | import java.util.Deque; | |
27 | import java.util.HashMap; | |
28 | import java.util.List; | |
29 | import java.util.Map; | |
30 | import java.util.Optional; | |
31 | import java.util.Set; | |
32 | import java.util.TreeSet; | |
33 | import java.util.regex.Pattern; | |
34 | import java.util.stream.Collectors; | |
35 | ||
36 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
37 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
38 | import com.puppycrawl.tools.checkstyle.api.FullIdent; | |
39 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
40 | import com.puppycrawl.tools.checkstyle.utils.CheckUtils; | |
41 | import com.puppycrawl.tools.checkstyle.utils.CommonUtils; | |
42 | ||
43 | /** | |
44 | * Base class for coupling calculation. | |
45 | * | |
46 | * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a> | |
47 | * @author o_sukhodolsky | |
48 | */ | |
49 | public abstract class AbstractClassCouplingCheck extends AbstractCheck { | |
50 | /** A package separator - "." */ | |
51 | private static final String DOT = "."; | |
52 | ||
53 | /** Class names to ignore. */ | |
54 | private static final Set<String> DEFAULT_EXCLUDED_CLASSES = Collections.unmodifiableSet( | |
55 | Arrays.stream(new String[] { | |
56 | // primitives | |
57 | "boolean", "byte", "char", "double", "float", "int", | |
58 | "long", "short", "void", | |
59 | // wrappers | |
60 | "Boolean", "Byte", "Character", "Double", "Float", | |
61 | "Integer", "Long", "Short", "Void", | |
62 | // java.lang.* | |
63 | "Object", "Class", | |
64 | "String", "StringBuffer", "StringBuilder", | |
65 | // Exceptions | |
66 | "ArrayIndexOutOfBoundsException", "Exception", | |
67 | "RuntimeException", "IllegalArgumentException", | |
68 | "IllegalStateException", "IndexOutOfBoundsException", | |
69 | "NullPointerException", "Throwable", "SecurityException", | |
70 | "UnsupportedOperationException", | |
71 | // java.util.* | |
72 | "List", "ArrayList", "Deque", "Queue", "LinkedList", | |
73 | "Set", "HashSet", "SortedSet", "TreeSet", | |
74 | "Map", "HashMap", "SortedMap", "TreeMap", | |
75 | }).collect(Collectors.toSet())); | |
76 | ||
77 | /** Package names to ignore. */ | |
78 | private static final Set<String> DEFAULT_EXCLUDED_PACKAGES = Collections.emptySet(); | |
79 | ||
80 | /** User-configured regular expressions to ignore classes. */ | |
81 | private final List<Pattern> excludeClassesRegexps = new ArrayList<>(); | |
82 | ||
83 | /** User-configured class names to ignore. */ | |
84 | private Set<String> excludedClasses = DEFAULT_EXCLUDED_CLASSES; | |
85 | /** User-configured package names to ignore. */ | |
86 | private Set<String> excludedPackages = DEFAULT_EXCLUDED_PACKAGES; | |
87 | /** Allowed complexity. */ | |
88 | private int max; | |
89 | ||
90 | /** Current file context. */ | |
91 | private FileContext fileContext; | |
92 | ||
93 | /** | |
94 | * Creates new instance of the check. | |
95 | * @param defaultMax default value for allowed complexity. | |
96 | */ | |
97 | protected AbstractClassCouplingCheck(int defaultMax) { | |
98 | max = defaultMax; | |
99 | excludeClassesRegexps.add(CommonUtils.createPattern("^$")); | |
100 | } | |
101 | ||
102 | /** | |
103 | * Returns message key we use for log violations. | |
104 | * @return message key we use for log violations. | |
105 | */ | |
106 | protected abstract String getLogMessageId(); | |
107 | ||
108 | @Override | |
109 | public final int[] getDefaultTokens() { | |
110 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
111 | } | |
112 | ||
113 | /** | |
114 | * Sets maximum allowed complexity. | |
115 | * @param max allowed complexity. | |
116 | */ | |
117 | public final void setMax(int max) { | |
118 | this.max = max; | |
119 | } | |
120 | ||
121 | /** | |
122 | * Sets user-excluded classes to ignore. | |
123 | * @param excludedClasses the list of classes to ignore. | |
124 | */ | |
125 | public final void setExcludedClasses(String... excludedClasses) { | |
126 | this.excludedClasses = | |
127 | Collections.unmodifiableSet(Arrays.stream(excludedClasses).collect(Collectors.toSet())); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Sets user-excluded regular expression of classes to ignore. | |
132 | * @param from array representing regular expressions of classes to ignore. | |
133 | */ | |
134 | public void setExcludeClassesRegexps(String... from) { | |
135 | excludeClassesRegexps.addAll(Arrays.stream(from.clone()) | |
136 | .map(CommonUtils::createPattern) | |
137 | .collect(Collectors.toSet())); | |
138 | } | |
139 | ||
140 | /** | |
141 | * Sets user-excluded pakcages to ignore. All exlcuded packages should end with a period, | |
142 | * so it also appends a dot to a package name. | |
143 | * @param excludedPackages the list of packages to ignore. | |
144 | */ | |
145 | public final void setExcludedPackages(String... excludedPackages) { | |
146 | final List<String> invalidIdentifiers = Arrays.stream(excludedPackages) | |
147 |
2
1. lambda$setExcludedPackages$0 : negated conditional → KILLED 2. lambda$setExcludedPackages$0 : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
.filter(x -> !CommonUtils.isName(x)) |
148 | .collect(Collectors.toList()); | |
149 |
1
1. setExcludedPackages : negated conditional → KILLED |
if (!invalidIdentifiers.isEmpty()) { |
150 | throw new IllegalArgumentException( | |
151 | "the following values are not valid identifiers: " | |
152 | + invalidIdentifiers.stream().collect(Collectors.joining(", ", "[", "]"))); | |
153 | } | |
154 | ||
155 | this.excludedPackages = Collections.unmodifiableSet( | |
156 | Arrays.stream(excludedPackages).collect(Collectors.toSet())); | |
157 | } | |
158 | ||
159 | @Override | |
160 | public final void beginTree(DetailAST ast) { | |
161 | fileContext = new FileContext(); | |
162 | } | |
163 | ||
164 | @Override | |
165 | public void visitToken(DetailAST ast) { | |
166 | switch (ast.getType()) { | |
167 | case TokenTypes.PACKAGE_DEF: | |
168 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck::visitPackageDef → SURVIVED |
visitPackageDef(ast); |
169 | break; | |
170 | case TokenTypes.IMPORT: | |
171 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::registerImport → KILLED |
fileContext.registerImport(ast); |
172 | break; | |
173 | case TokenTypes.CLASS_DEF: | |
174 | case TokenTypes.INTERFACE_DEF: | |
175 | case TokenTypes.ANNOTATION_DEF: | |
176 | case TokenTypes.ENUM_DEF: | |
177 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck::visitClassDef → KILLED |
visitClassDef(ast); |
178 | break; | |
179 | case TokenTypes.TYPE: | |
180 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::visitType → KILLED |
fileContext.visitType(ast); |
181 | break; | |
182 | case TokenTypes.LITERAL_NEW: | |
183 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::visitLiteralNew → KILLED |
fileContext.visitLiteralNew(ast); |
184 | break; | |
185 | case TokenTypes.LITERAL_THROWS: | |
186 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::visitLiteralThrows → KILLED |
fileContext.visitLiteralThrows(ast); |
187 | break; | |
188 | default: | |
189 | throw new IllegalArgumentException("Unknown type: " + ast); | |
190 | } | |
191 | } | |
192 | ||
193 | @Override | |
194 | public void leaveToken(DetailAST ast) { | |
195 | switch (ast.getType()) { | |
196 | case TokenTypes.CLASS_DEF: | |
197 | case TokenTypes.INTERFACE_DEF: | |
198 | case TokenTypes.ANNOTATION_DEF: | |
199 | case TokenTypes.ENUM_DEF: | |
200 |
1
1. leaveToken : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck::leaveClassDef → KILLED |
leaveClassDef(); |
201 | break; | |
202 | default: | |
203 | // Do nothing | |
204 | } | |
205 | } | |
206 | ||
207 | /** | |
208 | * Stores package of current class we check. | |
209 | * @param pkg package definition. | |
210 | */ | |
211 | private void visitPackageDef(DetailAST pkg) { | |
212 | final FullIdent ident = FullIdent.createFullIdent(pkg.getLastChild().getPreviousSibling()); | |
213 |
1
1. visitPackageDef : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::setPackageName → SURVIVED |
fileContext.setPackageName(ident.getText()); |
214 | } | |
215 | ||
216 | /** | |
217 | * Creates new context for a given class. | |
218 | * @param classDef class definition node. | |
219 | */ | |
220 | private void visitClassDef(DetailAST classDef) { | |
221 | final String className = classDef.findFirstToken(TokenTypes.IDENT).getText(); | |
222 |
1
1. visitClassDef : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::createNewClassContext → KILLED |
fileContext.createNewClassContext(className, classDef.getLineNo(), classDef.getColumnNo()); |
223 | } | |
224 | ||
225 | /** Restores previous context. */ | |
226 | private void leaveClassDef() { | |
227 |
1
1. leaveClassDef : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::checkCurrentClassAndRestorePrevious → KILLED |
fileContext.checkCurrentClassAndRestorePrevious(); |
228 | } | |
229 | ||
230 | /** | |
231 | * Encapsulates information about classes coupling inside single file. | |
232 | * @noinspection ThisEscapedInObjectConstruction | |
233 | */ | |
234 | private class FileContext { | |
235 | /** A map of (imported class name -> class name with package) pairs. */ | |
236 | private final Map<String, String> importedClassPackage = new HashMap<>(); | |
237 | ||
238 | /** Stack of class contexts. */ | |
239 | private final Deque<ClassContext> classesContexts = new ArrayDeque<>(); | |
240 | ||
241 | /** Current file package. */ | |
242 | private String packageName = ""; | |
243 | ||
244 | /** Current context. */ | |
245 | private ClassContext classContext = new ClassContext(this, "", 0, 0); | |
246 | ||
247 | /** | |
248 | * Retrieves current file package name. | |
249 | * @return Package name. | |
250 | */ | |
251 | public String getPackageName() { | |
252 |
1
1. getPackageName : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::getPackageName to ( if (x != null) null else throw new RuntimeException ) → SURVIVED |
return packageName; |
253 | } | |
254 | ||
255 | /** | |
256 | * Sets current context package name. | |
257 | * @param packageName Package name to be set. | |
258 | */ | |
259 | public void setPackageName(String packageName) { | |
260 | this.packageName = packageName; | |
261 | } | |
262 | ||
263 | /** | |
264 | * Registers given import. This allows us to track imported classes. | |
265 | * @param imp import definition. | |
266 | */ | |
267 | public void registerImport(DetailAST imp) { | |
268 | final FullIdent ident = FullIdent.createFullIdent( | |
269 | imp.getLastChild().getPreviousSibling()); | |
270 | final String fullName = ident.getText(); | |
271 |
2
1. registerImport : Replaced integer subtraction with addition → KILLED 2. registerImport : negated conditional → KILLED |
if (fullName.charAt(fullName.length() - 1) != '*') { |
272 | final int lastDot = fullName.lastIndexOf(DOT); | |
273 |
1
1. registerImport : Replaced integer addition with subtraction → KILLED |
importedClassPackage.put(fullName.substring(lastDot + 1), fullName); |
274 | } | |
275 | } | |
276 | ||
277 | /** | |
278 | * Retrieves class name with packages. Uses previously registered imports to | |
279 | * get the full class name. | |
280 | * @param className Class name to be retrieved. | |
281 | * @return Class name with package name, if found, {@link Optional#empty()} otherwise. | |
282 | */ | |
283 | public Optional<String> getClassNameWithPackage(String className) { | |
284 |
1
1. getClassNameWithPackage : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$FileContext::getClassNameWithPackage to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return Optional.ofNullable(importedClassPackage.get(className)); |
285 | } | |
286 | ||
287 | /** | |
288 | * Creates new inner class context with given name and location. | |
289 | * @param className The class name. | |
290 | * @param lineNo The class line number. | |
291 | * @param columnNo The class column number. | |
292 | */ | |
293 | public void createNewClassContext(String className, int lineNo, int columnNo) { | |
294 |
1
1. createNewClassContext : removed call to java/util/Deque::push → KILLED |
classesContexts.push(classContext); |
295 | classContext = new ClassContext(this, className, lineNo, columnNo); | |
296 | } | |
297 | ||
298 | /** Restores previous context. */ | |
299 | public void checkCurrentClassAndRestorePrevious() { | |
300 |
1
1. checkCurrentClassAndRestorePrevious : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::checkCoupling → KILLED |
classContext.checkCoupling(); |
301 | classContext = classesContexts.pop(); | |
302 | } | |
303 | ||
304 | /** | |
305 | * Visits type token for the current class context. | |
306 | * @param ast TYPE token. | |
307 | */ | |
308 | public void visitType(DetailAST ast) { | |
309 |
1
1. visitType : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::visitType → KILLED |
classContext.visitType(ast); |
310 | } | |
311 | ||
312 | /** | |
313 | * Visits NEW token for the current class context. | |
314 | * @param ast NEW token. | |
315 | */ | |
316 | public void visitLiteralNew(DetailAST ast) { | |
317 |
1
1. visitLiteralNew : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::visitLiteralNew → KILLED |
classContext.visitLiteralNew(ast); |
318 | } | |
319 | ||
320 | /** | |
321 | * Visits THROWS token for the current class context. | |
322 | * @param ast THROWS token. | |
323 | */ | |
324 | public void visitLiteralThrows(DetailAST ast) { | |
325 |
1
1. visitLiteralThrows : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::visitLiteralThrows → KILLED |
classContext.visitLiteralThrows(ast); |
326 | } | |
327 | } | |
328 | ||
329 | /** | |
330 | * Encapsulates information about class coupling. | |
331 | * | |
332 | * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a> | |
333 | * @author o_sukhodolsky | |
334 | */ | |
335 | private class ClassContext { | |
336 | /** Parent file context. */ | |
337 | private final FileContext parentContext; | |
338 | /** | |
339 | * Set of referenced classes. | |
340 | * Sorted by name for predictable error messages in unit tests. | |
341 | */ | |
342 | private final Set<String> referencedClassNames = new TreeSet<>(); | |
343 | /** Own class name. */ | |
344 | private final String className; | |
345 | /* Location of own class. (Used to log violations) */ | |
346 | /** Line number of class definition. */ | |
347 | private final int lineNo; | |
348 | /** Column number of class definition. */ | |
349 | private final int columnNo; | |
350 | ||
351 | /** | |
352 | * Create new context associated with given class. | |
353 | * @param parentContext Parent file context. | |
354 | * @param className name of the given class. | |
355 | * @param lineNo line of class definition. | |
356 | * @param columnNo column of class definition. | |
357 | */ | |
358 | ClassContext(FileContext parentContext, String className, int lineNo, int columnNo) { | |
359 | this.parentContext = parentContext; | |
360 | this.className = className; | |
361 | this.lineNo = lineNo; | |
362 | this.columnNo = columnNo; | |
363 | } | |
364 | ||
365 | /** | |
366 | * Visits throws clause and collects all exceptions we throw. | |
367 | * @param literalThrows throws to process. | |
368 | */ | |
369 | public void visitLiteralThrows(DetailAST literalThrows) { | |
370 | for (DetailAST childAST = literalThrows.getFirstChild(); | |
371 |
1
1. visitLiteralThrows : negated conditional → KILLED |
childAST != null; |
372 | childAST = childAST.getNextSibling()) { | |
373 |
1
1. visitLiteralThrows : negated conditional → KILLED |
if (childAST.getType() != TokenTypes.COMMA) { |
374 |
1
1. visitLiteralThrows : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::addReferencedClassName → KILLED |
addReferencedClassName(childAST); |
375 | } | |
376 | } | |
377 | } | |
378 | ||
379 | /** | |
380 | * Visits type. | |
381 | * @param ast type to process. | |
382 | */ | |
383 | public void visitType(DetailAST ast) { | |
384 | final String fullTypeName = CheckUtils.createFullType(ast).getText(); | |
385 |
1
1. visitType : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::addReferencedClassName → KILLED |
addReferencedClassName(fullTypeName); |
386 | } | |
387 | ||
388 | /** | |
389 | * Visits NEW. | |
390 | * @param ast NEW to process. | |
391 | */ | |
392 | public void visitLiteralNew(DetailAST ast) { | |
393 |
1
1. visitLiteralNew : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::addReferencedClassName → KILLED |
addReferencedClassName(ast.getFirstChild()); |
394 | } | |
395 | ||
396 | /** | |
397 | * Adds new referenced class. | |
398 | * @param ast a node which represents referenced class. | |
399 | */ | |
400 | private void addReferencedClassName(DetailAST ast) { | |
401 | final String fullIdentName = FullIdent.createFullIdent(ast).getText(); | |
402 |
1
1. addReferencedClassName : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck$ClassContext::addReferencedClassName → KILLED |
addReferencedClassName(fullIdentName); |
403 | } | |
404 | ||
405 | /** | |
406 | * Adds new referenced class. | |
407 | * @param referencedClassName class name of the referenced class. | |
408 | */ | |
409 | private void addReferencedClassName(String referencedClassName) { | |
410 |
1
1. addReferencedClassName : negated conditional → KILLED |
if (isSignificant(referencedClassName)) { |
411 | referencedClassNames.add(referencedClassName); | |
412 | } | |
413 | } | |
414 | ||
415 | /** Checks if coupling less than allowed or not. */ | |
416 | public void checkCoupling() { | |
417 | referencedClassNames.remove(className); | |
418 | referencedClassNames.remove(parentContext.getPackageName() + DOT + className); | |
419 | ||
420 |
2
1. checkCoupling : changed conditional boundary → KILLED 2. checkCoupling : negated conditional → KILLED |
if (referencedClassNames.size() > max) { |
421 |
1
1. checkCoupling : removed call to com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck::log → KILLED |
log(lineNo, columnNo, getLogMessageId(), |
422 | referencedClassNames.size(), max, | |
423 | referencedClassNames.toString()); | |
424 | } | |
425 | } | |
426 | ||
427 | /** | |
428 | * Checks if given class shouldn't be ignored and not from java.lang. | |
429 | * @param candidateClassName class to check. | |
430 | * @return true if we should count this class. | |
431 | */ | |
432 | private boolean isSignificant(String candidateClassName) { | |
433 |
1
1. isSignificant : negated conditional → KILLED |
boolean result = !excludedClasses.contains(candidateClassName) |
434 |
1
1. isSignificant : negated conditional → KILLED |
&& !isFromExcludedPackage(candidateClassName); |
435 |
1
1. isSignificant : negated conditional → KILLED |
if (result) { |
436 |
1
1. isSignificant : negated conditional → KILLED |
for (Pattern pattern : excludeClassesRegexps) { |
437 |
1
1. isSignificant : negated conditional → KILLED |
if (pattern.matcher(candidateClassName).matches()) { |
438 | result = false; | |
439 | break; | |
440 | } | |
441 | } | |
442 | } | |
443 |
1
1. isSignificant : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
444 | } | |
445 | ||
446 | /** | |
447 | * Checks if given class should be ignored as it belongs to excluded package. | |
448 | * @param candidateClassName class to check | |
449 | * @return true if we should not count this class. | |
450 | */ | |
451 | private boolean isFromExcludedPackage(String candidateClassName) { | |
452 | String classNameWithPackage = candidateClassName; | |
453 |
1
1. isFromExcludedPackage : negated conditional → KILLED |
if (!candidateClassName.contains(DOT)) { |
454 | classNameWithPackage = parentContext.getClassNameWithPackage(candidateClassName) | |
455 | .orElse(""); | |
456 | } | |
457 | boolean isFromExcludedPackage = false; | |
458 |
1
1. isFromExcludedPackage : negated conditional → KILLED |
if (classNameWithPackage.contains(DOT)) { |
459 | final int lastDotIndex = classNameWithPackage.lastIndexOf(DOT); | |
460 | final String packageName = classNameWithPackage.substring(0, lastDotIndex); | |
461 |
1
1. isFromExcludedPackage : negated conditional → KILLED |
isFromExcludedPackage = packageName.startsWith("java.lang") |
462 |
1
1. isFromExcludedPackage : negated conditional → KILLED |
|| excludedPackages.contains(packageName); |
463 | } | |
464 |
1
1. isFromExcludedPackage : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isFromExcludedPackage; |
465 | } | |
466 | } | |
467 | } | |
Mutations | ||
110 |
1.1 |
|
147 |
1.1 2.2 |
|
149 |
1.1 |
|
168 |
1.1 |
|
171 |
1.1 |
|
177 |
1.1 |
|
180 |
1.1 |
|
183 |
1.1 |
|
186 |
1.1 |
|
200 |
1.1 |
|
213 |
1.1 |
|
222 |
1.1 |
|
227 |
1.1 |
|
252 |
1.1 |
|
271 |
1.1 2.2 |
|
273 |
1.1 |
|
284 |
1.1 |
|
294 |
1.1 |
|
300 |
1.1 |
|
309 |
1.1 |
|
317 |
1.1 |
|
325 |
1.1 |
|
371 |
1.1 |
|
373 |
1.1 |
|
374 |
1.1 |
|
385 |
1.1 |
|
393 |
1.1 |
|
402 |
1.1 |
|
410 |
1.1 |
|
420 |
1.1 2.2 |
|
421 |
1.1 |
|
433 |
1.1 |
|
434 |
1.1 |
|
435 |
1.1 |
|
436 |
1.1 |
|
437 |
1.1 |
|
443 |
1.1 |
|
453 |
1.1 |
|
458 |
1.1 |
|
461 |
1.1 |
|
462 |
1.1 |
|
464 |
1.1 |