View Javadoc

1   package net.sourceforge.pmd.lang.java.rule.codesize;
2   
3   import net.sourceforge.pmd.lang.ast.Node;
4   import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
5   import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement;
6   import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement;
7   import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
8   import net.sourceforge.pmd.lang.java.ast.ASTFinallyStatement;
9   import net.sourceforge.pmd.lang.java.ast.ASTForInit;
10  import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
11  import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
12  import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement;
13  import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
14  import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
15  import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
16  import net.sourceforge.pmd.lang.java.ast.ASTStatementExpressionList;
17  import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
18  import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
19  import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement;
20  import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement;
21  import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
22  import net.sourceforge.pmd.lang.java.ast.JavaNode;
23  import net.sourceforge.pmd.lang.java.rule.AbstractStatisticalJavaRule;
24  import net.sourceforge.pmd.stat.DataPoint;
25  import net.sourceforge.pmd.util.NumericConstants;
26  
27  /**
28   * Abstract superclass for NCSS counting methods. Counts tokens according to <a
29   * href="http://www.kclee.de/clemens/java/javancss/">JavaNCSS rules</a>.
30   * 
31   * @author Jason Bennett
32   */
33  public abstract class AbstractNcssCountRule extends AbstractStatisticalJavaRule {
34  
35      private Class<?> nodeClass;
36  
37      /**
38       * Count the nodes of the given type using NCSS rules.
39       * 
40       * @param nodeClass
41       *          class of node to count
42       */
43      protected AbstractNcssCountRule(Class<?> nodeClass) {
44  	this.nodeClass = nodeClass;
45      }
46  
47      @Override
48      public Object visit(JavaNode node, Object data) {
49  	int numNodes = 0;
50  
51  	for (int i = 0; i < node.jjtGetNumChildren(); i++) {
52  	    JavaNode n = (JavaNode) node.jjtGetChild(i);
53  	    Integer treeSize = (Integer) n.jjtAccept(this, data);
54  	    numNodes += treeSize.intValue();
55  	}
56  
57  	if (this.nodeClass.isInstance(node)) {
58  	    // Add 1 to account for base node
59  	    numNodes++;
60  	    DataPoint point = new DataPoint();
61  	    point.setNode(node);
62  	    point.setScore(1.0 * numNodes);
63  	    point.setMessage(getMessage());
64  	    addDataPoint(point);
65  	}
66  
67  	return Integer.valueOf(numNodes);
68      }
69  
70      /**
71       * Count the number of children of the given Java node. Adds one to count the
72       * node itself.
73       * 
74       * @param node
75       *          java node having children counted
76       * @param data
77       *          node data
78       * @return count of the number of children of the node, plus one
79       */
80      protected Integer countNodeChildren(Node node, Object data) {
81  	Integer nodeCount = null;
82  	int lineCount = 0;
83  	for (int i = 0; i < node.jjtGetNumChildren(); i++) {
84  	    nodeCount = (Integer) ((JavaNode) node.jjtGetChild(i)).jjtAccept(this, data);
85  	    lineCount += nodeCount.intValue();
86  	}
87  	return ++lineCount;
88      }
89  
90      @Override
91      public Object visit(ASTForStatement node, Object data) {
92  	return countNodeChildren(node, data);
93      }
94  
95      @Override
96      public Object visit(ASTDoStatement node, Object data) {
97  	return countNodeChildren(node, data);
98      }
99  
100     @Override
101     public Object visit(ASTIfStatement node, Object data) {
102 
103 	Integer lineCount = countNodeChildren(node, data);
104 
105 	if (node.hasElse()) {
106 	    lineCount++;
107 	}
108 
109 	return lineCount;
110     }
111 
112     @Override
113     public Object visit(ASTWhileStatement node, Object data) {
114 	return countNodeChildren(node, data);
115     }
116 
117     @Override
118     public Object visit(ASTBreakStatement node, Object data) {
119 	return NumericConstants.ONE;
120     }
121 
122     @Override
123     public Object visit(ASTCatchStatement node, Object data) {
124 	return countNodeChildren(node, data);
125     }
126 
127     @Override
128     public Object visit(ASTContinueStatement node, Object data) {
129 	return NumericConstants.ONE;
130     }
131 
132     @Override
133     public Object visit(ASTFinallyStatement node, Object data) {
134 	return countNodeChildren(node, data);
135     }
136 
137     @Override
138     public Object visit(ASTReturnStatement node, Object data) {
139 	return countNodeChildren(node, data);
140     }
141 
142     @Override
143     public Object visit(ASTSwitchStatement node, Object data) {
144 	return countNodeChildren(node, data);
145     }
146 
147     @Override
148     public Object visit(ASTSynchronizedStatement node, Object data) {
149 	return countNodeChildren(node, data);
150     }
151 
152     @Override
153     public Object visit(ASTThrowStatement node, Object data) {
154 	return NumericConstants.ONE;
155     }
156 
157     @Override
158     public Object visit(ASTStatementExpression node, Object data) {
159 
160 	// "For" update expressions do not count as separate lines of code
161 	if (node.jjtGetParent() instanceof ASTStatementExpressionList) {
162 	    return NumericConstants.ZERO;
163 	}
164 
165 	return NumericConstants.ONE;
166     }
167 
168     @Override
169     public Object visit(ASTLabeledStatement node, Object data) {
170 	return countNodeChildren(node, data);
171     }
172 
173     @Override
174     public Object visit(ASTLocalVariableDeclaration node, Object data) {
175 
176 	// "For" init declarations do not count as separate lines of code
177 	if (node.jjtGetParent() instanceof ASTForInit) {
178 	    return NumericConstants.ZERO;
179 	}
180 
181 	/*
182 	 * This will count variables declared on the same line as separate NCSS
183 	 * counts. This violates JavaNCSS standards, but I'm not convinced that's a
184 	 * bad thing here.
185 	 */
186 
187 	return countNodeChildren(node, data);
188     }
189 
190     @Override
191     public Object visit(ASTSwitchLabel node, Object data) {
192 	return countNodeChildren(node, data);
193     }
194 
195 }