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 }