1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2018 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 * <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 * @author Lars Kühne
58 */
59 @StatelessCheck
60 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 private boolean countEmpty = true;
73
74 /** The maximum number of lines. */
75 private int max = DEFAULT_MAX_LINES;
76
77 @Override
78 public int[] getDefaultTokens() {
79 return getAcceptableTokens();
80 }
81
82 @Override
83 public int[] getAcceptableTokens() {
84 return new int[] {TokenTypes.METHOD_DEF, TokenTypes.CTOR_DEF};
85 }
86
87 @Override
88 public int[] getRequiredTokens() {
89 return CommonUtils.EMPTY_INT_ARRAY;
90 }
91
92 @Override
93 public void visitToken(DetailAST ast) {
94 final DetailAST openingBrace = ast.findFirstToken(TokenTypes.SLIST);
95 if (openingBrace != null) {
96 final DetailAST closingBrace =
97 openingBrace.findFirstToken(TokenTypes.RCURLY);
98 final int length = getLengthOfBlock(openingBrace, closingBrace);
99 if (length > max) {
100 log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY,
101 length, max);
102 }
103 }
104 }
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 int length = closingBrace.getLineNo() - openingBrace.getLineNo() + 1;
114
115 if (!countEmpty) {
116 final FileContents contents = getFileContents();
117 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 for (int i = openingBrace.getLineNo() - 1; i <= lastLine - 2; i++) {
122 if (contents.lineIsBlank(i) || contents.lineIsComment(i)) {
123 length--;
124 }
125 }
126 }
127 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 max = length;
136 }
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 this.countEmpty = countEmpty;
145 }
146
147 }