Source code: com/puppycrawl/tools/checkstyle/checks/metrics/AbstractComplexityCheck.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 Oliver Burn
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 package com.puppycrawl.tools.checkstyle.checks.metrics;
20
21 import com.puppycrawl.tools.checkstyle.api.Check;
22 import com.puppycrawl.tools.checkstyle.api.DetailAST;
23 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
24 import java.util.Stack;
25
26
27 /**
28 * Base class for checks the calculate complexity based around methods.
29 *
30 * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
31 * @author Oliver Burn
32 */
33 public abstract class AbstractComplexityCheck
34 extends Check
35 {
36 /** the initial current value */
37 private static final int INITIAL_VALUE = 1;
38
39 /** stack of values - all but the current value */
40 private final Stack mValueStack = new Stack();
41
42 /** the current value */
43 private int mCurrentValue;
44
45 /** threshold to report error for */
46 private int mMax;
47
48 /**
49 * Creates an instance.
50 * @param aMax the threshold of when to report an error
51 */
52 public AbstractComplexityCheck(int aMax)
53 {
54 mMax = aMax;
55 }
56
57 /**
58 * @return the message ID to log violations with
59 */
60 protected abstract String getMessageID();
61
62 /**
63 * Hook called when visiting a token. Will not be called the method
64 * definition tokens.
65 *
66 * @param aAST the token being visited
67 */
68 protected void visitTokenHook(DetailAST aAST)
69 {
70 }
71
72 /**
73 * Hook called when leaving a token. Will not be called the method
74 * definition tokens.
75 *
76 * @param aAST the token being left
77 */
78 protected void leaveTokenHook(DetailAST aAST)
79 {
80 }
81
82 /** {@inheritDoc} */
83 public final int[] getRequiredTokens()
84 {
85 return new int[] {
86 TokenTypes.CTOR_DEF,
87 TokenTypes.METHOD_DEF,
88 TokenTypes.INSTANCE_INIT,
89 TokenTypes.STATIC_INIT,
90 };
91 }
92
93 /** @return the maximum threshold allowed */
94 public final int getMax()
95 {
96 return mMax;
97 }
98
99 /**
100 * Set the maximum threshold allowed.
101 *
102 * @param aMax the maximum threshold
103 */
104 public final void setMax(int aMax)
105 {
106 mMax = aMax;
107 }
108
109 /** {@inheritDoc} */
110 public final void visitToken(DetailAST aAST)
111 {
112 switch (aAST.getType()) {
113 case TokenTypes.CTOR_DEF:
114 case TokenTypes.METHOD_DEF:
115 case TokenTypes.INSTANCE_INIT:
116 case TokenTypes.STATIC_INIT:
117 visitMethodDef();
118 break;
119 default:
120 visitTokenHook(aAST);
121 }
122 }
123
124 /** {@inheritDoc} */
125 public final void leaveToken(DetailAST aAST)
126 {
127 switch (aAST.getType()) {
128 case TokenTypes.CTOR_DEF:
129 case TokenTypes.METHOD_DEF:
130 case TokenTypes.INSTANCE_INIT:
131 case TokenTypes.STATIC_INIT:
132 leaveMethodDef(aAST);
133 break;
134 default:
135 leaveTokenHook(aAST);
136 }
137 }
138
139 /**
140 * @return the current value
141 */
142 protected final int getCurrentValue()
143 {
144 return mCurrentValue;
145 }
146
147 /**
148 * Set the current value
149 * @param aValue the new value
150 */
151 protected final void setCurrentValue(int aValue)
152 {
153 mCurrentValue = aValue;
154 }
155
156 /**
157 * Increments the current value by a specified amount.
158 *
159 * @param aBy the amount to increment by
160 */
161 protected final void incrementCurrentValue(int aBy)
162 {
163 setCurrentValue(getCurrentValue() + aBy);
164 }
165
166 /** Push the current value on the stack */
167 protected final void pushValue()
168 {
169 mValueStack.push(new Integer(mCurrentValue));
170 mCurrentValue = INITIAL_VALUE;
171 }
172
173 /**
174 * @return pop a value off the stack and make it the current value
175 */
176 protected final int popValue()
177 {
178 mCurrentValue = ((Integer) mValueStack.pop()).intValue();
179
180 return mCurrentValue;
181 }
182
183
184 /** Process the start of the method definition */
185 private void visitMethodDef()
186 {
187 pushValue();
188 }
189
190 /**
191 * Process the end of a method definition.
192 *
193 * @param aAST the token representing the method definition
194 */
195 private void leaveMethodDef(DetailAST aAST)
196 {
197 if (mCurrentValue > mMax) {
198 log(aAST.getLineNo(),
199 aAST.getColumnNo(),
200 getMessageID(),
201 new Integer(mCurrentValue),
202 new Integer(mMax));
203 }
204 popValue();
205 }
206 }