Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AbstractComplexityCheck |
|
| 1.5625;1.562 |
1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2014 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.FastStack; | |
24 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
25 | import java.math.BigInteger; | |
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 | 1 | private static final BigInteger INITIAL_VALUE = BigInteger.ONE; |
38 | ||
39 | /** stack of values - all but the current value */ | |
40 | 3 | private final FastStack<BigInteger> mValueStack = FastStack.newInstance(); |
41 | ||
42 | /** the current value */ | |
43 | 3 | private BigInteger mCurrentValue = BigInteger.ZERO; |
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 | 3 | { |
54 | 3 | mMax = aMax; |
55 | 3 | } |
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 | 0 | } |
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 | 20 | } |
81 | ||
82 | @Override | |
83 | public final int[] getRequiredTokens() | |
84 | { | |
85 | 0 | 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 | 0 | 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 | 3 | mMax = aMax; |
107 | 3 | } |
108 | ||
109 | @Override | |
110 | public void visitToken(DetailAST aAST) | |
111 | { | |
112 | 41 | switch (aAST.getType()) { |
113 | case TokenTypes.CTOR_DEF: | |
114 | case TokenTypes.METHOD_DEF: | |
115 | case TokenTypes.INSTANCE_INIT: | |
116 | case TokenTypes.STATIC_INIT: | |
117 | 21 | visitMethodDef(); |
118 | 21 | break; |
119 | default: | |
120 | 20 | visitTokenHook(aAST); |
121 | } | |
122 | 41 | } |
123 | ||
124 | @Override | |
125 | public void leaveToken(DetailAST aAST) | |
126 | { | |
127 | 41 | switch (aAST.getType()) { |
128 | case TokenTypes.CTOR_DEF: | |
129 | case TokenTypes.METHOD_DEF: | |
130 | case TokenTypes.INSTANCE_INIT: | |
131 | case TokenTypes.STATIC_INIT: | |
132 | 21 | leaveMethodDef(aAST); |
133 | 21 | break; |
134 | default: | |
135 | 20 | leaveTokenHook(aAST); |
136 | } | |
137 | 41 | } |
138 | ||
139 | /** | |
140 | * @return the current value | |
141 | */ | |
142 | protected final BigInteger getCurrentValue() | |
143 | { | |
144 | 128 | return mCurrentValue; |
145 | } | |
146 | ||
147 | /** | |
148 | * Set the current value | |
149 | * @param aValue the new value | |
150 | */ | |
151 | protected final void setCurrentValue(BigInteger aValue) | |
152 | { | |
153 | 128 | mCurrentValue = aValue; |
154 | 128 | } |
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(BigInteger aBy) | |
162 | { | |
163 | 20 | setCurrentValue(getCurrentValue().add(aBy)); |
164 | 20 | } |
165 | ||
166 | /** Push the current value on the stack */ | |
167 | protected final void pushValue() | |
168 | { | |
169 | 129 | mValueStack.push(mCurrentValue); |
170 | 129 | mCurrentValue = INITIAL_VALUE; |
171 | 129 | } |
172 | ||
173 | /** | |
174 | * @return pop a value off the stack and make it the current value | |
175 | */ | |
176 | protected final BigInteger popValue() | |
177 | { | |
178 | 129 | mCurrentValue = mValueStack.pop(); |
179 | 129 | return mCurrentValue; |
180 | } | |
181 | ||
182 | /** Process the start of the method definition */ | |
183 | private void visitMethodDef() | |
184 | { | |
185 | 21 | pushValue(); |
186 | 21 | } |
187 | ||
188 | /** | |
189 | * Process the end of a method definition. | |
190 | * | |
191 | * @param aAST the token representing the method definition | |
192 | */ | |
193 | private void leaveMethodDef(DetailAST aAST) | |
194 | { | |
195 | 21 | final BigInteger max = BigInteger.valueOf(mMax); |
196 | 21 | if (mCurrentValue.compareTo(max) > 0) { |
197 | 21 | log(aAST, getMessageID(), mCurrentValue, max); |
198 | } | |
199 | 21 | popValue(); |
200 | 21 | } |
201 | } |