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