001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2015 the original author or authors. 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//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.sizes; 021 022import org.apache.commons.lang3.ArrayUtils; 023 024import com.puppycrawl.tools.checkstyle.api.Check; 025import com.puppycrawl.tools.checkstyle.api.DetailAST; 026import com.puppycrawl.tools.checkstyle.api.FileContents; 027import com.puppycrawl.tools.checkstyle.api.TokenTypes; 028 029/** 030 * <p> 031 * Checks for long methods. 032 * </p> 033 * <p> 034 * Rationale: If a method becomes very long it is hard to understand. 035 * Therefore long methods should usually be refactored into several 036 * individual methods that focus on a specific task. 037 * </p> 038 *<p> 039 * The default maximum method length is 150 lines. To change the maximum 040 * number of lines, set property max. 041 * </p> 042 * <p> 043 * An example of how to configure the check is: 044 * </p> 045 * <pre> 046 * <module name="MethodLength"/> 047 * </pre> 048 * <p> 049 * An example of how to configure the check so that it accepts methods with at 050 * most 60 lines is: 051 * </p> 052 * <pre> 053 * <module name="MethodLength"> 054 * <property name="max" value="60"/> 055 * </module> 056 * </pre> 057 * @author Lars Kühne 058 */ 059public class MethodLengthCheck extends Check { 060 061 /** 062 * A key is pointing to the warning message text in "messages.properties" 063 * file. 064 */ 065 public static final String MSG_KEY = "maxLen.method"; 066 067 /** Default maximum number of lines. */ 068 private static final int DEFAULT_MAX_LINES = 150; 069 070 /** Whether to ignore empty lines and single line comments. */ 071 private boolean countEmpty = true; 072 073 /** The maximum number of lines. */ 074 private int max = DEFAULT_MAX_LINES; 075 076 @Override 077 public int[] getDefaultTokens() { 078 return getAcceptableTokens(); 079 } 080 081 @Override 082 public int[] getAcceptableTokens() { 083 return new int[] {TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF}; 084 } 085 086 @Override 087 public int[] getRequiredTokens() { 088 return ArrayUtils.EMPTY_INT_ARRAY; 089 } 090 091 @Override 092 public void visitToken(DetailAST ast) { 093 final DetailAST openingBrace = ast.findFirstToken(TokenTypes.SLIST); 094 if (openingBrace != null) { 095 final DetailAST closingBrace = 096 openingBrace.findFirstToken(TokenTypes.RCURLY); 097 final int length = getLengthOfBlock(openingBrace, closingBrace); 098 if (length > max) { 099 log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY, 100 length, max); 101 } 102 } 103 } 104 105 /** 106 * Returns length of code only without comments and blank lines. 107 * @param openingBrace block opening brace 108 * @param closingBrace block closing brace 109 * @return number of lines with code for current block 110 */ 111 private int getLengthOfBlock(DetailAST openingBrace, DetailAST closingBrace) { 112 int length = closingBrace.getLineNo() - openingBrace.getLineNo() + 1; 113 114 if (!countEmpty) { 115 final FileContents contents = getFileContents(); 116 final int lastLine = closingBrace.getLineNo(); 117 for (int i = openingBrace.getLineNo() - 1; i < lastLine; i++) { 118 if (contents.lineIsBlank(i) || contents.lineIsComment(i)) { 119 length--; 120 } 121 } 122 } 123 return length; 124 } 125 126 /** 127 * @param length the maximum length of a method. 128 */ 129 public void setMax(int length) { 130 max = length; 131 } 132 133 /** 134 * @param countEmpty whether to count empty and single line comments 135 * of the form //. 136 */ 137 public void setCountEmpty(boolean countEmpty) { 138 this.countEmpty = countEmpty; 139 } 140}