001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2021 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.naming;
021
022import com.puppycrawl.tools.checkstyle.api.DetailAST;
023import com.puppycrawl.tools.checkstyle.api.TokenTypes;
024import com.puppycrawl.tools.checkstyle.utils.ScopeUtil;
025
026/**
027 * Abstract class for checking a class member (field/method)'s name conforms to
028 * a specified pattern.
029 *
030 * <p>
031 * This class extends {@link AbstractNameCheck} with support for access level
032 * restrictions. This allows the check to be configured to be applied to one of
033 * the four Java access levels: {@code public}, {@code protected},
034 * {@code "package"}, and {@code private}.
035 * </p>
036 *
037 * <p>Level is configured using the following properties:
038 * <ol>
039 * <li>applyToPublic, default true;</li>
040 * <li>applyToProtected, default true;</li>
041 * <li>applyToPackage, default true;</li>
042 * <li>applyToPrivate, default true;</li>
043 * </ol>
044 *
045 *
046 */
047public abstract class AbstractAccessControlNameCheck
048    extends AbstractNameCheck {
049
050    /** If true, applies the check be public members. */
051    private boolean applyToPublic = true;
052
053    /** If true, applies the check be protected members. */
054    private boolean applyToProtected = true;
055
056    /** If true, applies the check be "package" members. */
057    private boolean applyToPackage = true;
058
059    /** If true, applies the check be private members. */
060    private boolean applyToPrivate = true;
061
062    /**
063     * Creates a new {@code AbstractAccessControlNameCheck} instance.
064     *
065     * @param format
066     *                format to check with
067     */
068    protected AbstractAccessControlNameCheck(String format) {
069        super(format);
070    }
071
072    @Override
073    protected boolean mustCheckName(DetailAST ast) {
074        return shouldCheckInScope(ast.findFirstToken(TokenTypes.MODIFIERS));
075    }
076
077    /**
078     * Should we check member with given modifiers.
079     *
080     * @param modifiers
081     *                modifiers of member to check.
082     * @return true if we should check such member.
083     */
084    protected boolean shouldCheckInScope(DetailAST modifiers) {
085        final boolean isProtected = modifiers
086                .findFirstToken(TokenTypes.LITERAL_PROTECTED) != null;
087        final boolean isPrivate = modifiers
088                .findFirstToken(TokenTypes.LITERAL_PRIVATE) != null;
089        final boolean isPublic = isPublic(modifiers);
090
091        final boolean isPackage = !(isPublic || isProtected || isPrivate);
092
093        return applyToPublic && isPublic
094                || applyToProtected && isProtected
095                || applyToPackage && isPackage
096                || applyToPrivate && isPrivate;
097    }
098
099    /**
100     * Checks if given modifiers has public access.
101     * There are 2 cases - it is either has explicit modifier, or it is
102     * in annotation or interface.
103     *
104     * @param modifiers - modifiers to check
105     * @return true if public
106     */
107    private static boolean isPublic(DetailAST modifiers) {
108        return modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null
109                || ScopeUtil.isInAnnotationBlock(modifiers)
110                || ScopeUtil.isInInterfaceBlock(modifiers)
111                    // interface methods can be private
112                    && modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) == null;
113    }
114
115    /**
116     * Sets whether we should apply the check to public members.
117     *
118     * @param applyTo new value of the property.
119     */
120    public void setApplyToPublic(boolean applyTo) {
121        applyToPublic = applyTo;
122    }
123
124    /**
125     * Sets whether we should apply the check to protected members.
126     *
127     * @param applyTo new value of the property.
128     */
129    public void setApplyToProtected(boolean applyTo) {
130        applyToProtected = applyTo;
131    }
132
133    /**
134     * Sets whether we should apply the check to package-private members.
135     *
136     * @param applyTo new value of the property.
137     */
138    public void setApplyToPackage(boolean applyTo) {
139        applyToPackage = applyTo;
140    }
141
142    /**
143     * Sets whether we should apply the check to private members.
144     *
145     * @param applyTo new value of the property.
146     */
147    public void setApplyToPrivate(boolean applyTo) {
148        applyToPrivate = applyTo;
149    }
150
151}