001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2014  Oliver Burn
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////////////////////////////////////////////////////////////////////////////////
019package com.puppycrawl.tools.checkstyle.api;
020
021import com.google.common.collect.Sets;
022import java.util.Set;
023
024/**
025 * The base class for checks.
026 *
027 * @author Oliver Burn
028 * @version 1.0
029 * @see <a href="{@docRoot}/../writingchecks.html" target="_top">Writing
030 * your own checks</a>
031 */
032public abstract class Check extends AbstractViolationReporter
033{
034    /** default tab width for column reporting */
035    private static final int DEFAULT_TAB_WIDTH = 8;
036
037    /** the current file contents */
038    private FileContents mFileContents;
039
040    /** the tokens the check is interested in */
041    private final Set<String> mTokens = Sets.newHashSet();
042
043    /** the object for collecting messages. */
044    private LocalizedMessages mMessages;
045
046    /** the tab width for column reporting */
047    private int mTabWidth = DEFAULT_TAB_WIDTH; // meaningful default
048
049    /**
050     * The class loader to load external classes. Not initialised as this must
051     * be set by my creator.
052     */
053    private ClassLoader mLoader;
054
055    /**
056     * Returns the default token a check is interested in. Only used if the
057     * configuration for a check does not define the tokens.
058     * @return the default tokens
059     * @see TokenTypes
060     */
061    public abstract int[] getDefaultTokens();
062
063    /**
064     * The configurable token set.
065     * Used to protect Checks against malicious users who specify an
066     * unacceptable token set in the configuration file.
067     * The default implementation returns the check's default tokens.
068     * @return the token set this check is designed for.
069     * @see TokenTypes
070     */
071    public int[] getAcceptableTokens()
072    {
073        final int[] defaultTokens = getDefaultTokens();
074        final int[] copy = new int[defaultTokens.length];
075        System.arraycopy(defaultTokens, 0, copy, 0, defaultTokens.length);
076        return copy;
077    }
078
079    /**
080     * The tokens that this check must be registered for.
081     * @return the token set this must be registered for.
082     * @see TokenTypes
083     */
084    public int[] getRequiredTokens()
085    {
086        return new int[] {};
087    }
088
089    /**
090     * Adds a set of tokens the check is interested in.
091     * @param aStrRep the string representation of the tokens interested in
092     */
093    public final void setTokens(String[] aStrRep)
094    {
095        for (final String s : aStrRep) {
096            mTokens.add(s);
097        }
098    }
099
100    /**
101     * Returns the tokens registered for the check.
102     * @return the set of token names
103     */
104    public final Set<String> getTokenNames()
105    {
106        return mTokens;
107    }
108
109    /**
110     * Set the global object used to collect messages.
111     * @param aMessages the messages to log with
112     */
113    public final void setMessages(LocalizedMessages aMessages)
114    {
115        mMessages = aMessages;
116    }
117
118    /**
119     * Initialise the check. This is the time to verify that the check has
120     * everything required to perform it job.
121     */
122    public void init()
123    {
124    }
125
126    /**
127     * Destroy the check. It is being retired from service.
128     */
129    public void destroy()
130    {
131    }
132
133    /**
134     * Called before the starting to process a tree. Ideal place to initialise
135     * information that is to be collected whilst processing a tree.
136     * @param aRootAST the root of the tree
137     */
138    public void beginTree(DetailAST aRootAST)
139    {
140    }
141
142    /**
143     * Called after finished processing a tree. Ideal place to report on
144     * information collected whilst processing a tree.
145     * @param aRootAST the root of the tree
146     */
147    public void finishTree(DetailAST aRootAST)
148    {
149    }
150
151    /**
152     * Called to process a token.
153     * @param aAST the token to process
154     */
155    public void visitToken(DetailAST aAST)
156    {
157    }
158
159    /**
160     * Called after all the child nodes have been process.
161     * @param aAST the token leaving
162     */
163    public void leaveToken(DetailAST aAST)
164    {
165    }
166
167    /**
168     * Returns the lines associated with the tree.
169     * @return the file contents
170     */
171    public final String[] getLines()
172    {
173        return getFileContents().getLines();
174    }
175
176    /**
177     * Set the file contents associated with the tree.
178     * @param aContents the manager
179     */
180    public final void setFileContents(FileContents aContents)
181    {
182        mFileContents = aContents;
183    }
184
185    /**
186     * Returns the file contents associated with the tree.
187     * @return the file contents
188     */
189    public final FileContents getFileContents()
190    {
191        return mFileContents;
192    }
193
194    /**
195     * Set the class loader associated with the tree.
196     * @param aLoader the class loader
197     */
198    public final void setClassLoader(ClassLoader aLoader)
199    {
200        mLoader = aLoader;
201    }
202
203    /**
204     * Returns the class loader associated with the tree.
205     * @return the class loader
206     */
207    public final ClassLoader getClassLoader()
208    {
209        return mLoader;
210    }
211
212    /** @return the tab width to report errors with */
213    protected final int getTabWidth()
214    {
215        return mTabWidth;
216    }
217
218    /**
219     * Set the tab width to report errors with.
220     * @param aTabWidth an <code>int</code> value
221     */
222    public final void setTabWidth(int aTabWidth)
223    {
224        mTabWidth = aTabWidth;
225    }
226
227    @Override
228    public final void log(int aLine, String aKey, Object... aArgs)
229    {
230        mMessages.add(
231            new LocalizedMessage(
232                aLine,
233                getMessageBundle(),
234                aKey,
235                aArgs,
236                getSeverityLevel(),
237                getId(),
238                this.getClass(),
239                this.getCustomMessages().get(aKey)));
240    }
241
242
243    @Override
244    public final void log(int aLineNo, int aColNo, String aKey,
245            Object... aArgs)
246    {
247        final int col = 1 + Utils.lengthExpandedTabs(
248            getLines()[aLineNo - 1], aColNo, getTabWidth());
249        mMessages.add(
250            new LocalizedMessage(
251                aLineNo,
252                col,
253                getMessageBundle(),
254                aKey,
255                aArgs,
256                getSeverityLevel(),
257                getId(),
258                this.getClass(),
259                this.getCustomMessages().get(aKey)));
260    }
261}