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