1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2019 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.CommonUtil;
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 * <module name="MethodLength"/>
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 * <module name="MethodLength">
54 * <property name="max" value="60"/>
55 * </module>
56 * </pre>
57 */
58 @StatelessCheck
59 public class MethodLengthCheck extends AbstractCheck {
60
61 /**
62 * A key is pointing to the warning message text in "messages.properties"
63 * file.
64 */
65 public static final String MSG_KEY = "maxLen.method";
66
67 /** Default maximum number of lines. */
68 private static final int DEFAULT_MAX_LINES = 150;
69
70 /** Whether to ignore empty lines and single line comments. */
71 private boolean countEmpty = true;
72
73 /** The maximum number of lines. */
74 private int max = DEFAULT_MAX_LINES;
75
76 @Override
77 public int[] getDefaultTokens() {
78 return getAcceptableTokens();
79 }
80
81 @Override
82 public int[] getAcceptableTokens() {
83 return new int[] {TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF};
84 }
85
86 @Override
87 public int[] getRequiredTokens() {
88 return CommonUtil.EMPTY_INT_ARRAY;
89 }
90
91 @Override
92 public void visitToken(DetailAST ast) {
93 final DetailAST openingBrace = ast.findFirstToken(TokenTypes.SLIST);
94 if (openingBrace != null) {
95 final DetailAST closingBrace =
96 openingBrace.findFirstToken(TokenTypes.RCURLY);
97 final int length = getLengthOfBlock(openingBrace, closingBrace);
98 if (length > max) {
99 log(ast, MSG_KEY, 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 // lastLine - 1 is actual last line index. Last line is line with curly brace,
117 // which is always not empty. So, we make it lastLine - 2 to cover last line that
118 // actually may be empty.
119 for (int i = openingBrace.getLineNo() - 1; i <= lastLine - 2; i++) {
120 if (contents.lineIsBlank(i) || contents.lineIsComment(i)) {
121 length--;
122 }
123 }
124 }
125 return length;
126 }
127
128 /**
129 * Sets maximum length of a method.
130 * @param length the maximum length of a method.
131 */
132 public void setMax(int length) {
133 max = length;
134 }
135
136 /**
137 * Sets countEmpty.
138 * @param countEmpty whether to count empty and single line comments
139 * of the form //.
140 */
141 public void setCountEmpty(boolean countEmpty) {
142 this.countEmpty = countEmpty;
143 }
144
145 }