1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
package com.puppycrawl.tools.checkstyle.checks.sizes; |
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.Scope; |
25 | |
import com.puppycrawl.tools.checkstyle.api.ScopeUtils; |
26 | |
import com.puppycrawl.tools.checkstyle.api.TokenTypes; |
27 | |
import java.util.EnumMap; |
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | 3 | public final class MethodCountCheck extends Check |
36 | |
{ |
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
private static class MethodCounter |
43 | |
{ |
44 | |
|
45 | 9 | private final EnumMap<Scope, Integer> mCounts = |
46 | |
new EnumMap<Scope, Integer>(Scope.class); |
47 | |
|
48 | |
private final boolean mInInterface; |
49 | |
|
50 | |
private int mTotal; |
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
MethodCounter(boolean aInInterface) |
58 | 9 | { |
59 | 9 | mInInterface = aInInterface; |
60 | 9 | } |
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
void increment(Scope aScope) |
67 | |
{ |
68 | 66 | mTotal++; |
69 | 66 | if (mInInterface) { |
70 | 10 | mCounts.put(Scope.PUBLIC, 1 + value(Scope.PUBLIC)); |
71 | |
} |
72 | |
else { |
73 | 56 | mCounts.put(aScope, 1 + value(aScope)); |
74 | |
} |
75 | 66 | } |
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | |
int value(Scope aScope) |
82 | |
{ |
83 | 102 | final Integer value = mCounts.get(aScope); |
84 | 102 | return (null == value) ? 0 : value; |
85 | |
} |
86 | |
|
87 | |
|
88 | |
int getTotal() |
89 | |
{ |
90 | 9 | return mTotal; |
91 | |
} |
92 | |
}; |
93 | |
|
94 | |
|
95 | |
private static final int DEFAULT_MAX_METHODS = 100; |
96 | |
|
97 | 3 | private int mMaxPrivate = DEFAULT_MAX_METHODS; |
98 | |
|
99 | 3 | private int mMaxPackage = DEFAULT_MAX_METHODS; |
100 | |
|
101 | 3 | private int mMaxProtected = DEFAULT_MAX_METHODS; |
102 | |
|
103 | 3 | private int mMaxPublic = DEFAULT_MAX_METHODS; |
104 | |
|
105 | 3 | private int mMaxTotal = DEFAULT_MAX_METHODS; |
106 | |
|
107 | 3 | private final FastStack<MethodCounter> mCounters = |
108 | |
new FastStack<MethodCounter>(); |
109 | |
|
110 | |
@Override |
111 | |
public int[] getDefaultTokens() |
112 | |
{ |
113 | 3 | return new int[] { |
114 | |
TokenTypes.CLASS_DEF, |
115 | |
TokenTypes.ENUM_CONSTANT_DEF, |
116 | |
TokenTypes.ENUM_DEF, |
117 | |
TokenTypes.INTERFACE_DEF, |
118 | |
TokenTypes.METHOD_DEF, |
119 | |
}; |
120 | |
} |
121 | |
|
122 | |
@Override |
123 | |
public void visitToken(DetailAST aAST) |
124 | |
{ |
125 | 75 | if ((TokenTypes.CLASS_DEF == aAST.getType()) |
126 | |
|| (TokenTypes.INTERFACE_DEF == aAST.getType()) |
127 | |
|| (TokenTypes.ENUM_CONSTANT_DEF == aAST.getType()) |
128 | |
|| (TokenTypes.ENUM_DEF == aAST.getType())) |
129 | |
{ |
130 | 9 | mCounters.push(new MethodCounter( |
131 | |
TokenTypes.INTERFACE_DEF == aAST.getType())); |
132 | |
} |
133 | 66 | else if (TokenTypes.METHOD_DEF == aAST.getType()) { |
134 | 66 | raiseCounter(aAST); |
135 | |
} |
136 | 75 | } |
137 | |
|
138 | |
@Override |
139 | |
public void leaveToken(DetailAST aAST) |
140 | |
{ |
141 | 75 | if ((TokenTypes.CLASS_DEF == aAST.getType()) |
142 | |
|| (TokenTypes.INTERFACE_DEF == aAST.getType()) |
143 | |
|| (TokenTypes.ENUM_CONSTANT_DEF == aAST.getType()) |
144 | |
|| (TokenTypes.ENUM_DEF == aAST.getType())) |
145 | |
{ |
146 | 9 | final MethodCounter counter = mCounters.pop(); |
147 | 9 | checkCounters(counter, aAST); |
148 | |
} |
149 | 75 | } |
150 | |
|
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
private void raiseCounter(DetailAST aMethod) |
157 | |
{ |
158 | 66 | final MethodCounter actualCounter = mCounters.peek(); |
159 | 66 | final DetailAST temp = aMethod.findFirstToken(TokenTypes.MODIFIERS); |
160 | 66 | final Scope scope = ScopeUtils.getScopeFromMods(temp); |
161 | 66 | actualCounter.increment(scope); |
162 | 66 | } |
163 | |
|
164 | |
|
165 | |
|
166 | |
|
167 | |
|
168 | |
|
169 | |
private void checkCounters(MethodCounter aCounter, DetailAST aAst) |
170 | |
{ |
171 | 9 | checkMax(mMaxPrivate, aCounter.value(Scope.PRIVATE), |
172 | |
"too.many.privateMethods", aAst); |
173 | 9 | checkMax(mMaxPackage, aCounter.value(Scope.PACKAGE), |
174 | |
"too.many.packageMethods", aAst); |
175 | 9 | checkMax(mMaxProtected, aCounter.value(Scope.PROTECTED), |
176 | |
"too.many.protectedMethods", aAst); |
177 | 9 | checkMax(mMaxPublic, aCounter.value(Scope.PUBLIC), |
178 | |
"too.many.publicMethods", aAst); |
179 | 9 | checkMax(mMaxTotal, aCounter.getTotal(), "too.many.methods", aAst); |
180 | 9 | } |
181 | |
|
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
private void checkMax(int aMax, int aValue, String aMsg, DetailAST aAst) |
190 | |
{ |
191 | 45 | if (aMax < aValue) { |
192 | 11 | log(aAst.getLineNo(), aMsg, aValue, aMax); |
193 | |
} |
194 | 45 | } |
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
public void setMaxPrivate(int aValue) |
201 | |
{ |
202 | 2 | mMaxPrivate = aValue; |
203 | 2 | } |
204 | |
|
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
public void setMaxPackage(int aValue) |
210 | |
{ |
211 | 1 | mMaxPackage = aValue; |
212 | 1 | } |
213 | |
|
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
public void setMaxProtected(int aValue) |
219 | |
{ |
220 | 1 | mMaxProtected = aValue; |
221 | 1 | } |
222 | |
|
223 | |
|
224 | |
|
225 | |
|
226 | |
|
227 | |
public void setMaxPublic(int aValue) |
228 | |
{ |
229 | 1 | mMaxPublic = aValue; |
230 | 1 | } |
231 | |
|
232 | |
|
233 | |
|
234 | |
|
235 | |
|
236 | |
public void setMaxTotal(int aValue) |
237 | |
{ |
238 | 2 | mMaxTotal = aValue; |
239 | 2 | } |
240 | |
} |