001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.api; 020 021import java.util.Set; 022 023import com.google.common.collect.Sets; 024 025/** 026 * The base class for checks. 027 * 028 * @author Oliver Burn 029 * @version 1.0 030 * @see <a href="{@docRoot}/../writingchecks.html" target="_top">Writing 031 * your own checks</a> 032 */ 033public abstract class Check extends AbstractViolationReporter 034{ 035 /** default tab width for column reporting */ 036 private static final int DEFAULT_TAB_WIDTH = 8; 037 038 /** the current file contents */ 039 private FileContents fileContents; 040 041 /** the tokens the check is interested in */ 042 private final Set<String> tokens = Sets.newHashSet(); 043 044 /** the object for collecting messages. */ 045 private LocalizedMessages messages; 046 047 /** the tab width for column reporting */ 048 private int tabWidth = DEFAULT_TAB_WIDTH; // meaningful default 049 050 /** 051 * The class loader to load external classes. Not initialised as this must 052 * be set by my creator. 053 */ 054 private ClassLoader loader; 055 056 public boolean isCommentNodesRequired() 057 { 058 return false; 059 } 060 061 /** 062 * Returns the default token a check is interested in. Only used if the 063 * configuration for a check does not define the tokens. 064 * @return the default tokens 065 * @see TokenTypes 066 */ 067 public abstract int[] getDefaultTokens(); 068 069 /** 070 * The configurable token set. 071 * Used to protect Checks against malicious users who specify an 072 * unacceptable token set in the configuration file. 073 * The default implementation returns the check's default tokens. 074 * @return the token set this check is designed for. 075 * @see TokenTypes 076 */ 077 public int[] getAcceptableTokens() 078 { 079 final int[] defaultTokens = getDefaultTokens(); 080 final int[] copy = new int[defaultTokens.length]; 081 System.arraycopy(defaultTokens, 0, copy, 0, defaultTokens.length); 082 return copy; 083 } 084 085 /** 086 * The tokens that this check must be registered for. 087 * @return the token set this must be registered for. 088 * @see TokenTypes 089 */ 090 public int[] getRequiredTokens() 091 { 092 return new int[] {}; 093 } 094 095 /** 096 * Adds a set of tokens the check is interested in. 097 * @param strRep the string representation of the tokens interested in 098 */ 099 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}