| 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 |