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