001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2026 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 java.util.regex.Pattern;
023
024import com.puppycrawl.tools.checkstyle.api.TokenTypes;
025
026/**
027 * <div>
028 * Checks the number of other types a given class/record/interface/enum/annotation
029 * relies on. Also, the square of this has been shown to indicate the amount
030 * of maintenance required in functional programs (on a file basis) at least.
031 * </div>
032 *
033 * <p>
034 * This check processes files in the following way:
035 * </p>
036 * <ol>
037 * <li>
038 * Iterates over all tokens that might contain type reference.
039 * </li>
040 * <li>
041 * If a class was imported with direct import (i.e. {@code import java.math.BigDecimal}),
042 * or the class was referenced with the package name (i.e. {@code java.math.BigDecimal value})
043 * and the package was added to the {@code excludedPackages} parameter,
044 * the class does not increase complexity.
045 * </li>
046 * <li>
047 * If a class name was added to the {@code excludedClasses} parameter,
048 * the class does not increase complexity.
049 * </li>
050 * </ol>
051 *
052 * @since 3.4
053 */
054public final class ClassFanOutComplexityCheck extends AbstractClassCouplingCheck {
055
056    /**
057     * A key is pointing to the warning message text in "messages.properties"
058     * file.
059     */
060    public static final String MSG_KEY = "classFanOutComplexity";
061
062    /** Default value of max value. */
063    private static final int DEFAULT_MAX = 20;
064
065    /** Creates new instance of this check. */
066    public ClassFanOutComplexityCheck() {
067        super(DEFAULT_MAX);
068    }
069
070    @Override
071    public int[] getRequiredTokens() {
072        return new int[] {
073            TokenTypes.PACKAGE_DEF,
074            TokenTypes.IMPORT,
075            TokenTypes.CLASS_DEF,
076            TokenTypes.EXTENDS_CLAUSE,
077            TokenTypes.IMPLEMENTS_CLAUSE,
078            TokenTypes.ANNOTATION,
079            TokenTypes.INTERFACE_DEF,
080            TokenTypes.ENUM_DEF,
081            TokenTypes.TYPE,
082            TokenTypes.LITERAL_NEW,
083            TokenTypes.LITERAL_THROWS,
084            TokenTypes.ANNOTATION_DEF,
085            TokenTypes.RECORD_DEF,
086            TokenTypes.COMPACT_COMPILATION_UNIT,
087        };
088    }
089
090    @Override
091    public int[] getAcceptableTokens() {
092        return getRequiredTokens();
093    }
094
095    @Override
096    protected String getLogMessageId() {
097        return MSG_KEY;
098    }
099
100    /**
101     * Setter to specify user-configured regular expressions to ignore classes.
102     *
103     * @param from array representing regular expressions of classes to ignore.
104     * @propertySince 7.7
105     */
106    @Override
107    public void setExcludeClassesRegexps(Pattern... from) {
108        super.setExcludeClassesRegexps(from);
109    }
110
111    /**
112     * Setter to specify user-configured class names to ignore.
113     *
114     * @param excludedClasses classes to ignore.
115     * @propertySince 5.7
116     */
117    @Override
118    public void setExcludedClasses(String... excludedClasses) {
119        super.setExcludedClasses(excludedClasses);
120    }
121
122    /**
123     * Setter to specify user-configured packages to ignore.
124     *
125     * @param excludedPackages packages to ignore.
126     * @throws IllegalArgumentException if there are invalid identifiers among the packages.
127     * @propertySince 7.7
128     */
129    @Override
130    public void setExcludedPackages(String... excludedPackages) {
131        super.setExcludedPackages(excludedPackages);
132    }
133
134}