1
2
3
4 package net.sourceforge.pmd.lang.java.dfa;
5
6 import java.util.logging.Level;
7 import java.util.logging.Logger;
8
9 import net.sourceforge.pmd.lang.DataFlowHandler;
10 import net.sourceforge.pmd.lang.ast.Node;
11 import net.sourceforge.pmd.lang.dfa.Linker;
12 import net.sourceforge.pmd.lang.dfa.LinkerException;
13 import net.sourceforge.pmd.lang.dfa.NodeType;
14 import net.sourceforge.pmd.lang.dfa.SequenceException;
15 import net.sourceforge.pmd.lang.dfa.Structure;
16 import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
17 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
18 import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement;
19 import net.sourceforge.pmd.lang.java.ast.ASTDoStatement;
20 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
21 import net.sourceforge.pmd.lang.java.ast.ASTForInit;
22 import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
23 import net.sourceforge.pmd.lang.java.ast.ASTForUpdate;
24 import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
25 import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement;
26 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
27 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
28 import net.sourceforge.pmd.lang.java.ast.ASTStatement;
29 import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
30 import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel;
31 import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement;
32 import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement;
33 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
34 import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
35 import net.sourceforge.pmd.lang.java.ast.JavaNode;
36 import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
37
38
39
40
41
42
43
44
45 public class StatementAndBraceFinder extends JavaParserVisitorAdapter {
46 private final static Logger LOGGER = Logger.getLogger(StatementAndBraceFinder.class.getName());
47
48 private final DataFlowHandler dataFlowHandler;
49 private Structure dataFlow;
50
51 public StatementAndBraceFinder(DataFlowHandler dataFlowHandler) {
52 this.dataFlowHandler = dataFlowHandler;
53 }
54
55 public void buildDataFlowFor(JavaNode node) {
56 if (!(node instanceof ASTMethodDeclaration) && !(node instanceof ASTConstructorDeclaration)) {
57 throw new RuntimeException("Can't build a data flow for anything other than a method or a constructor");
58 }
59
60 this.dataFlow = new Structure(dataFlowHandler);
61 this.dataFlow.createStartNode(node.getBeginLine());
62 this.dataFlow.createNewNode(node);
63
64 node.jjtAccept(this, dataFlow);
65
66 this.dataFlow.createEndNode(node.getEndLine());
67 if (LOGGER.isLoggable(Level.FINE))
68 {
69 LOGGER.fine("DataFlow is " + this.dataFlow.dump() );
70 }
71 Linker linker = new Linker(dataFlowHandler, dataFlow.getBraceStack(), dataFlow.getContinueBreakReturnStack());
72 try {
73 linker.computePaths();
74 } catch (LinkerException e) {
75 e.printStackTrace();
76 } catch (SequenceException e) {
77 e.printStackTrace();
78 }
79 }
80
81 public Object visit(ASTStatementExpression node, Object data) {
82 if (!(data instanceof Structure)) {
83 return data;
84 }
85 Structure dataFlow = (Structure) data;
86 LOGGER.finest("createNewNode ASTStatementExpression: line " + node.getBeginLine() +", column " + node.getBeginColumn());
87 dataFlow.createNewNode(node);
88 return super.visit(node, data);
89 }
90
91 public Object visit(ASTVariableDeclarator node, Object data) {
92 if (!(data instanceof Structure)) {
93 return data;
94 }
95 Structure dataFlow = (Structure) data;
96 LOGGER.finest("createNewNode ASTVariableDeclarator: line " + node.getBeginLine() +", column " + node.getBeginColumn());
97 dataFlow.createNewNode(node);
98 return super.visit(node, data);
99 }
100
101 public Object visit(ASTExpression node, Object data) {
102 if (!(data instanceof Structure)) {
103 return data;
104 }
105 Structure dataFlow = (Structure) data;
106
107
108 if (node.jjtGetParent() instanceof ASTIfStatement) {
109 dataFlow.createNewNode(node);
110 dataFlow.pushOnStack(NodeType.IF_EXPR, dataFlow.getLast());
111 LOGGER.finest("pushOnStack parent IF_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
112 } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
113 dataFlow.createNewNode(node);
114 dataFlow.pushOnStack(NodeType.WHILE_EXPR, dataFlow.getLast());
115 LOGGER.finest("pushOnStack parent WHILE_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
116 } else if (node.jjtGetParent() instanceof ASTSwitchStatement) {
117 dataFlow.createNewNode(node);
118 dataFlow.pushOnStack(NodeType.SWITCH_START, dataFlow.getLast());
119 LOGGER.finest("pushOnStack parent SWITCH_START: line " + node.getBeginLine() +", column " + node.getBeginColumn());
120 } else if (node.jjtGetParent() instanceof ASTForStatement) {
121 dataFlow.createNewNode(node);
122 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
123 LOGGER.finest("pushOnStack parent FOR_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
124 } else if (node.jjtGetParent() instanceof ASTDoStatement) {
125 dataFlow.createNewNode(node);
126 dataFlow.pushOnStack(NodeType.DO_EXPR, dataFlow.getLast());
127 LOGGER.finest("pushOnStack parent DO_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
128 }
129
130 return super.visit(node, data);
131 }
132
133 public Object visit(ASTForInit node, Object data) {
134 if (!(data instanceof Structure)) {
135 return data;
136 }
137 Structure dataFlow = (Structure) data;
138 super.visit(node, data);
139 dataFlow.pushOnStack(NodeType.FOR_INIT, dataFlow.getLast());
140 LOGGER.finest("pushOnStack FOR_INIT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
141 this.addForExpressionNode(node, dataFlow);
142 return data;
143 }
144
145 public Object visit(ASTLabeledStatement node, Object data) {
146 dataFlow.createNewNode(node);
147 dataFlow.pushOnStack(NodeType.LABEL_STATEMENT, dataFlow.getLast());
148 LOGGER.finest("pushOnStack LABEL_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
149 return super.visit(node, data);
150 }
151
152 public Object visit(ASTForUpdate node, Object data) {
153 if (!(data instanceof Structure)) {
154 return data;
155 }
156 Structure dataFlow = (Structure) data;
157 this.addForExpressionNode(node, dataFlow);
158 super.visit(node, data);
159 dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
160 LOGGER.finest("pushOnStack FOR_UPDATE: line " + node.getBeginLine() +", column " + node.getBeginColumn());
161 return data;
162 }
163
164
165
166
167 public Object visit(ASTStatement node, Object data) {
168 if (!(data instanceof Structure)) {
169 return data;
170 }
171 Structure dataFlow = (Structure) data;
172
173 if (node.jjtGetParent() instanceof ASTForStatement) {
174 this.addForExpressionNode(node, dataFlow);
175 dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
176 LOGGER.finest("pushOnStack FOR_BEFORE_FIRST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
177 } else if (node.jjtGetParent() instanceof ASTDoStatement) {
178 dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
179 dataFlow.createNewNode(node.jjtGetParent());
180 LOGGER.finest("pushOnStack DO_BEFORE_FIRST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
181 }
182
183 super.visit(node, data);
184
185 if (node.jjtGetParent() instanceof ASTIfStatement) {
186 ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
187 if (!st.hasElse()) {
188 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
189 LOGGER.finest("pushOnStack IF_LAST_STATEMENT_WITHOUT_ELSE: line " + node.getBeginLine() +", column " + node.getBeginColumn());
190 } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
191 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
192 LOGGER.finest("pushOnStack ELSE_LAST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
193 } else {
194 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
195 LOGGER.finest("pushOnStack IF_LAST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
196 }
197 } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
198 dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
199 LOGGER.finest("pushOnStack WHILE_LAST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
200 } else if (node.jjtGetParent() instanceof ASTForStatement) {
201 dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
202 LOGGER.finest("pushOnStack FOR_END: line " + node.getBeginLine() +", column " + node.getBeginColumn());
203 } else if (node.jjtGetParent() instanceof ASTLabeledStatement) {
204 dataFlow.pushOnStack(NodeType.LABEL_LAST_STATEMENT, dataFlow.getLast());
205 LOGGER.finest("pushOnStack LABEL_LAST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
206 }
207 return data;
208 }
209
210 public Object visit(ASTSwitchStatement node, Object data) {
211 if (!(data instanceof Structure)) {
212 return data;
213 }
214 Structure dataFlow = (Structure) data;
215 super.visit(node, data);
216 dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
217 LOGGER.finest("pushOnStack SWITCH_END: line " + node.getBeginLine() +", column " + node.getBeginColumn());
218 return data;
219 }
220
221 public Object visit(ASTSwitchLabel node, Object data) {
222 if (!(data instanceof Structure)) {
223 return data;
224 }
225 Structure dataFlow = (Structure) data;
226
227 if (node.jjtGetNumChildren() == 0) {
228 dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
229 LOGGER.finest("pushOnStack SWITCH_LAST_DEFAULT_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
230 } else {
231 dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
232 LOGGER.finest("pushOnStack CASE_LAST_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
233 }
234 return data;
235 }
236
237 public Object visit(ASTBreakStatement node, Object data) {
238 if (!(data instanceof Structure)) {
239 return data;
240 }
241 Structure dataFlow = (Structure) data;
242 dataFlow.createNewNode(node);
243 dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
244 LOGGER.finest("pushOnStack BREAK_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
245 return super.visit(node, data);
246 }
247
248
249 public Object visit(ASTContinueStatement node, Object data) {
250 if (!(data instanceof Structure)) {
251 return data;
252 }
253 Structure dataFlow = (Structure) data;
254 dataFlow.createNewNode(node);
255 dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
256 LOGGER.finest("pushOnStack CONTINUE_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
257 return super.visit(node, data);
258 }
259
260 public Object visit(ASTReturnStatement node, Object data) {
261 if (!(data instanceof Structure)) {
262 return data;
263 }
264 Structure dataFlow = (Structure) data;
265 dataFlow.createNewNode(node);
266 dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
267 LOGGER.finest("pushOnStack RETURN_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
268 return super.visit(node, data);
269 }
270
271 public Object visit(ASTThrowStatement node, Object data) {
272 if (!(data instanceof Structure)) {
273 return data;
274 }
275 Structure dataFlow = (Structure) data;
276 dataFlow.createNewNode(node);
277 dataFlow.pushOnStack(NodeType.THROW_STATEMENT, dataFlow.getLast());
278 LOGGER.finest("pushOnStack THROW_STATEMENT: line " + node.getBeginLine() +", column " + node.getBeginColumn());
279 return super.visit(node, data);
280 }
281
282
283
284
285
286 private void addForExpressionNode(Node node, Structure dataFlow) {
287 ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
288 boolean hasExpressionChild = false;
289 boolean hasForInitNode = false;
290 boolean hasForUpdateNode = false;
291
292 for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
293 if (parent.jjtGetChild(i) instanceof ASTExpression) {
294 hasExpressionChild = true;
295 } else if (parent.jjtGetChild(i) instanceof ASTForUpdate) {
296 hasForUpdateNode = true;
297 } else if (parent.jjtGetChild(i) instanceof ASTForInit) {
298 hasForInitNode = true;
299 }
300 }
301 if (!hasExpressionChild) {
302 if (node instanceof ASTForInit) {
303 dataFlow.createNewNode(node);
304 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
305 LOGGER.finest("pushOnStack FOR_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
306 } else if (node instanceof ASTForUpdate) {
307 if (!hasForInitNode) {
308 dataFlow.createNewNode(node);
309 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
310 LOGGER.finest("pushOnStack FOR_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
311 }
312 } else if (node instanceof ASTStatement) {
313 if (!hasForInitNode && !hasForUpdateNode) {
314 dataFlow.createNewNode(node);
315 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
316 LOGGER.finest("pushOnStack FOR_EXPR: line " + node.getBeginLine() +", column " + node.getBeginColumn());
317 }
318 }
319 }
320 }
321 }