Coverage Report - com.puppycrawl.tools.checkstyle.checks.sizes.ExecutableStatementCountCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
ExecutableStatementCountCheck
95%
42/44
60%
18/30
2.333
ExecutableStatementCountCheck$Context
100%
8/8
N/A
2.333
 
 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.checks.sizes;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.Check;
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.FastStack;
 24  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 25  
 
 26  
 /**
 27  
  * Restricts the number of executable statements to a specified limit
 28  
  * (default = 30).
 29  
  * @author Simon Harris
 30  
  */
 31  
 public final class ExecutableStatementCountCheck
 32  
     extends Check
 33  
 {
 34  
     /** default threshold */
 35  
     private static final int DEFAULT_MAX = 30;
 36  
 
 37  
     /** threshold to report error for */
 38  
     private int mMax;
 39  
 
 40  
     /** Stack of method contexts. */
 41  5
     private final FastStack<Context> mContextStack = FastStack.newInstance();
 42  
 
 43  
     /** Current method context. */
 44  
     private Context mContext;
 45  
 
 46  
     /** Constructs a <code>ExecutableStatementCountCheck</code>. */
 47  
     public ExecutableStatementCountCheck()
 48  5
     {
 49  5
         setMax(DEFAULT_MAX);
 50  5
     }
 51  
 
 52  
     @Override
 53  
     public int[] getDefaultTokens()
 54  
     {
 55  5
         return new int[] {
 56  
             TokenTypes.CTOR_DEF,
 57  
             TokenTypes.METHOD_DEF,
 58  
             TokenTypes.INSTANCE_INIT,
 59  
             TokenTypes.STATIC_INIT,
 60  
             TokenTypes.SLIST,
 61  
         };
 62  
     }
 63  
 
 64  
     @Override
 65  
     public int[] getRequiredTokens()
 66  
     {
 67  4
         return new int[] {TokenTypes.SLIST};
 68  
     }
 69  
 
 70  
     /**
 71  
      * Gets the maximum threshold.
 72  
      * @return the maximum threshold.
 73  
      */
 74  
     public int getMax()
 75  
     {
 76  40
         return mMax;
 77  
     }
 78  
 
 79  
     /**
 80  
      * Sets the maximum threshold.
 81  
      * @param aMax the maximum threshold.
 82  
      */
 83  
     public void setMax(int aMax)
 84  
     {
 85  10
         mMax = aMax;
 86  10
     }
 87  
 
 88  
     @Override
 89  
     public void beginTree(DetailAST aRootAST)
 90  
     {
 91  5
         mContext = null;
 92  5
         mContextStack.clear();
 93  5
     }
 94  
 
 95  
     @Override
 96  
     public void visitToken(DetailAST aAST)
 97  
     {
 98  190
         switch (aAST.getType()) {
 99  
         case TokenTypes.CTOR_DEF:
 100  
         case TokenTypes.METHOD_DEF:
 101  
         case TokenTypes.INSTANCE_INIT:
 102  
         case TokenTypes.STATIC_INIT:
 103  20
             visitMemberDef(aAST);
 104  20
             break;
 105  
         case TokenTypes.SLIST:
 106  170
             visitSlist(aAST);
 107  170
             break;
 108  
         default:
 109  0
             throw new IllegalStateException(aAST.toString());
 110  
         }
 111  190
     }
 112  
 
 113  
     @Override
 114  
     public void leaveToken(DetailAST aAST)
 115  
     {
 116  190
         switch (aAST.getType()) {
 117  
         case TokenTypes.CTOR_DEF:
 118  
         case TokenTypes.METHOD_DEF:
 119  
         case TokenTypes.INSTANCE_INIT:
 120  
         case TokenTypes.STATIC_INIT:
 121  20
             leaveMemberDef(aAST);
 122  20
             break;
 123  
         case TokenTypes.SLIST:
 124  
             // Do nothing
 125  170
             break;
 126  
         default:
 127  0
             throw new IllegalStateException(aAST.toString());
 128  
         }
 129  190
     }
 130  
 
 131  
     /**
 132  
      * Process the start of the member definition.
 133  
      * @param aAST the token representing the member definition.
 134  
      */
 135  
     private void visitMemberDef(DetailAST aAST)
 136  
     {
 137  20
         mContextStack.push(mContext);
 138  20
         mContext = new Context(aAST);
 139  20
     }
 140  
 
 141  
     /**
 142  
      * Process the end of a member definition.
 143  
      *
 144  
      * @param aAST the token representing the member definition.
 145  
      */
 146  
     private void leaveMemberDef(DetailAST aAST)
 147  
     {
 148  20
         final int count = mContext.getCount();
 149  20
         if (count > getMax()) {
 150  20
             log(aAST.getLineNo(), aAST.getColumnNo(),
 151  
                     "executableStatementCount", count, getMax());
 152  
         }
 153  20
         mContext = mContextStack.pop();
 154  20
     }
 155  
 
 156  
     /**
 157  
      * Process the end of a statement list.
 158  
      *
 159  
      * @param aAST the token representing the statement list.
 160  
      */
 161  
     private void visitSlist(DetailAST aAST)
 162  
     {
 163  170
         if (mContext != null) {
 164  
             // find member AST for the statement list
 165  70
             final DetailAST contextAST = mContext.getAST();
 166  70
             DetailAST parent = aAST.getParent();
 167  250
             while (parent != null) {
 168  250
                 final int type = parent.getType();
 169  250
                 if ((type == TokenTypes.CTOR_DEF)
 170  
                     || (type == TokenTypes.METHOD_DEF)
 171  
                     || (type == TokenTypes.INSTANCE_INIT)
 172  
                     || (type == TokenTypes.STATIC_INIT))
 173  
                 {
 174  70
                     if (parent == contextAST) {
 175  68
                         mContext.addCount(aAST.getChildCount() / 2);
 176  
                     }
 177  
                     break;
 178  
                 }
 179  180
                 parent = parent.getParent();
 180  180
             }
 181  
         }
 182  170
     }
 183  
 
 184  
     /**
 185  
      * Class to encapsulate counting information about one member.
 186  
      * @author Simon Harris
 187  
      */
 188  
     private static class Context
 189  
     {
 190  
         /** Member AST node. */
 191  
         private final DetailAST mAST;
 192  
 
 193  
         /** Counter for context elements. */
 194  
         private int mCount;
 195  
 
 196  
         /**
 197  
          * Creates new member context.
 198  
          * @param aAST member AST node.
 199  
          */
 200  
         public Context(DetailAST aAST)
 201  20
         {
 202  20
             mAST = aAST;
 203  20
             mCount = 0;
 204  20
         }
 205  
 
 206  
         /**
 207  
          * Increase count.
 208  
          * @param aCount the count increment.
 209  
          */
 210  
         public void addCount(int aCount)
 211  
         {
 212  68
             mCount += aCount;
 213  68
         }
 214  
 
 215  
         /**
 216  
          * Gets the member AST node.
 217  
          * @return the member AST node.
 218  
          */
 219  
         public DetailAST getAST()
 220  
         {
 221  70
             return mAST;
 222  
         }
 223  
 
 224  
         /**
 225  
          * Gets the count.
 226  
          * @return the count.
 227  
          */
 228  
         public int getCount()
 229  
         {
 230  20
             return mCount;
 231  
         }
 232  
     }
 233  
 }