01: /**
02: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03: */package net.sourceforge.pmd.rules.design;
04:
05: import java.util.HashMap;
06: import java.util.List;
07: import java.util.Map;
08:
09: import net.sourceforge.pmd.AbstractRule;
10: import net.sourceforge.pmd.PropertyDescriptor;
11: import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
12: import net.sourceforge.pmd.ast.ASTCompilationUnit;
13: import net.sourceforge.pmd.ast.ASTFieldDeclaration;
14: import net.sourceforge.pmd.ast.SimpleNode;
15: import net.sourceforge.pmd.properties.IntegerProperty;
16: import net.sourceforge.pmd.util.NumericConstants;
17:
18: public class TooManyFields extends AbstractRule {
19:
20: private static final int DEFAULT_MAXFIELDS = 15;
21:
22: private Map<String, Integer> stats;
23: private Map<String, ASTClassOrInterfaceDeclaration> nodes;
24:
25: private static final PropertyDescriptor maxFieldsDescriptor = new IntegerProperty(
26: "maxfields", "Maximum allowable fields per class",
27: DEFAULT_MAXFIELDS, 1.0f);
28:
29: private static final Map<String, PropertyDescriptor> propertyDescriptorsByName = asFixedMap(maxFieldsDescriptor);
30:
31: public Object visit(ASTCompilationUnit node, Object data) {
32:
33: int maxFields = getIntProperty(maxFieldsDescriptor);
34:
35: stats = new HashMap<String, Integer>(5);
36: nodes = new HashMap<String, ASTClassOrInterfaceDeclaration>(5);
37:
38: List<ASTFieldDeclaration> l = node
39: .findChildrenOfType(ASTFieldDeclaration.class);
40:
41: for (ASTFieldDeclaration fd : l) {
42: if (fd.isFinal() && fd.isStatic()) {
43: continue;
44: }
45: ASTClassOrInterfaceDeclaration clazz = fd
46: .getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
47: if (clazz != null && !clazz.isInterface()) {
48: bumpCounterFor(clazz);
49: }
50: }
51: for (String k : stats.keySet()) {
52: int val = stats.get(k);
53: SimpleNode n = nodes.get(k);
54: if (val > maxFields) {
55: addViolation(data, n);
56: }
57: }
58: return data;
59: }
60:
61: private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
62: String key = clazz.getImage();
63: if (!stats.containsKey(key)) {
64: stats.put(key, NumericConstants.ZERO);
65: nodes.put(key, clazz);
66: }
67: Integer i = Integer.valueOf(stats.get(key) + 1);
68: stats.put(key, i);
69: }
70:
71: /**
72: * @return Map
73: */
74: protected Map<String, PropertyDescriptor> propertiesByName() {
75: return propertyDescriptorsByName;
76: }
77: }
|