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-2017 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  2939
 public abstract class AbstractCheck extends AbstractViolationReporter {
 39  
     /** Default tab width for column reporting. */
 40  
     private static final int DEFAULT_TAB_WIDTH = 8;
 41  
 
 42  
     /**
 43  
      * The check context.
 44  
      * @noinspection ThreadLocalNotStaticFinal
 45  
      */
 46  4436
     private final ThreadLocal<FileContext> context = ThreadLocal.withInitial(FileContext::new);
 47  
 
 48  
     /** The tokens the check is interested in. */
 49  2939
     private final Set<String> tokens = new HashSet<>();
 50  
 
 51  
     /** The tab width for column reporting. */
 52  2939
     private int tabWidth = DEFAULT_TAB_WIDTH;
 53  
 
 54  
     /**
 55  
      * The class loader to load external classes. Not initialized as this must
 56  
      * be set by my creator.
 57  
      */
 58  
     private ClassLoader classLoader;
 59  
 
 60  
     /**
 61  
      * Returns the default token a check is interested in. Only used if the
 62  
      * configuration for a check does not define the tokens.
 63  
      * @return the default tokens
 64  
      * @see TokenTypes
 65  
      */
 66  
     public abstract int[] getDefaultTokens();
 67  
 
 68  
     /**
 69  
      * The configurable token set.
 70  
      * Used to protect Checks against malicious users who specify an
 71  
      * unacceptable token set in the configuration file.
 72  
      * The default implementation returns the check's default tokens.
 73  
      * @return the token set this check is designed for.
 74  
      * @see TokenTypes
 75  
      */
 76  
     public abstract int[] getAcceptableTokens();
 77  
 
 78  
     /**
 79  
      * The tokens that this check must be registered for.
 80  
      * @return the token set this must be registered for.
 81  
      * @see TokenTypes
 82  
      */
 83  
     public abstract int[] getRequiredTokens();
 84  
 
 85  
     /**
 86  
      * Whether comment nodes are required or not.
 87  
      * @return false as a default value.
 88  
      */
 89  
     public boolean isCommentNodesRequired() {
 90  11386
         return false;
 91  
     }
 92  
 
 93  
     /**
 94  
      * Adds a set of tokens the check is interested in.
 95  
      * @param strRep the string representation of the tokens interested in
 96  
      * @noinspection WeakerAccess
 97  
      */
 98  
     public final void setTokens(String... strRep) {
 99  222
         Collections.addAll(tokens, strRep);
 100  222
     }
 101  
 
 102  
     /**
 103  
      * Returns the tokens registered for the check.
 104  
      * @return the set of token names
 105  
      */
 106  
     public final Set<String> getTokenNames() {
 107  1923
         return Collections.unmodifiableSet(tokens);
 108  
     }
 109  
 
 110  
     /**
 111  
      * Returns the sorted set of {@link LocalizedMessage}.
 112  
      * @return the sorted set of {@link LocalizedMessage}.
 113  
      */
 114  
     public SortedSet<LocalizedMessage> getMessages() {
 115  1508
         return new TreeSet<>(context.get().messages);
 116  
     }
 117  
 
 118  
     /**
 119  
      * Clears the sorted set of {@link LocalizedMessage} of the check.
 120  
      */
 121  
     public final void clearMessages() {
 122  1497
         context.get().messages.clear();
 123  1497
     }
 124  
 
 125  
     /**
 126  
      * Initialize the check. This is the time to verify that the check has
 127  
      * everything required to perform it job.
 128  
      */
 129  
     public void init() {
 130  
         // No code by default, should be overridden only by demand at subclasses
 131  1818
     }
 132  
 
 133  
     /**
 134  
      * Destroy the check. It is being retired from service.
 135  
      */
 136  
     public void destroy() {
 137  
         // No code by default, should be overridden only by demand at subclasses
 138  1480
     }
 139  
 
 140  
     /**
 141  
      * Called before the starting to process a tree. Ideal place to initialize
 142  
      * information that is to be collected whilst processing a tree.
 143  
      * @param rootAST the root of the tree
 144  
      */
 145  
     public void beginTree(DetailAST rootAST) {
 146  
         // No code by default, should be overridden only by demand at subclasses
 147  901
     }
 148  
 
 149  
     /**
 150  
      * Called after finished processing a tree. Ideal place to report on
 151  
      * information collected whilst processing a tree.
 152  
      * @param rootAST the root of the tree
 153  
      */
 154  
     public void finishTree(DetailAST rootAST) {
 155  
         // No code by default, should be overridden only by demand at subclasses
 156  1332
     }
 157  
 
 158  
     /**
 159  
      * Called to process a token.
 160  
      * @param ast the token to process
 161  
      */
 162  
     public void visitToken(DetailAST ast) {
 163  
         // No code by default, should be overridden only by demand at subclasses
 164  1
     }
 165  
 
 166  
     /**
 167  
      * Called after all the child nodes have been process.
 168  
      * @param ast the token leaving
 169  
      */
 170  
     public void leaveToken(DetailAST ast) {
 171  
         // No code by default, should be overridden only by demand at subclasses
 172  115208
     }
 173  
 
 174  
     /**
 175  
      * Returns the lines associated with the tree.
 176  
      * @return the file contents
 177  
      */
 178  
     public final String[] getLines() {
 179  7534
         return context.get().fileContents.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  62563
         return context.get().fileContents.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  1498
         context.get().fileContents = contents;
 197  1498
     }
 198  
 
 199  
     /**
 200  
      * Returns the file contents associated with the tree.
 201  
      * @return the file contents
 202  
      * @noinspection WeakerAccess
 203  
      */
 204  
     public final FileContents getFileContents() {
 205  1852
         return context.get().fileContents;
 206  
     }
 207  
 
 208  
     /**
 209  
      * Set the class loader associated with the tree.
 210  
      * @param classLoader the class loader
 211  
      */
 212  
     public final void setClassLoader(ClassLoader classLoader) {
 213  1908
         this.classLoader = classLoader;
 214  1908
     }
 215  
 
 216  
     /**
 217  
      * Returns the class loader associated with the tree.
 218  
      * @return the class loader
 219  
      */
 220  
     public final ClassLoader getClassLoader() {
 221  16
         return classLoader;
 222  
     }
 223  
 
 224  
     /**
 225  
      * Get tab width to report errors with.
 226  
      * @return the tab width to report errors with
 227  
      */
 228  
     protected final int getTabWidth() {
 229  59422
         return tabWidth;
 230  
     }
 231  
 
 232  
     /**
 233  
      * Set the tab width to report errors with.
 234  
      * @param tabWidth an {@code int} value
 235  
      */
 236  
     public final void setTabWidth(int tabWidth) {
 237  1983
         this.tabWidth = tabWidth;
 238  1983
     }
 239  
 
 240  
     /**
 241  
      * Helper method to log a LocalizedMessage.
 242  
      *
 243  
      * @param ast a node to get line id column numbers associated
 244  
      *             with the message
 245  
      * @param key key to locale message format
 246  
      * @param args arguments to format
 247  
      */
 248  
     public final void log(DetailAST ast, String key, Object... args) {
 249  
 
 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  2948
         final int col = 1 + CommonUtils.lengthExpandedTabs(
 257  1474
                 getLines()[ast.getLineNo() - 1], ast.getColumnNo(), tabWidth);
 258  2948
         context.get().messages.add(
 259  
                 new LocalizedMessage(
 260  1474
                         ast.getLineNo(),
 261  
                         col,
 262  1474
                         ast.getColumnNo(),
 263  1474
                         ast.getType(),
 264  1474
                         getMessageBundle(),
 265  
                         key,
 266  
                         args,
 267  1474
                         getSeverityLevel(),
 268  1474
                         getId(),
 269  1474
                         getClass(),
 270  1474
                         getCustomMessages().get(key)));
 271  1474
     }
 272  
 
 273  
     @Override
 274  
     public final void log(int line, String key, Object... args) {
 275  134858
         context.get().messages.add(
 276  
             new LocalizedMessage(
 277  
                 line,
 278  67429
                 getMessageBundle(),
 279  
                 key,
 280  
                 args,
 281  67429
                 getSeverityLevel(),
 282  67429
                 getId(),
 283  67429
                 getClass(),
 284  67429
                 getCustomMessages().get(key)));
 285  67428
     }
 286  
 
 287  
     @Override
 288  
     public final void log(int lineNo, int colNo, String key,
 289  
             Object... args) {
 290  6096
         final int col = 1 + CommonUtils.lengthExpandedTabs(
 291  3048
             getLines()[lineNo - 1], colNo, tabWidth);
 292  6096
         context.get().messages.add(
 293  
             new LocalizedMessage(
 294  
                 lineNo,
 295  
                 col,
 296  3048
                 getMessageBundle(),
 297  
                 key,
 298  
                 args,
 299  3048
                 getSeverityLevel(),
 300  3048
                 getId(),
 301  3048
                 getClass(),
 302  3048
                 getCustomMessages().get(key)));
 303  3048
     }
 304  
 
 305  
     /**
 306  
      * The actual context holder.
 307  
      */
 308  151397
     private static class FileContext {
 309  
         /** The sorted set for collecting messages. */
 310  1497
         private final SortedSet<LocalizedMessage> messages = new TreeSet<>();
 311  
 
 312  
         /** The current file contents. */
 313  
         private FileContents fileContents;
 314  
     }
 315  
 }