001///////////////////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
003// Copyright (C) 2001-2025 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        };
087    }
088
089    @Override
090    public int[] getAcceptableTokens() {
091        return getRequiredTokens();
092    }
093
094    @Override
095    protected String getLogMessageId() {
096        return MSG_KEY;
097    }
098
099    /**
100     * Setter to specify user-configured regular expressions to ignore classes.
101     *
102     * @param from array representing regular expressions of classes to ignore.
103     * @propertySince 7.7
104     * @noinspection RedundantMethodOverride
105     * @noinspectionreason Display module's unique property version
106     */
107    @Override
108    public void setExcludeClassesRegexps(Pattern... from) {
109        super.setExcludeClassesRegexps(from);
110    }
111
112    /**
113     * Setter to specify user-configured class names to ignore.
114     *
115     * @param excludedClasses classes to ignore.
116     * @propertySince 5.7
117     * @noinspection RedundantMethodOverride
118     * @noinspectionreason Display module's unique property version
119     */
120    @Override
121    public void setExcludedClasses(String... excludedClasses) {
122        super.setExcludedClasses(excludedClasses);
123    }
124
125    /**
126     * Setter to specify user-configured packages to ignore.
127     *
128     * @param excludedPackages packages to ignore.
129     * @throws IllegalArgumentException if there are invalid identifiers among the packages.
130     * @propertySince 7.7
131     * @noinspection RedundantMethodOverride
132     * @noinspectionreason Display module's unique property version
133     */
134    @Override
135    public void setExcludedPackages(String... excludedPackages) {
136        super.setExcludedPackages(excludedPackages);
137    }
138
139}