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