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(ASTForUpdate node, Object data) {
99 if (!(data instanceof Structure)) {
100 return data;
101 }
102 Structure dataFlow = (Structure) data;
103 this.addForExpressionNode(node, dataFlow);
104 super.visit(node, data);
105 dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
106 return data;
107 }
108
109
110
111
112 public Object visit(ASTStatement node, Object data) {
113 if (!(data instanceof Structure)) {
114 return data;
115 }
116 Structure dataFlow = (Structure) data;
117
118 if (node.jjtGetParent() instanceof ASTForStatement) {
119 this.addForExpressionNode(node, dataFlow);
120 dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
121 } else if (node.jjtGetParent() instanceof ASTDoStatement) {
122 dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
123 dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
124 }
125
126 super.visit(node, data);
127
128 if (node.jjtGetParent() instanceof ASTIfStatement) {
129 ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
130 if (!st.hasElse()) {
131 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
132 } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
133 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
134 } else {
135 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
136 }
137 } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
138 dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
139 } else if (node.jjtGetParent() instanceof ASTForStatement) {
140 dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
141 }
142 return data;
143 }
144
145 public Object visit(ASTSwitchStatement node, Object data) {
146 if (!(data instanceof Structure)) {
147 return data;
148 }
149 Structure dataFlow = (Structure) data;
150 super.visit(node, data);
151 dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
152 return data;
153 }
154
155 public Object visit(ASTSwitchLabel node, Object data) {
156 if (!(data instanceof Structure)) {
157 return data;
158 }
159 Structure dataFlow = (Structure) data;
160
161 if (node.jjtGetNumChildren() == 0) {
162 dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
163 } else {
164 dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
165 }
166 return data;
167 }
168
169 public Object visit(ASTBreakStatement node, Object data) {
170 if (!(data instanceof Structure)) {
171 return data;
172 }
173 Structure dataFlow = (Structure) data;
174 dataFlow.createNewNode(node);
175 dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
176 return super.visit(node, data);
177 }
178
179
180 public Object visit(ASTContinueStatement node, Object data) {
181 if (!(data instanceof Structure)) {
182 return data;
183 }
184 Structure dataFlow = (Structure) data;
185 dataFlow.createNewNode(node);
186 dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
187 return super.visit(node, data);
188 }
189
190 public Object visit(ASTReturnStatement node, Object data) {
191 if (!(data instanceof Structure)) {
192 return data;
193 }
194 Structure dataFlow = (Structure) data;
195 dataFlow.createNewNode(node);
196 dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
197 return super.visit(node, data);
198 }
199
200
201
202
203
204 private void addForExpressionNode(SimpleNode node, Structure dataFlow) {
205 ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
206 boolean hasExpressionChild = false;
207 boolean hasForInitNode = false;
208 boolean hasForUpdateNode = false;
209
210 for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
211 if (parent.jjtGetChild(i) instanceof ASTExpression)
212 hasExpressionChild = true;
213 else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
214 hasForUpdateNode = true;
215 else if (parent.jjtGetChild(i) instanceof ASTForInit)
216 hasForInitNode = true;
217 }
218 if (!hasExpressionChild) {
219 if (node instanceof ASTForInit) {
220 dataFlow.createNewNode(node);
221 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
222 } else if (node instanceof ASTForUpdate) {
223 if (!hasForInitNode) {
224 dataFlow.createNewNode(node);
225 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
226 }
227 } else if (node instanceof ASTStatement) {
228 if (!hasForInitNode && !hasForUpdateNode) {
229 dataFlow.createNewNode(node);
230 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
231 }
232 }
233 }
234 }
235 }