View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2014  Oliver Burn
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  package com.puppycrawl.tools.checkstyle.api;
20  
21  import java.util.Set;
22  
23  import com.google.common.collect.Sets;
24  
25  /**
26   * The base class for checks.
27   *
28   * @author Oliver Burn
29   * @version 1.0
30   * @see <a href="{@docRoot}/../writingchecks.html" target="_top">Writing
31   * your own checks</a>
32   */
33  public abstract class Check extends AbstractViolationReporter
34  {
35      /** default tab width for column reporting */
36      private static final int DEFAULT_TAB_WIDTH = 8;
37  
38      /** the current file contents */
39      private FileContents fileContents;
40  
41      /** the tokens the check is interested in */
42      private final Set<String> tokens = Sets.newHashSet();
43  
44      /** the object for collecting messages. */
45      private LocalizedMessages messages;
46  
47      /** the tab width for column reporting */
48      private int tabWidth = DEFAULT_TAB_WIDTH; // meaningful default
49  
50      /**
51       * The class loader to load external classes. Not initialised as this must
52       * be set by my creator.
53       */
54      private ClassLoader loader;
55  
56      public boolean isCommentNodesRequired()
57      {
58          return false;
59      }
60  
61      /**
62       * Returns the default token a check is interested in. Only used if the
63       * configuration for a check does not define the tokens.
64       * @return the default tokens
65       * @see TokenTypes
66       */
67      public abstract int[] getDefaultTokens();
68  
69      /**
70       * The configurable token set.
71       * Used to protect Checks against malicious users who specify an
72       * unacceptable token set in the configuration file.
73       * The default implementation returns the check's default tokens.
74       * @return the token set this check is designed for.
75       * @see TokenTypes
76       */
77      public int[] getAcceptableTokens()
78      {
79          final int[] defaultTokens = getDefaultTokens();
80          final int[] copy = new int[defaultTokens.length];
81          System.arraycopy(defaultTokens, 0, copy, 0, defaultTokens.length);
82          return copy;
83      }
84  
85      /**
86       * The tokens that this check must be registered for.
87       * @return the token set this must be registered for.
88       * @see TokenTypes
89       */
90      public int[] getRequiredTokens()
91      {
92          return new int[] {};
93      }
94  
95      /**
96       * Adds a set of tokens the check is interested in.
97       * @param strRep the string representation of the tokens interested in
98       */
99      public final void setTokens(String[] strRep)
100     {
101         for (final String s : strRep) {
102             tokens.add(s);
103         }
104     }
105 
106     /**
107      * Returns the tokens registered for the check.
108      * @return the set of token names
109      */
110     public final Set<String> getTokenNames()
111     {
112         return tokens;
113     }
114 
115     /**
116      * Set the global object used to collect messages.
117      * @param messages the messages to log with
118      */
119     public final void setMessages(LocalizedMessages messages)
120     {
121         this.messages = messages;
122     }
123 
124     /**
125      * Initialise the check. This is the time to verify that the check has
126      * everything required to perform it job.
127      */
128     public void init()
129     {
130     }
131 
132     /**
133      * Destroy the check. It is being retired from service.
134      */
135     public void destroy()
136     {
137     }
138 
139     /**
140      * Called before the starting to process a tree. Ideal place to initialise
141      * information that is to be collected whilst processing a tree.
142      * @param rootAST the root of the tree
143      */
144     public void beginTree(DetailAST rootAST)
145     {
146     }
147 
148     /**
149      * Called after finished processing a tree. Ideal place to report on
150      * information collected whilst processing a tree.
151      * @param rootAST the root of the tree
152      */
153     public void finishTree(DetailAST rootAST)
154     {
155     }
156 
157     /**
158      * Called to process a token.
159      * @param ast the token to process
160      */
161     public void visitToken(DetailAST ast)
162     {
163     }
164 
165     /**
166      * Called after all the child nodes have been process.
167      * @param ast the token leaving
168      */
169     public void leaveToken(DetailAST ast)
170     {
171     }
172 
173     /**
174      * Returns the lines associated with the tree.
175      * @return the file contents
176      */
177     public final String[] getLines()
178     {
179         return getFileContents().getLines();
180     }
181 
182     /**
183      * Returns the line associated with the tree.
184      * @param index index of the line
185      * @return the line from the file contents
186      */
187     public final String getLine(int index)
188     {
189         return getFileContents().getLine(index);
190     }
191 
192     /**
193      * Set the file contents associated with the tree.
194      * @param contents the manager
195      */
196     public final void setFileContents(FileContents contents)
197     {
198         fileContents = contents;
199     }
200 
201     /**
202      * Returns the file contents associated with the tree.
203      * @return the file contents
204      */
205     public final FileContents getFileContents()
206     {
207         return fileContents;
208     }
209 
210     /**
211      * Set the class loader associated with the tree.
212      * @param loader the class loader
213      */
214     public final void setClassLoader(ClassLoader loader)
215     {
216         this.loader = loader;
217     }
218 
219     /**
220      * Returns the class loader associated with the tree.
221      * @return the class loader
222      */
223     public final ClassLoader getClassLoader()
224     {
225         return loader;
226     }
227 
228     /** @return the tab width to report errors with */
229     protected final int getTabWidth()
230     {
231         return tabWidth;
232     }
233 
234     /**
235      * Set the tab width to report errors with.
236      * @param tabWidth an <code>int</code> value
237      */
238     public final void setTabWidth(int tabWidth)
239     {
240         this.tabWidth = tabWidth;
241     }
242 
243     @Override
244     public final void log(int line, String key, Object... args)
245     {
246         messages.add(
247             new LocalizedMessage(
248                 line,
249                 getMessageBundle(),
250                 key,
251                 args,
252                 getSeverityLevel(),
253                 getId(),
254                 this.getClass(),
255                 this.getCustomMessages().get(key)));
256     }
257 
258 
259     @Override
260     public final void log(int lineNo, int colNo, String key,
261             Object... args)
262     {
263         final int col = 1 + Utils.lengthExpandedTabs(
264             getLines()[lineNo - 1], colNo, getTabWidth());
265         messages.add(
266             new LocalizedMessage(
267                 lineNo,
268                 col,
269                 getMessageBundle(),
270                 key,
271                 args,
272                 getSeverityLevel(),
273                 getId(),
274                 this.getClass(),
275                 this.getCustomMessages().get(key)));
276     }
277 }