001 /**
002 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003 */
004 package net.sourceforge.pmd.lang.java.rule.design;
005
006 import net.sourceforge.pmd.lang.java.ast.ASTStatement;
007 import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
008 import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
009 import net.sourceforge.pmd.lang.java.rule.AbstractStatisticalJavaRule;
010 import net.sourceforge.pmd.stat.DataPoint;
011
012 /**
013 * @author David Dixon-Peugh
014 *
015 * <p/>
016 * Switch Density - This is the number of statements over the
017 * number of cases within a switch. The higher the value, the
018 * more work each case is doing.
019 * <p/>
020 * Its my theory, that when the Switch Density is high, you should
021 * start looking at Subclasses or State Pattern to alleviate the
022 * problem.
023 */
024 public class SwitchDensityRule extends AbstractStatisticalJavaRule {
025
026 private static class SwitchDensity {
027 private int labels = 0;
028 private int stmts = 0;
029
030 public void addSwitchLabel() {
031 labels++;
032 }
033
034 public void addStatement() {
035 stmts++;
036 }
037
038 public void addStatements(int stmtCount) {
039 stmts += stmtCount;
040 }
041
042 public int getStatementCount() {
043 return stmts;
044 }
045
046 public double getDensity() {
047 if (labels == 0) {
048 return 0;
049 }
050 return (double) stmts / (double) labels;
051 }
052 }
053
054 public SwitchDensityRule() {
055 super();
056 setProperty(MINIMUM_DESCRIPTOR, 10d);
057 }
058
059 public Object visit(ASTSwitchStatement node, Object data) {
060 SwitchDensity oldData = null;
061
062 if (data instanceof SwitchDensity) {
063 oldData = (SwitchDensity) data;
064 }
065
066 SwitchDensity density = new SwitchDensity();
067
068 node.childrenAccept(this, density);
069
070 DataPoint point = new DataPoint();
071 point.setNode(node);
072 point.setScore(density.getDensity());
073 point.setMessage(getMessage());
074
075 addDataPoint(point);
076
077 if (data instanceof SwitchDensity) {
078 ((SwitchDensity) data).addStatements(density.getStatementCount());
079 }
080 return oldData;
081 }
082
083 public Object visit(ASTStatement statement, Object data) {
084 if (data instanceof SwitchDensity) {
085 ((SwitchDensity) data).addStatement();
086 }
087
088 statement.childrenAccept(this, data);
089
090 return data;
091 }
092
093 public Object visit(ASTSwitchLabel switchLabel, Object data) {
094 if (data instanceof SwitchDensity) {
095 ((SwitchDensity) data).addSwitchLabel();
096 }
097
098 switchLabel.childrenAccept(this, data);
099 return data;
100 }
101 }
|