Clover coverage report - PMD - 3.7 Coverage timestamp: Wed May 31 2006 09:25:59 EDT FRAMES NO FRAMES |
file stats: | LOC: | 303 |  | Methods: | 8
| NCLOC: | 186 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
Linker.java | 82% | 88.7% | 100% | 87.4% |

1 |  | /*
2 |  | * Created on 12.07.2004
3 |  | */
4 |  | package net.sourceforge.pmd.dfa;
5 |  |
6 |  | import java.util.List;
7 |  |
8 |  | /**
9 |  | * @author raik
10 |  | * Links data flow nodes to each other.
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 |  | * Creates all the links between the data flow nodes.
24 |  | */
25 | 40 | public void computePaths() throws LinkerException, SequenceException {
26 |  | // Returns true if there are more sequences, computes the first and
27 |  | // the last index of the sequence.
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 |  | // remove all children (should contain only one child)
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 |  | // What about breaks to labels above if statements?
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 |  | //List cList = node.getFlow();
108 |  | /* traverse up the tree and find the first loop start node
109 |  | */
110 |  | /*
111 |  | for(int i = cList.indexOf(node)-1;i>=0;i--) {
112 |  | IDataFlowNode n = (IDataFlowNode)cList.get(i);
113 |  |
114 |  | if(n.isType(NodeType.FOR_UPDATE) ||
115 |  | n.isType(NodeType.FOR_EXPR) ||
116 |  | n.isType(NodeType.WHILE_EXPR)) {
117 |  | */
118 |  | /*
119 |  | * while(..) {
120 |  | * while(...) {
121 |  | * ...
122 |  | * }
123 |  | * continue;
124 |  | * }
125 |  | *
126 |  | * Without this Expression he continues the second
127 |  | * WHILE loop. The continue statement and the while loop
128 |  | * have to be in different scopes.
129 |  | *
130 |  | * TODO An error occurs if "continue" is even nested in
131 |  | * scopes other than local loop scopes, like "if".
132 |  | * The result is, that the data flow isn't build right
133 |  | * and the pathfinder runs in invinity loop.
134 |  | * */
135 |  | /* if(n.getSimpleNode().getScope().equals(node.getSimpleNode().getScope())) {
136 |  | System.err.println("equals");
137 |  | continue;
138 |  | }
139 |  | else {
140 |  | System.err.println("don't equals");
141 |  | }
142 |  |
143 |  | //remove all children (should contain only one child)
144 |  | node.removePathToChild((IDataFlowNode)node.getChildren().get(0));
145 |  |
146 |  | node.addPathToChild(n);
147 |  | cbrStack.remove(0);
148 |  | break;
149 |  |
150 |  | }else if(n.isType(NodeType.DO_BEFOR_FIRST_STATEMENT)) {
151 |  |
152 |  | IDataFlowNode inode = (IDataFlowNode)n.getFlow().get(n.getIndex()1);
153 |  |
154 |  | for(int j=0;j<inode.getParents().size();j) {
155 |  | IDataFlowNode parent = (IDataFlowNode)inode.getParents().get(j);
156 |  |
157 |  | if(parent.isType(NodeType.DO_EXPR)) {
158 |  | node.removePathToChild((IDataFlowNode)node.getChildren().get(0));
159 |  | node.addPathToChild(parent);
160 |  |
161 |  | cbrStack.remove(0);
162 |  | break;
163 |  | }
164 |  | }
165 |  | break;
166 |  | }
167 |  | }
168 | 1 | */continueBreakReturnStack.remove(0); // delete this statement if you uncomment the stuff above
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 |  | //IDataFlowNode doFirst = (IDataFlowNode)doSt.getChildren().get(0);
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 |  | // if if-statement and else-statement contains statements or expressions
276 | 11 | if (ifStart.getIndex() != ifEnd.getIndex() &&
277 |  | ifEnd.getIndex() != elseEnd.getIndex()) {
278 | 11 | elseStart.reverseParentPathsTo(end);
279 | 11 | ifStart.addPathToChild(elseStart);
280 |  | }
281 |  | // if only if-statement contains no expressions
282 | 0 | else if (ifStart.getIndex() == ifEnd.getIndex() &&
283 |  | ifEnd.getIndex() != elseEnd.getIndex()) {
284 | 0 | ifStart.addPathToChild(end);
285 |  | }
286 |  | // if only else-statement contains no expressions
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 |  | // only if the if-statement contains another Statement or Expression
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 |  | }