1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.rules.design;
5
6 import net.sourceforge.pmd.ast.ASTStatement;
7 import net.sourceforge.pmd.ast.ASTSwitchLabel;
8 import net.sourceforge.pmd.ast.ASTSwitchStatement;
9 import net.sourceforge.pmd.stat.DataPoint;
10 import net.sourceforge.pmd.stat.StatisticalRule;
11
12 /***
13 * @author dpeugh
14 * <p/>
15 * Switch Density - This is the number of statements over the
16 * number of cases within a switch. The higher the value, the
17 * more work each case is doing.
18 * <p/>
19 * Its my theory, that when the Switch Density is high, you should
20 * start looking at Subclasses or State Pattern to alleviate the
21 * problem.
22 */
23 public class SwitchDensityRule extends StatisticalRule {
24
25 private static class SwitchDensity {
26 private int labels = 0;
27 private int stmts = 0;
28
29 public void addSwitchLabel() {
30 labels++;
31 }
32
33 public void addStatement() {
34 stmts++;
35 }
36
37 public void addStatements(int stmtCount) {
38 stmts += stmtCount;
39 }
40
41 public int getStatementCount() {
42 return stmts;
43 }
44
45 public double getDensity() {
46 if (labels == 0) {
47 return 0;
48 }
49 return (double) stmts / (double) labels;
50 }
51 }
52
53 public Object visit(ASTSwitchStatement node, Object data) {
54 SwitchDensity oldData = null;
55
56 if (data instanceof SwitchDensity) {
57 oldData = (SwitchDensity) data;
58 }
59
60 SwitchDensity density = new SwitchDensity();
61
62 node.childrenAccept(this, density);
63
64 DataPoint point = new DataPoint();
65 point.setNode(node);
66 point.setScore(density.getDensity());
67 point.setMessage(getMessage());
68
69 addDataPoint(point);
70
71 if (data instanceof SwitchDensity) {
72 ((SwitchDensity) data).addStatements(density.getStatementCount());
73 }
74 return oldData;
75 }
76
77 public Object visit(ASTStatement statement, Object data) {
78 if (data instanceof SwitchDensity) {
79 ((SwitchDensity) data).addStatement();
80 }
81
82 statement.childrenAccept(this, data);
83
84 return data;
85 }
86
87 public Object visit(ASTSwitchLabel switchLabel, Object data) {
88 if (data instanceof SwitchDensity) {
89 ((SwitchDensity) data).addSwitchLabel();
90 }
91
92 switchLabel.childrenAccept(this, data);
93 return data;
94 }
95 }