1
2
3
4 package net.sourceforge.pmd.lang.plsql.rule.codesize;
5
6 import java.util.logging.Level;
7 import java.util.logging.Logger;
8
9 import net.sourceforge.pmd.lang.ast.Node;
10 import net.sourceforge.pmd.lang.plsql.ast.ASTCaseStatement;
11 import net.sourceforge.pmd.lang.plsql.ast.ASTCaseWhenClause;
12 import net.sourceforge.pmd.lang.plsql.ast.ASTContinueStatement;
13 import net.sourceforge.pmd.lang.plsql.ast.ASTElseClause;
14 import net.sourceforge.pmd.lang.plsql.ast.ASTElsifClause;
15 import net.sourceforge.pmd.lang.plsql.ast.ASTExceptionHandler;
16 import net.sourceforge.pmd.lang.plsql.ast.ASTExitStatement;
17 import net.sourceforge.pmd.lang.plsql.ast.ASTExpression;
18 import net.sourceforge.pmd.lang.plsql.ast.ASTForStatement;
19 import net.sourceforge.pmd.lang.plsql.ast.ASTGotoStatement;
20 import net.sourceforge.pmd.lang.plsql.ast.ASTIfStatement;
21 import net.sourceforge.pmd.lang.plsql.ast.ASTLabelledStatement;
22 import net.sourceforge.pmd.lang.plsql.ast.ASTLoopStatement;
23 import net.sourceforge.pmd.lang.plsql.ast.ASTRaiseStatement;
24 import net.sourceforge.pmd.lang.plsql.ast.ASTReturnStatement;
25 import net.sourceforge.pmd.lang.plsql.ast.ASTStatement;
26 import net.sourceforge.pmd.lang.plsql.ast.ASTWhileStatement;
27 import net.sourceforge.pmd.lang.plsql.ast.PLSQLNode;
28 import net.sourceforge.pmd.lang.plsql.rule.AbstractStatisticalPLSQLRule;
29 import net.sourceforge.pmd.stat.DataPoint;
30 import net.sourceforge.pmd.util.NumericConstants;
31
32
33
34
35 public abstract class AbstractNcssCountRule extends AbstractStatisticalPLSQLRule {
36 private final static Logger LOGGER = Logger.getLogger(AbstractNcssCountRule.class.getName());
37
38 private Class<?> nodeClass;
39
40
41
42
43
44
45
46 protected AbstractNcssCountRule(Class<?> nodeClass) {
47 this.nodeClass = nodeClass;
48 if (LOGGER.isLoggable(Level.FINE)) {
49 LOGGER.fine("Counting for " + nodeClass.getCanonicalName());
50 }
51 }
52
53 @Override
54 public Object visit(PLSQLNode node, Object data) {
55 int numNodes = 0;
56
57 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
58 PLSQLNode n = (PLSQLNode) node.jjtGetChild(i);
59 Integer treeSize = (Integer) n.jjtAccept(this, data);
60 numNodes += treeSize.intValue();
61 }
62
63 if (LOGGER.isLoggable(Level.FINER)) {
64 LOGGER.finer("Checking candidate " + node.getClass().getCanonicalName()
65 + " against target class " + nodeClass.getCanonicalName()
66 + " with " + numNodes + " nodes"
67 );
68 }
69
70 if (this.nodeClass.isInstance(node)) {
71 if (LOGGER.isLoggable(Level.FINE)) {
72 LOGGER.fine("Matched candidate " + node.getClass().getCanonicalName()
73 + " against target class " + nodeClass.getCanonicalName()
74 );
75 }
76
77 numNodes++;
78 DataPoint point = new DataPoint();
79 point.setNode(node);
80 point.setScore(1.0 * numNodes);
81 point.setMessage(getMessage());
82 addDataPoint(point);
83 if (LOGGER.isLoggable(Level.FINE)) {
84 LOGGER.fine("Running score is " + point.getScore());
85 }
86 }
87
88 return Integer.valueOf(numNodes);
89 }
90
91
92
93
94
95
96
97
98
99
100
101 protected Integer countNodeChildren(Node node, Object data) {
102 Integer nodeCount = null;
103 int lineCount = 0;
104 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
105 nodeCount = (Integer) ((PLSQLNode) node.jjtGetChild(i)).jjtAccept(this, data);
106 lineCount += nodeCount.intValue();
107 }
108 return ++lineCount;
109 }
110
111 @Override
112 public Object visit(ASTForStatement node, Object data) {
113 return countNodeChildren(node, data);
114 }
115
116 @Override
117 public Object visit(ASTLoopStatement node, Object data) {
118 return countNodeChildren(node, data);
119 }
120
121 @Override
122 public Object visit(ASTIfStatement node, Object data) {
123
124 Integer lineCount = countNodeChildren(node, data);
125
126 return lineCount;
127 }
128
129 @Override
130 public Object visit(ASTElsifClause node, Object data) {
131
132 Integer lineCount = countNodeChildren(node, data);
133
134 return lineCount;
135 }
136
137 @Override
138 public Object visit(ASTElseClause node, Object data) {
139
140 Integer lineCount = countNodeChildren(node, data);
141
142 return lineCount;
143 }
144
145 @Override
146 public Object visit(ASTWhileStatement node, Object data) {
147 return countNodeChildren(node, data);
148 }
149
150 @Override
151 public Object visit(ASTExitStatement node, Object data) {
152 return NumericConstants.ONE;
153 }
154
155 @Override
156 public Object visit(ASTExceptionHandler node, Object data) {
157 return countNodeChildren(node, data);
158 }
159
160 @Override
161 public Object visit(ASTContinueStatement node, Object data) {
162 return NumericConstants.ONE;
163 }
164
165 @Override
166 public Object visit(ASTGotoStatement node, Object data) {
167 return NumericConstants.ONE;
168 }
169
170 @Override
171 public Object visit(ASTReturnStatement node, Object data) {
172 return countNodeChildren(node, data);
173 }
174
175 @Override
176 public Object visit(ASTCaseStatement node, Object data) {
177 return countNodeChildren(node, data);
178 }
179
180 @Override
181 public Object visit(ASTRaiseStatement node, Object data) {
182 return NumericConstants.ONE;
183 }
184
185 @Override
186 public Object visit(ASTExpression node, Object data) {
187
188
189 if (node.jjtGetParent() instanceof ASTStatement) {
190 return NumericConstants.ZERO;
191 }
192
193 return NumericConstants.ONE;
194 }
195
196 @Override
197 public Object visit(ASTLabelledStatement node, Object data) {
198 return countNodeChildren(node, data);
199 }
200
201
202
203 @Override
204 public Object visit(ASTCaseWhenClause node, Object data) {
205 return countNodeChildren(node, data);
206 }
207
208 @Override
209 public Object[] getViolationParameters(DataPoint point) {
210 if (LOGGER.isLoggable(Level.FINE)) {
211 LOGGER.fine("Point score is " + point.getScore());
212 }
213 return new String[] { String.valueOf((int) point.getScore()) };
214 }
215 }