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