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 }