1 |
| |
2 |
| |
3 |
| |
4 |
| package net.sourceforge.pmd.dfa; |
5 |
| |
6 |
| import java.util.List; |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| public class Linker { |
13 |
| |
14 |
| private List braceStack; |
15 |
| private List continueBreakReturnStack; |
16 |
| |
17 |
40
| public Linker(List braceStack, List continueBreakReturnStack) {
|
18 |
40
| this.braceStack = braceStack;
|
19 |
40
| this.continueBreakReturnStack = continueBreakReturnStack;
|
20 |
| } |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
40
| public void computePaths() throws LinkerException, SequenceException {
|
26 |
| |
27 |
| |
28 |
40
| SequenceChecker sc = new SequenceChecker(braceStack);
|
29 |
40
| while (!sc.run()) {
|
30 |
58
| if (sc.getFirstIndex() < 0 || sc.getLastIndex() < 0) {
|
31 |
0
| throw new SequenceException("computePaths(): return index < 0");
|
32 |
| } |
33 |
| |
34 |
58
| StackObject firstStackObject = (StackObject) braceStack.get(sc.getFirstIndex());
|
35 |
| |
36 |
58
| switch (firstStackObject.getType()) {
|
37 |
24
| case NodeType.IF_EXPR:
|
38 |
24
| int x = sc.getLastIndex() - sc.getFirstIndex();
|
39 |
24
| if (x == 2) {
|
40 |
11
| this.computeIf(sc.getFirstIndex(), sc.getFirstIndex() + 1, sc.getLastIndex());
|
41 |
13
| } else if (x == 1) {
|
42 |
13
| this.computeIf(sc.getFirstIndex(), sc.getLastIndex());
|
43 |
| } else { |
44 |
0
| System.out.println("Error - computePaths 1");
|
45 |
| } |
46 |
24
| break;
|
47 |
| |
48 |
3
| case NodeType.WHILE_EXPR:
|
49 |
3
| this.computeWhile(sc.getFirstIndex(), sc.getLastIndex());
|
50 |
3
| break;
|
51 |
| |
52 |
3
| case NodeType.SWITCH_START:
|
53 |
3
| this.computeSwitch(sc.getFirstIndex(), sc.getLastIndex());
|
54 |
3
| break;
|
55 |
| |
56 |
20
| case NodeType.FOR_INIT:
|
57 |
5
| case NodeType.FOR_EXPR:
|
58 |
0
| case NodeType.FOR_UPDATE:
|
59 |
0
| case NodeType.FOR_BEFORE_FIRST_STATEMENT:
|
60 |
25
| this.computeFor(sc.getFirstIndex(), sc.getLastIndex());
|
61 |
25
| break;
|
62 |
| |
63 |
3
| case NodeType.DO_BEFORE_FIRST_STATEMENT:
|
64 |
3
| this.computeDo(sc.getFirstIndex(), sc.getLastIndex());
|
65 |
3
| break;
|
66 |
| |
67 |
0
| default:
|
68 |
| } |
69 |
| |
70 |
58
| for (int y = sc.getLastIndex(); y >= sc.getFirstIndex(); y--) {
|
71 |
197
| braceStack.remove(y);
|
72 |
| } |
73 |
| } |
74 |
| |
75 |
40
| while (!continueBreakReturnStack.isEmpty()) {
|
76 |
6
| StackObject stackObject = (StackObject) continueBreakReturnStack.get(0);
|
77 |
6
| IDataFlowNode node = stackObject.getDataFlowNode();
|
78 |
| |
79 |
6
| switch (stackObject.getType()) {
|
80 |
0
| case NodeType.RETURN_STATEMENT:
|
81 |
| |
82 |
0
| node.removePathToChild((IDataFlowNode) node.getChildren().get(0));
|
83 |
0
| IDataFlowNode lastNode = (IDataFlowNode) node.getFlow().get(node.getFlow().size() - 1);
|
84 |
0
| node.addPathToChild(lastNode);
|
85 |
0
| continueBreakReturnStack.remove(0);
|
86 |
0
| break;
|
87 |
5
| case NodeType.BREAK_STATEMENT:
|
88 |
| |
89 |
5
| List bList = node.getFlow();
|
90 |
8
| for (int i = bList.indexOf(node); i < bList.size(); i++) {
|
91 |
8
| IDataFlowNode n = (IDataFlowNode) bList.get(i);
|
92 |
8
| if (n.isType(NodeType.WHILE_LAST_STATEMENT) ||
|
93 |
| n.isType(NodeType.SWITCH_END) || |
94 |
| n.isType(NodeType.FOR_END) || |
95 |
| n.isType(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE) || |
96 |
| n.isType(NodeType.DO_EXPR)) { |
97 |
5
| node.removePathToChild((IDataFlowNode) node.getChildren().get(0));
|
98 |
5
| IDataFlowNode last = (IDataFlowNode) bList.get(i + 1);
|
99 |
5
| node.addPathToChild(last);
|
100 |
5
| continueBreakReturnStack.remove(0);
|
101 |
5
| break;
|
102 |
| } |
103 |
| } |
104 |
5
| break;
|
105 |
| |
106 |
1
| case NodeType.CONTINUE_STATEMENT:
|
107 |
| |
108 |
| |
109 |
| |
110 |
| |
111 |
| |
112 |
| |
113 |
| |
114 |
| |
115 |
| |
116 |
| |
117 |
| |
118 |
| |
119 |
| |
120 |
| |
121 |
| |
122 |
| |
123 |
| |
124 |
| |
125 |
| |
126 |
| |
127 |
| |
128 |
| |
129 |
| |
130 |
| |
131 |
| |
132 |
| |
133 |
| |
134 |
| |
135 |
| |
136 |
| |
137 |
| |
138 |
| |
139 |
| |
140 |
| |
141 |
| |
142 |
| |
143 |
| |
144 |
| |
145 |
| |
146 |
| |
147 |
| |
148 |
| |
149 |
| |
150 |
| |
151 |
| |
152 |
| |
153 |
| |
154 |
| |
155 |
| |
156 |
| |
157 |
| |
158 |
| |
159 |
| |
160 |
| |
161 |
| |
162 |
| |
163 |
| |
164 |
| |
165 |
| |
166 |
| |
167 |
| |
168 |
1
| continueBreakReturnStack.remove(0);
|
169 |
| } |
170 |
| } |
171 |
| } |
172 |
| |
173 |
3
| private void computeDo(int first, int last) {
|
174 |
3
| IDataFlowNode doSt = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
|
175 |
3
| IDataFlowNode doExpr = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
|
176 |
| |
177 |
3
| IDataFlowNode doFirst = (IDataFlowNode) doSt.getFlow().get(doSt.getIndex() + 1);
|
178 |
3
| if (doFirst.getIndex() != doExpr.getIndex()) {
|
179 |
3
| doExpr.addPathToChild(doFirst);
|
180 |
| } |
181 |
| } |
182 |
| |
183 |
25
| private void computeFor(int firstIndex, int lastIndex) {
|
184 |
25
| IDataFlowNode fExpr = null;
|
185 |
25
| IDataFlowNode fUpdate = null;
|
186 |
25
| IDataFlowNode fSt = null;
|
187 |
25
| IDataFlowNode fEnd = null;
|
188 |
25
| boolean isUpdate = false;
|
189 |
| |
190 |
25
| for (int i = firstIndex; i <= lastIndex; i++) {
|
191 |
115
| StackObject so = (StackObject) this.braceStack.get(i);
|
192 |
115
| IDataFlowNode node = so.getDataFlowNode();
|
193 |
| |
194 |
115
| if (so.getType() == NodeType.FOR_EXPR) {
|
195 |
25
| fExpr = node;
|
196 |
90
| } else if (so.getType() == NodeType.FOR_UPDATE) {
|
197 |
20
| fUpdate = node;
|
198 |
20
| isUpdate = true;
|
199 |
70
| } else if (so.getType() == NodeType.FOR_BEFORE_FIRST_STATEMENT) {
|
200 |
25
| fSt = node;
|
201 |
45
| } else if (so.getType() == NodeType.FOR_END) {
|
202 |
25
| fEnd = node;
|
203 |
| } |
204 |
| } |
205 |
25
| IDataFlowNode end = (IDataFlowNode) fEnd.getFlow().get(fEnd.getIndex() + 1);
|
206 |
| |
207 |
25
| IDataFlowNode firstSt = (IDataFlowNode) fSt.getChildren().get(0);
|
208 |
| |
209 |
25
| if (isUpdate) {
|
210 |
20
| if (fSt.getIndex() != fEnd.getIndex()) {
|
211 |
14
| end.reverseParentPathsTo(fUpdate);
|
212 |
14
| fExpr.removePathToChild(fUpdate);
|
213 |
14
| fUpdate.addPathToChild(fExpr);
|
214 |
14
| fUpdate.removePathToChild(firstSt);
|
215 |
14
| fExpr.addPathToChild(firstSt);
|
216 |
14
| fExpr.addPathToChild(end);
|
217 |
| } else { |
218 |
6
| fSt.removePathToChild(end);
|
219 |
6
| fExpr.removePathToChild(fUpdate);
|
220 |
6
| fUpdate.addPathToChild(fExpr);
|
221 |
6
| fExpr.addPathToChild(fUpdate);
|
222 |
6
| fExpr.addPathToChild(end);
|
223 |
| } |
224 |
| } else { |
225 |
5
| if (fSt.getIndex() != fEnd.getIndex()) {
|
226 |
1
| end.reverseParentPathsTo(fExpr);
|
227 |
1
| fExpr.addPathToChild(end);
|
228 |
| } |
229 |
| } |
230 |
| } |
231 |
| |
232 |
3
| private void computeSwitch(int firstIndex, int lastIndex) {
|
233 |
| |
234 |
3
| int diff = lastIndex - firstIndex;
|
235 |
3
| boolean defaultStatement = false;
|
236 |
| |
237 |
3
| IDataFlowNode sStart = ((StackObject) this.braceStack.get(firstIndex)).getDataFlowNode();
|
238 |
3
| IDataFlowNode sEnd = ((StackObject) this.braceStack.get(lastIndex)).getDataFlowNode();
|
239 |
3
| IDataFlowNode end = (IDataFlowNode) sEnd.getChildren().get(0);
|
240 |
| |
241 |
3
| for (int i = 0; i < diff - 2; i++) {
|
242 |
2
| StackObject so = (StackObject) this.braceStack.get(firstIndex + 2 + i);
|
243 |
2
| IDataFlowNode node = so.getDataFlowNode();
|
244 |
| |
245 |
2
| sStart.addPathToChild((IDataFlowNode) node.getChildren().get(0));
|
246 |
| |
247 |
2
| if (so.getType() == NodeType.SWITCH_LAST_DEFAULT_STATEMENT)
|
248 |
1
| defaultStatement = true;
|
249 |
| } |
250 |
| |
251 |
3
| if (!defaultStatement)
|
252 |
2
| sStart.addPathToChild(end);
|
253 |
| } |
254 |
| |
255 |
3
| private void computeWhile(int first, int last) {
|
256 |
3
| IDataFlowNode wStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
|
257 |
3
| IDataFlowNode wEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
|
258 |
| |
259 |
3
| IDataFlowNode end = (IDataFlowNode) wEnd.getFlow().get(wEnd.getIndex() + 1);
|
260 |
| |
261 |
3
| if (wStart.getIndex() != wEnd.getIndex()) {
|
262 |
2
| end.reverseParentPathsTo(wStart);
|
263 |
2
| wStart.addPathToChild(end);
|
264 |
| } |
265 |
| } |
266 |
| |
267 |
11
| private void computeIf(int first, int second, int last) {
|
268 |
11
| IDataFlowNode ifStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
|
269 |
11
| IDataFlowNode ifEnd = ((StackObject) this.braceStack.get(second)).getDataFlowNode();
|
270 |
11
| IDataFlowNode elseEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
|
271 |
| |
272 |
11
| IDataFlowNode elseStart = (IDataFlowNode) ifEnd.getFlow().get(ifEnd.getIndex() + 1);
|
273 |
11
| IDataFlowNode end = (IDataFlowNode) elseEnd.getFlow().get(elseEnd.getIndex() + 1);
|
274 |
| |
275 |
| |
276 |
11
| if (ifStart.getIndex() != ifEnd.getIndex() &&
|
277 |
| ifEnd.getIndex() != elseEnd.getIndex()) { |
278 |
11
| elseStart.reverseParentPathsTo(end);
|
279 |
11
| ifStart.addPathToChild(elseStart);
|
280 |
| } |
281 |
| |
282 |
0
| else if (ifStart.getIndex() == ifEnd.getIndex() &&
|
283 |
| ifEnd.getIndex() != elseEnd.getIndex()) { |
284 |
0
| ifStart.addPathToChild(end);
|
285 |
| } |
286 |
| |
287 |
0
| else if (ifEnd.getIndex() == elseEnd.getIndex() &&
|
288 |
| ifStart.getIndex() != ifEnd.getIndex()) { |
289 |
0
| ifStart.addPathToChild(end);
|
290 |
| } |
291 |
| } |
292 |
| |
293 |
13
| private void computeIf(int first, int last) {
|
294 |
13
| IDataFlowNode ifStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
|
295 |
13
| IDataFlowNode ifEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
|
296 |
| |
297 |
| |
298 |
13
| if (ifStart.getIndex() != ifEnd.getIndex()) {
|
299 |
12
| IDataFlowNode end = (IDataFlowNode) ifEnd.getFlow().get(ifEnd.getIndex() + 1);
|
300 |
12
| ifStart.addPathToChild(end);
|
301 |
| } |
302 |
| } |
303 |
| } |