Coverage Report - com.puppycrawl.tools.checkstyle.api.AbstractCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractCheck
100%
56/56
N/A
0
AbstractCheck$1
N/A
N/A
0
AbstractCheck$FileContext
100%
2/2
N/A
0
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2018 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  
 
 20  
 package com.puppycrawl.tools.checkstyle.api;
 21  
 
 22  
 import java.util.Collections;
 23  
 import java.util.HashSet;
 24  
 import java.util.Set;
 25  
 import java.util.SortedSet;
 26  
 import java.util.TreeSet;
 27  
 
 28  
 import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
 29  
 
 30  
 /**
 31  
  * The base class for checks.
 32  
  *
 33  
  * @author Oliver Burn
 34  
  * @see <a href="{@docRoot}/../writingchecks.html" target="_top">Writing
 35  
  * your own checks</a>
 36  
  * @noinspection NoopMethodInAbstractClass
 37  
  */
 38  2968
 public abstract class AbstractCheck extends AbstractViolationReporter {
 39  
 
 40  
     /** Default tab width for column reporting. */
 41  
     private static final int DEFAULT_TAB_WIDTH = 8;
 42  
 
 43  
     /**
 44  
      * The check context.
 45  
      * @noinspection ThreadLocalNotStaticFinal
 46  
      */
 47  4482
     private final ThreadLocal<FileContext> context = ThreadLocal.withInitial(FileContext::new);
 48  
 
 49  
     /** The tokens the check is interested in. */
 50  2968
     private final Set<String> tokens = new HashSet<>();
 51  
 
 52  
     /** The tab width for column reporting. */
 53  2968
     private int tabWidth = DEFAULT_TAB_WIDTH;
 54  
 
 55  
     /**
 56  
      * The class loader to load external classes. Not initialized as this must
 57  
      * be set by my creator.
 58  
      */
 59  
     private ClassLoader classLoader;
 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 abstract int[] getAcceptableTokens();
 78  
 
 79  
     /**
 80  
      * The tokens that this check must be registered for.
 81  
      * @return the token set this must be registered for.
 82  
      * @see TokenTypes
 83  
      */
 84  
     public abstract int[] getRequiredTokens();
 85  
 
 86  
     /**
 87  
      * Whether comment nodes are required or not.
 88  
      * @return false as a default value.
 89  
      */
 90  
     public boolean isCommentNodesRequired() {
 91  11575
         return false;
 92  
     }
 93  
 
 94  
     /**
 95  
      * Adds a set of tokens the check is interested in.
 96  
      * @param strRep the string representation of the tokens interested in
 97  
      * @noinspection WeakerAccess
 98  
      */
 99  
     public final void setTokens(String... strRep) {
 100  222
         Collections.addAll(tokens, strRep);
 101  222
     }
 102  
 
 103  
     /**
 104  
      * Returns the tokens registered for the check.
 105  
      * @return the set of token names
 106  
      */
 107  
     public final Set<String> getTokenNames() {
 108  1941
         return Collections.unmodifiableSet(tokens);
 109  
     }
 110  
 
 111  
     /**
 112  
      * Returns the sorted set of {@link LocalizedMessage}.
 113  
      * @return the sorted set of {@link LocalizedMessage}.
 114  
      */
 115  
     public SortedSet<LocalizedMessage> getMessages() {
 116  1526
         return new TreeSet<>(context.get().messages);
 117  
     }
 118  
 
 119  
     /**
 120  
      * Clears the sorted set of {@link LocalizedMessage} of the check.
 121  
      */
 122  
     public final void clearMessages() {
 123  1515
         context.get().messages.clear();
 124  1515
     }
 125  
 
 126  
     /**
 127  
      * Initialize the check. This is the time to verify that the check has
 128  
      * everything required to perform it job.
 129  
      */
 130  
     public void init() {
 131  
         // No code by default, should be overridden only by demand at subclasses
 132  1836
     }
 133  
 
 134  
     /**
 135  
      * Destroy the check. It is being retired from service.
 136  
      */
 137  
     public void destroy() {
 138  
         // No code by default, should be overridden only by demand at subclasses
 139  1497
     }
 140  
 
 141  
     /**
 142  
      * Called before the starting to process a tree. Ideal place to initialize
 143  
      * information that is to be collected whilst processing a tree.
 144  
      * @param rootAST the root of the tree
 145  
      */
 146  
     public void beginTree(DetailAST rootAST) {
 147  
         // No code by default, should be overridden only by demand at subclasses
 148  898
     }
 149  
 
 150  
     /**
 151  
      * Called after finished processing a tree. Ideal place to report on
 152  
      * information collected whilst processing a tree.
 153  
      * @param rootAST the root of the tree
 154  
      */
 155  
     public void finishTree(DetailAST rootAST) {
 156  
         // No code by default, should be overridden only by demand at subclasses
 157  1346
     }
 158  
 
 159  
     /**
 160  
      * Called to process a token.
 161  
      * @param ast the token to process
 162  
      */
 163  
     public void visitToken(DetailAST ast) {
 164  
         // No code by default, should be overridden only by demand at subclasses
 165  1
     }
 166  
 
 167  
     /**
 168  
      * Called after all the child nodes have been process.
 169  
      * @param ast the token leaving
 170  
      */
 171  
     public void leaveToken(DetailAST ast) {
 172  
         // No code by default, should be overridden only by demand at subclasses
 173  113039
     }
 174  
 
 175  
     /**
 176  
      * Returns the lines associated with the tree.
 177  
      * @return the file contents
 178  
      */
 179  
     public final String[] getLines() {
 180  7618
         return context.get().fileContents.getLines();
 181  
     }
 182  
 
 183  
     /**
 184  
      * Returns the line associated with the tree.
 185  
      * @param index index of the line
 186  
      * @return the line from the file contents
 187  
      */
 188  
     public final String getLine(int index) {
 189  62949
         return context.get().fileContents.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  1516
         context.get().fileContents = contents;
 198  1516
     }
 199  
 
 200  
     /**
 201  
      * Returns the file contents associated with the tree.
 202  
      * @return the file contents
 203  
      * @noinspection WeakerAccess
 204  
      */
 205  
     public final FileContents getFileContents() {
 206  1857
         return context.get().fileContents;
 207  
     }
 208  
 
 209  
     /**
 210  
      * Set the class loader associated with the tree.
 211  
      * @param classLoader the class loader
 212  
      */
 213  
     public final void setClassLoader(ClassLoader classLoader) {
 214  1926
         this.classLoader = classLoader;
 215  1926
     }
 216  
 
 217  
     /**
 218  
      * Returns the class loader associated with the tree.
 219  
      * @return the class loader
 220  
      */
 221  
     public final ClassLoader getClassLoader() {
 222  16
         return classLoader;
 223  
     }
 224  
 
 225  
     /**
 226  
      * Get tab width to report errors with.
 227  
      * @return the tab width to report errors with
 228  
      */
 229  
     protected final int getTabWidth() {
 230  59802
         return tabWidth;
 231  
     }
 232  
 
 233  
     /**
 234  
      * Set the tab width to report errors with.
 235  
      * @param tabWidth an {@code int} value
 236  
      */
 237  
     public final void setTabWidth(int tabWidth) {
 238  2003
         this.tabWidth = tabWidth;
 239  2003
     }
 240  
 
 241  
     /**
 242  
      * Helper method to log a LocalizedMessage.
 243  
      *
 244  
      * @param ast a node to get line id column numbers associated
 245  
      *             with the message
 246  
      * @param key key to locale message format
 247  
      * @param args arguments to format
 248  
      */
 249  
     public final void log(DetailAST ast, String key, Object... args) {
 250  
         // CommonUtils.lengthExpandedTabs returns column number considering tabulation
 251  
         // characters, it takes line from the file by line number, ast column number and tab
 252  
         // width as arguments. Returned value is 0-based, but user must see column number starting
 253  
         // from 1, that is why result of the method CommonUtils.lengthExpandedTabs
 254  
         // is increased by one.
 255  
 
 256  3016
         final int col = 1 + CommonUtils.lengthExpandedTabs(
 257  1508
                 getLines()[ast.getLineNo() - 1], ast.getColumnNo(), tabWidth);
 258  3016
         context.get().messages.add(
 259  
                 new LocalizedMessage(
 260  1508
                         ast.getLineNo(),
 261  
                         col,
 262  1508
                         ast.getColumnNo(),
 263  1508
                         ast.getType(),
 264  1508
                         getMessageBundle(),
 265  
                         key,
 266  
                         args,
 267  1508
                         getSeverityLevel(),
 268  1508
                         getId(),
 269  1508
                         getClass(),
 270  1508
                         getCustomMessages().get(key)));
 271  1508
     }
 272  
 
 273  
     @Override
 274  
     public final void log(int line, String key, Object... args) {
 275  134918
         context.get().messages.add(
 276  
             new LocalizedMessage(
 277  
                 line,
 278  67459
                 getMessageBundle(),
 279  
                 key,
 280  
                 args,
 281  67459
                 getSeverityLevel(),
 282  67459
                 getId(),
 283  67459
                 getClass(),
 284  67459
                 getCustomMessages().get(key)));
 285  67458
     }
 286  
 
 287  
     @Override
 288  
     public final void log(int lineNo, int colNo, String key,
 289  
             Object... args) {
 290  6112
         final int col = 1 + CommonUtils.lengthExpandedTabs(
 291  3056
             getLines()[lineNo - 1], colNo, tabWidth);
 292  6112
         context.get().messages.add(
 293  
             new LocalizedMessage(
 294  
                 lineNo,
 295  
                 col,
 296  3056
                 getMessageBundle(),
 297  
                 key,
 298  
                 args,
 299  3056
                 getSeverityLevel(),
 300  3056
                 getId(),
 301  3056
                 getClass(),
 302  3056
                 getCustomMessages().get(key)));
 303  3056
     }
 304  
 
 305  
     /**
 306  
      * The actual context holder.
 307  
      */
 308  152032
     private static class FileContext {
 309  
 
 310  
         /** The sorted set for collecting messages. */
 311  1514
         private final SortedSet<LocalizedMessage> messages = new TreeSet<>();
 312  
 
 313  
         /** The current file contents. */
 314  
         private FileContents fileContents;
 315  
 
 316  
     }
 317  
 
 318  
 }