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 }