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   * @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         Collections.addAll(tokens, strRep);
102     }
103 
104     /**
105      * Returns the tokens registered for the check.
106      * @return the set of token names
107      */
108     public final Set<String> getTokenNames()
109     {
110         return tokens;
111     }
112 
113     /**
114      * Set the global object used to collect messages.
115      * @param messages the messages to log with
116      */
117     public final void setMessages(LocalizedMessages messages)
118     {
119         this.messages = messages;
120     }
121 
122     /**
123      * Initialise the check. This is the time to verify that the check has
124      * everything required to perform it job.
125      */
126     public void init()
127     {
128     }
129 
130     /**
131      * Destroy the check. It is being retired from service.
132      */
133     public void destroy()
134     {
135     }
136 
137     /**
138      * Called before the starting to process a tree. Ideal place to initialise
139      * information that is to be collected whilst processing a tree.
140      * @param rootAST the root of the tree
141      */
142     public void beginTree(DetailAST rootAST)
143     {
144     }
145 
146     /**
147      * Called after finished processing a tree. Ideal place to report on
148      * information collected whilst processing a tree.
149      * @param rootAST the root of the tree
150      */
151     public void finishTree(DetailAST rootAST)
152     {
153     }
154 
155     /**
156      * Called to process a token.
157      * @param ast the token to process
158      */
159     public void visitToken(DetailAST ast)
160     {
161     }
162 
163     /**
164      * Called after all the child nodes have been process.
165      * @param ast the token leaving
166      */
167     public void leaveToken(DetailAST ast)
168     {
169     }
170 
171     /**
172      * Returns the lines associated with the tree.
173      * @return the file contents
174      */
175     public final String[] getLines()
176     {
177         return getFileContents().getLines();
178     }
179 
180     /**
181      * Returns the line associated with the tree.
182      * @param index index of the line
183      * @return the line from the file contents
184      */
185     public final String getLine(int index)
186     {
187         return getFileContents().getLine(index);
188     }
189 
190     /**
191      * Set the file contents associated with the tree.
192      * @param contents the manager
193      */
194     public final void setFileContents(FileContents contents)
195     {
196         fileContents = contents;
197     }
198 
199     /**
200      * Returns the file contents associated with the tree.
201      * @return the file contents
202      */
203     public final FileContents getFileContents()
204     {
205         return fileContents;
206     }
207 
208     /**
209      * Set the class loader associated with the tree.
210      * @param loader the class loader
211      */
212     public final void setClassLoader(ClassLoader loader)
213     {
214         this.loader = loader;
215     }
216 
217     /**
218      * Returns the class loader associated with the tree.
219      * @return the class loader
220      */
221     public final ClassLoader getClassLoader()
222     {
223         return loader;
224     }
225 
226     /** @return the tab width to report errors with */
227     protected final int getTabWidth()
228     {
229         return tabWidth;
230     }
231 
232     /**
233      * Set the tab width to report errors with.
234      * @param tabWidth an <code>int</code> value
235      */
236     public final void setTabWidth(int tabWidth)
237     {
238         this.tabWidth = tabWidth;
239     }
240 
241     @Override
242     public final void log(int line, String key, Object... args)
243     {
244         messages.add(
245             new LocalizedMessage(
246                 line,
247                 getMessageBundle(),
248                 key,
249                 args,
250                 getSeverityLevel(),
251                 getId(),
252                 this.getClass(),
253                 this.getCustomMessages().get(key)));
254     }
255 
256 
257     @Override
258     public final void log(int lineNo, int colNo, String key,
259             Object... args)
260     {
261         final int col = 1 + Utils.lengthExpandedTabs(
262             getLines()[lineNo - 1], colNo, getTabWidth());
263         messages.add(
264             new LocalizedMessage(
265                 lineNo,
266                 col,
267                 getMessageBundle(),
268                 key,
269                 args,
270                 getSeverityLevel(),
271                 getId(),
272                 this.getClass(),
273                 this.getCustomMessages().get(key)));
274     }
275 }