View Javadoc

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   *
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   *
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      private class SwitchDensity {
25          private int labels = 0;
26          private int stmts = 0;
27  
28          public SwitchDensity() {
29          }
30  
31          public void addSwitchLabel() {
32              labels++;
33          }
34  
35          public void addStatement() {
36              stmts++;
37          }
38  
39          public void addStatements(int stmtCount) {
40              stmts += stmtCount;
41          }
42  
43          public int getStatementCount() {
44              return stmts;
45          }
46  
47          public double getDensity() {
48              if (labels == 0) {
49                  return 0;
50              }
51              return 1.0 * (stmts / labels);
52          }
53      }
54  
55      public SwitchDensityRule() {
56          super();
57      }
58  
59      public Object visit(ASTSwitchStatement node, Object data) {
60          SwitchDensity oldData = null;
61  
62          if (data instanceof SwitchDensity) {
63              oldData = (SwitchDensity) data;
64          }
65  
66          SwitchDensity density = new SwitchDensity();
67  
68          node.childrenAccept(this, density);
69  
70          DataPoint point = new DataPoint();
71          point.setLineNumber(node.getBeginLine());
72          point.setScore(density.getDensity());
73          point.setRule(this);
74          point.setMessage(getMessage());
75  
76          addDataPoint(point);
77  
78          if (data instanceof SwitchDensity) {
79              ((SwitchDensity) data).addStatements(density.getStatementCount());
80          }
81          return oldData;
82      }
83  
84      public Object visit(ASTStatement statement, Object data) {
85          if (data instanceof SwitchDensity) {
86              ((SwitchDensity) data).addStatement();
87          }
88  
89          statement.childrenAccept(this, data);
90  
91          return data;
92      }
93  
94      public Object visit(ASTSwitchLabel switchLabel, Object data) {
95          if (data instanceof SwitchDensity) {
96              ((SwitchDensity) data).addSwitchLabel();
97          }
98  
99          switchLabel.childrenAccept(this, data);
100         return data;
101     }
102 }