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