Coverage Report - com.puppycrawl.tools.checkstyle.checks.sizes.MethodLengthCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
MethodLengthCheck
100%
27/27
100%
12/12
1.857
 
 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.checks.sizes;
 21  
 
 22  
 import com.puppycrawl.tools.checkstyle.StatelessCheck;
 23  
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
 24  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 25  
 import com.puppycrawl.tools.checkstyle.api.FileContents;
 26  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 27  
 import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
 28  
 
 29  
 /**
 30  
  * <p>
 31  
  * Checks for long methods.
 32  
  * </p>
 33  
  * <p>
 34  
  * Rationale: If a method becomes very long it is hard to understand.
 35  
  * Therefore long methods should usually be refactored into several
 36  
  * individual methods that focus on a specific task.
 37  
  * </p>
 38  
  *<p>
 39  
  * The default maximum method length is 150 lines. To change the maximum
 40  
  * number of lines, set property max.
 41  
  * </p>
 42  
  * <p>
 43  
  * An example of how to configure the check is:
 44  
  * </p>
 45  
  * <pre>
 46  
  * &lt;module name="MethodLength"/&gt;
 47  
  * </pre>
 48  
  * <p>
 49  
  * An example of how to configure the check so that it accepts methods with at
 50  
  * most 60 lines is:
 51  
  * </p>
 52  
  * <pre>
 53  
  * &lt;module name="MethodLength"&gt;
 54  
  *    &lt;property name="max" value="60"/&gt;
 55  
  * &lt;/module&gt;
 56  
  * </pre>
 57  
  * @author Lars K├╝hne
 58  
  */
 59  
 @StatelessCheck
 60  20
 public class MethodLengthCheck extends AbstractCheck {
 61  
 
 62  
     /**
 63  
      * A key is pointing to the warning message text in "messages.properties"
 64  
      * file.
 65  
      */
 66  
     public static final String MSG_KEY = "maxLen.method";
 67  
 
 68  
     /** Default maximum number of lines. */
 69  
     private static final int DEFAULT_MAX_LINES = 150;
 70  
 
 71  
     /** Whether to ignore empty lines and single line comments. */
 72  20
     private boolean countEmpty = true;
 73  
 
 74  
     /** The maximum number of lines. */
 75  20
     private int max = DEFAULT_MAX_LINES;
 76  
 
 77  
     @Override
 78  
     public int[] getDefaultTokens() {
 79  13
         return getAcceptableTokens();
 80  
     }
 81  
 
 82  
     @Override
 83  
     public int[] getAcceptableTokens() {
 84  24
         return new int[] {TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF};
 85  
     }
 86  
 
 87  
     @Override
 88  
     public int[] getRequiredTokens() {
 89  25
         return CommonUtils.EMPTY_INT_ARRAY;
 90  
     }
 91  
 
 92  
     @Override
 93  
     public void visitToken(DetailAST ast) {
 94  36
         final DetailAST openingBrace = ast.findFirstToken(TokenTypes.SLIST);
 95  36
         if (openingBrace != null) {
 96  32
             final DetailAST closingBrace =
 97  32
                 openingBrace.findFirstToken(TokenTypes.RCURLY);
 98  32
             final int length = getLengthOfBlock(openingBrace, closingBrace);
 99  32
             if (length > max) {
 100  4
                 log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY,
 101  2
                         length, max);
 102  
             }
 103  
         }
 104  36
     }
 105  
 
 106  
     /**
 107  
      * Returns length of code only without comments and blank lines.
 108  
      * @param openingBrace block opening brace
 109  
      * @param closingBrace block closing brace
 110  
      * @return number of lines with code for current block
 111  
      */
 112  
     private int getLengthOfBlock(DetailAST openingBrace, DetailAST closingBrace) {
 113  32
         int length = closingBrace.getLineNo() - openingBrace.getLineNo() + 1;
 114  
 
 115  32
         if (!countEmpty) {
 116  11
             final FileContents contents = getFileContents();
 117  11
             final int lastLine = closingBrace.getLineNo();
 118  
             // lastLine - 1 is actual last line index. Last line is line with curly brace,
 119  
             // which is always not empty. So, we make it lastLine - 2 to cover last line that
 120  
             // actually may be empty.
 121  111
             for (int i = openingBrace.getLineNo() - 1; i <= lastLine - 2; i++) {
 122  100
                 if (contents.lineIsBlank(i) || contents.lineIsComment(i)) {
 123  39
                     length--;
 124  
                 }
 125  
             }
 126  
         }
 127  32
         return length;
 128  
     }
 129  
 
 130  
     /**
 131  
      * Sets maximum length of a method.
 132  
      * @param length the maximum length of a method.
 133  
      */
 134  
     public void setMax(int length) {
 135  7
         max = length;
 136  7
     }
 137  
 
 138  
     /**
 139  
      * Sets countEmpty.
 140  
      * @param countEmpty whether to count empty and single line comments
 141  
      *     of the form //.
 142  
      */
 143  
     public void setCountEmpty(boolean countEmpty) {
 144  3
         this.countEmpty = countEmpty;
 145  3
     }
 146  
 }