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 }