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