001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.metrics; 021 022import com.puppycrawl.tools.checkstyle.api.TokenTypes; 023 024/** 025 * <p> 026 * Measures the number of instantiations of other classes 027 * within the given class. This type of coupling is not caused by inheritance or 028 * the object oriented paradigm. Generally speaking, any data type with other 029 * data types as members or local variable that is an instantiation (object) 030 * of another class has data abstraction coupling (DAC). The higher the DAC, 031 * the more complex the structure of the class. 032 * </p> 033 * <p> 034 * This check processes files in the following way: 035 * </p> 036 * <ol> 037 * <li> 038 * Iterates over the list of tokens (defined below) and counts all mentioned classes. 039 * <ul> 040 * <li> 041 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#IMPORT"> 042 * PACKAGE_DEF</a> 043 * </li> 044 * <li> 045 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#IMPORT"> 046 * IMPORT</a> 047 * </li> 048 * <li> 049 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CLASS_DEF"> 050 * CLASS_DEF</a> 051 * </li> 052 * <li> 053 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INTERFACE_DEF"> 054 * INTERFACE_DEF</a> 055 * </li> 056 * <li> 057 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ENUM_DEF"> 058 * ENUM_DEF</a> 059 * </li> 060 * <li> 061 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_NEW"> 062 * LITERAL_NEW</a> 063 * </li> 064 * </ul> 065 * </li> 066 * <li> 067 * If a class was imported with direct import (i.e. {@code import java.math.BigDecimal}), 068 * or the class was referenced with the package name (i.e. {@code java.math.BigDecimal value}) 069 * and the package was added to the {@code excludedPackages} parameter, the class 070 * does not increase complexity. 071 * </li> 072 * <li> 073 * If a class name was added to the {@code excludedClasses} parameter, 074 * the class does not increase complexity. 075 * </li> 076 * </ol> 077 * <ul> 078 * <li> 079 * Property {@code max} - Specify the maximum threshold allowed. 080 * Type is {@code int}. 081 * Default value is {@code 7}. 082 * </li> 083 * <li> 084 * Property {@code excludedClasses} - Specify user-configured class names to ignore. 085 * Type is {@code java.lang.String[]}. 086 * Default value is {@code ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, 087 * Character, Class, Deprecated, Deque, Double, Exception, Float, FunctionalInterface, 088 * HashMap, HashSet, IllegalArgumentException, IllegalStateException, 089 * IndexOutOfBoundsException, Integer, LinkedList, List, Long, Map, NullPointerException, 090 * Object, Override, Queue, RuntimeException, SafeVarargs, SecurityException, Set, Short, 091 * SortedMap, SortedSet, String, StringBuffer, StringBuilder, SuppressWarnings, Throwable, 092 * TreeMap, TreeSet, UnsupportedOperationException, Void, boolean, byte, char, double, 093 * float, int, long, short, void}. 094 * </li> 095 * <li> 096 * Property {@code excludeClassesRegexps} - Specify user-configured regular 097 * expressions to ignore classes. 098 * Type is {@code java.lang.String[]}. 099 * Default value is {@code ^$}. 100 * </li> 101 * <li> 102 * Property {@code excludedPackages} - Specify user-configured packages to ignore. 103 * Type is {@code java.lang.String[]}. 104 * Default value is {@code {}}. 105 * </li> 106 * </ul> 107 * <p> 108 * To configure the check: 109 * </p> 110 * <pre> 111 * <module name="ClassDataAbstractionCoupling"/> 112 * </pre> 113 * <p> 114 * Example: 115 * </p> 116 * <p> 117 * The check passes without violations in the following: 118 * </p> 119 * <pre> 120 * class InputClassCoupling { 121 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 122 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 123 * Date date = new Date(); // Counted, 1 124 * Time time = new Time(); // Counted, 2 125 * Place place = new Place(); // Counted, 3 126 * } 127 * </pre> 128 * <p> 129 * The check results in a violation in the following: 130 * </p> 131 * <pre> 132 * class InputClassCoupling { 133 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 134 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 135 * Date date = new Date(); // Counted, 1 136 * Time time = new Time(); // Counted, 2 137 * // instantiation of 5 other user defined classes 138 * Place place = new Place(); // violation, total is 8 139 * } 140 * </pre> 141 * <p> 142 * To configure the check with a threshold of 2: 143 * </p> 144 * <pre> 145 * <module name="ClassDataAbstractionCoupling"> 146 * <property name="max" value="2"/> 147 * </module> 148 * </pre> 149 * <p> 150 * Example: 151 * </p> 152 * <p> 153 * The check passes without violations in the following: 154 * </p> 155 * <pre> 156 * class InputClassCoupling { 157 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 158 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 159 * Date date = new Date(); // Counted, 1 160 * Time time = new Time(); // Counted, 2 161 * } 162 * </pre> 163 * <p> 164 * The check results in a violation in the following: 165 * </p> 166 * <pre> 167 * class InputClassCoupling { 168 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 169 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 170 * Date date = new Date(); // Counted, 1 171 * Time time = new Time(); // Counted, 2 172 * Place place = new Place(); // violation, total is 3 173 * } 174 * </pre> 175 * <p> 176 * To configure the check with three excluded classes {@code HashMap}, 177 * {@code HashSet} and {@code Place}: 178 * </p> 179 * <pre> 180 * <module name="ClassDataAbstractionCoupling"> 181 * <property name="excludedClasses" value="HashMap, HashSet, Place"/> 182 * </module> 183 * </pre> 184 * <p> 185 * Example: 186 * </p> 187 * <p> 188 * The check passes without violations in the following: 189 * </p> 190 * <pre> 191 * class InputClassCoupling { 192 * Set set = new HashSet(); // Ignored 193 * Map map = new HashMap(); // Ignored 194 * Date date = new Date(); // Counted, 1 195 * Time time = new Time(); // Counted, 2 196 * // instantiation of 5 other user defined classes 197 * Place place = new Place(); // Ignored 198 * } 199 * </pre> 200 * <p> 201 * The check results in a violation in the following: 202 * </p> 203 * <pre> 204 * class InputClassCoupling { 205 * Set set = new HashSet(); // Ignored 206 * Map map = new HashMap(); // Ignored 207 * Date date = new Date(); // Counted, 1 208 * Time time = new Time(); // Counted, 2 209 * // instantiation of 5 other user defined classes 210 * Space space = new Space(); // violation, total is 8 211 * } 212 * </pre> 213 * <p> 214 * To configure the check to exclude classes with a regular expression 215 * {@code .*Reader$}: 216 * </p> 217 * <pre> 218 * <module name="ClassDataAbstractionCoupling"> 219 * <property name="excludeClassesRegexps" value=".*Reader$"/> 220 * </module> 221 * </pre> 222 * <p> 223 * Example: 224 * </p> 225 * <p> 226 * The check passes without violations in the following: 227 * </p> 228 * <pre> 229 * class InputClassCoupling { 230 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 231 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 232 * Date date = new Date(); // Counted, 1 233 * Time time = new Time(); // Counted, 2 234 * // instantiation of 5 other user defined classes 235 * BufferedReader br = new BufferedReader(); // Ignored 236 * } 237 * </pre> 238 * <p> 239 * The check results in a violation in the following: 240 * </p> 241 * <pre> 242 * class InputClassCoupling { 243 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 244 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 245 * Date date = new Date(); // Counted, 1 246 * Time time = new Time(); // Counted, 2 247 * // instantiation of 5 other user defined classes 248 * File file = new File(); // violation, total is 8 249 * } 250 * </pre> 251 * <p> 252 * To configure the check with an excluded package {@code java.io}: 253 * </p> 254 * <pre> 255 * <module name="ClassDataAbstractionCoupling"> 256 * <property name="excludedPackages" value="java.io"/> 257 * </module> 258 * </pre> 259 * <p> 260 * Example: 261 * </p> 262 * <p> 263 * The check passes without violations in the following: 264 * </p> 265 * <pre> 266 * import java.io.BufferedReader; 267 * 268 * class InputClassCoupling { 269 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 270 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 271 * Date date = new Date(); // Counted, 1 272 * Time time = new Time(); // Counted, 2 273 * // instantiation of 5 other user defined classes 274 * BufferedReader br = new BufferedReader(); // Ignored 275 * } 276 * </pre> 277 * <p> 278 * The check results in a violation in the following: 279 * </p> 280 * <pre> 281 * import java.util.StringTokenizer; 282 * 283 * class InputClassCoupling { 284 * Set set = new HashSet(); // HashSet ignored due to default excludedClasses property 285 * Map map = new HashMap(); // HashMap ignored due to default excludedClasses property 286 * Date date = new Date(); // Counted, 1 287 * Time time = new Time(); // Counted, 2 288 * // instantiation of 5 other user defined classes 289 * StringTokenizer st = new StringTokenizer(); // violation, total is 8 290 * } 291 * </pre> 292 * <p> 293 * Override property {@code excludedPackages} to mark some packages as excluded. 294 * Each member of {@code excludedPackages} should be a valid identifier: 295 * </p> 296 * <ul> 297 * <li> 298 * {@code java.util} - valid, excludes all classes inside {@code java.util}, 299 * but not from the subpackages. 300 * </li> 301 * <li> 302 * {@code java.util.} - invalid, should not end with a dot. 303 * </li> 304 * <li> 305 * {@code java.util.*} - invalid, should not end with a star. 306 * </li> 307 * </ul> 308 * <p> 309 * Note, that checkstyle will ignore all classes from the {@code java.lang} 310 * package and its subpackages, even if the {@code java.lang} was not listed 311 * in the {@code excludedPackages} parameter. 312 * </p> 313 * <p> 314 * Also note, that {@code excludedPackages} will not exclude classes, imported 315 * via wildcard (e.g. {@code import java.math.*}). Instead of wildcard import 316 * you should use direct import (e.g. {@code import java.math.BigDecimal}). 317 * </p> 318 * <p> 319 * Also note, that checkstyle will not exclude classes within the same file 320 * even if it was listed in the {@code excludedPackages} parameter. 321 * For example, assuming the config is 322 * </p> 323 * <pre> 324 * <module name="ClassDataAbstractionCoupling"> 325 * <property name="excludedPackages" value="a.b"/> 326 * </module> 327 * </pre> 328 * <p> 329 * And the file {@code a.b.Foo.java} is: 330 * </p> 331 * <pre> 332 * package a.b; 333 * 334 * import a.b.Bar; 335 * import a.b.c.Baz; 336 * 337 * class Foo { 338 * Bar bar; // Will be ignored, located inside ignored a.b package 339 * Baz baz; // Will not be ignored, located inside a.b.c package 340 * Data data; // Will not be ignored, same file 341 * 342 * class Data { 343 * Foo foo; // Will not be ignored, same file 344 * } 345 * } 346 * </pre> 347 * <p> 348 * The {@code bar} member will not be counted, since the {@code a.b} added 349 * to the {@code excludedPackages}. The {@code baz} member will be counted, 350 * since the {@code a.b.c} was not added to the {@code excludedPackages}. 351 * The {@code data} and {@code foo} members will be counted, as they are inside same file. 352 * </p> 353 * <p> 354 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 355 * </p> 356 * <p> 357 * Violation Message Keys: 358 * </p> 359 * <ul> 360 * <li> 361 * {@code classDataAbstractionCoupling} 362 * </li> 363 * </ul> 364 * 365 * @since 3.4 366 * 367 */ 368public final class ClassDataAbstractionCouplingCheck 369 extends AbstractClassCouplingCheck { 370 371 /** 372 * A key is pointing to the warning message text in "messages.properties" 373 * file. 374 */ 375 public static final String MSG_KEY = "classDataAbstractionCoupling"; 376 377 /** Default allowed complexity. */ 378 private static final int DEFAULT_MAX = 7; 379 380 /** Creates bew instance of the check. */ 381 public ClassDataAbstractionCouplingCheck() { 382 super(DEFAULT_MAX); 383 } 384 385 @Override 386 public int[] getRequiredTokens() { 387 return new int[] { 388 TokenTypes.PACKAGE_DEF, 389 TokenTypes.IMPORT, 390 TokenTypes.CLASS_DEF, 391 TokenTypes.INTERFACE_DEF, 392 TokenTypes.ENUM_DEF, 393 TokenTypes.LITERAL_NEW, 394 }; 395 } 396 397 @Override 398 public int[] getAcceptableTokens() { 399 return getRequiredTokens(); 400 } 401 402 @Override 403 protected String getLogMessageId() { 404 return MSG_KEY; 405 } 406 407}