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 }