Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 339   Methods: 9
NCLOC: 216   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Linker.java 75% 83.3% 100% 81.7%
coverage coverage
 1    /*
 2    * Created on 12.07.2004
 3    */
 4    package net.sourceforge.pmd.dfa;
 5   
 6    import java.util.List;
 7   
 8    import net.sourceforge.pmd.ast.ASTLabeledStatement;
 9    import net.sourceforge.pmd.ast.SimpleNode;
 10   
 11    /**
 12    * @author raik
 13    * Links data flow nodes to each other.
 14    */
 15    public class Linker {
 16   
 17    private List braceStack;
 18    private List continueBreakReturnStack;
 19   
 20  45 public Linker(List braceStack, List continueBreakReturnStack) {
 21  45 this.braceStack = braceStack;
 22  45 this.continueBreakReturnStack = continueBreakReturnStack;
 23    }
 24   
 25    /**
 26    * Creates all the links between the data flow nodes.
 27    */
 28  45 public void computePaths() throws LinkerException, SequenceException {
 29    // Returns true if there are more sequences, computes the first and
 30    // the last index of the sequence.
 31  45 SequenceChecker sc = new SequenceChecker(braceStack);
 32  45 while (!sc.run()) {
 33  63 if (sc.getFirstIndex() < 0 || sc.getLastIndex() < 0) {
 34  0 throw new SequenceException("computePaths(): return index < 0");
 35    }
 36   
 37  63 StackObject firstStackObject = (StackObject) braceStack.get(sc.getFirstIndex());
 38   
 39  63 switch (firstStackObject.getType()) {
 40  27 case NodeType.IF_EXPR:
 41  27 int x = sc.getLastIndex() - sc.getFirstIndex();
 42  27 if (x == 2) {
 43  11 this.computeIf(sc.getFirstIndex(), sc.getFirstIndex() + 1, sc.getLastIndex());
 44  16 } else if (x == 1) {
 45  16 this.computeIf(sc.getFirstIndex(), sc.getLastIndex());
 46    } else {
 47  0 System.out.println("Error - computePaths 1");
 48    }
 49  27 break;
 50   
 51  3 case NodeType.WHILE_EXPR:
 52  3 this.computeWhile(sc.getFirstIndex(), sc.getLastIndex());
 53  3 break;
 54   
 55  3 case NodeType.SWITCH_START:
 56  3 this.computeSwitch(sc.getFirstIndex(), sc.getLastIndex());
 57  3 break;
 58   
 59  21 case NodeType.FOR_INIT:
 60  5 case NodeType.FOR_EXPR:
 61  0 case NodeType.FOR_UPDATE:
 62  0 case NodeType.FOR_BEFORE_FIRST_STATEMENT:
 63  26 this.computeFor(sc.getFirstIndex(), sc.getLastIndex());
 64  26 break;
 65   
 66  3 case NodeType.DO_BEFORE_FIRST_STATEMENT:
 67  3 this.computeDo(sc.getFirstIndex(), sc.getLastIndex());
 68  3 break;
 69   
 70  1 default:
 71    }
 72   
 73  63 for (int y = sc.getLastIndex(); y >= sc.getFirstIndex(); y--) {
 74  210 braceStack.remove(y);
 75    }
 76    }
 77   
 78  45 while (!continueBreakReturnStack.isEmpty()) {
 79  6 StackObject stackObject = (StackObject) continueBreakReturnStack.get(0);
 80  6 IDataFlowNode node = stackObject.getDataFlowNode();
 81   
 82  6 switch (stackObject.getType()) {
 83  0 case NodeType.RETURN_STATEMENT:
 84    // remove all children (should contain only one child)
 85  0 node.removePathToChild((IDataFlowNode) node.getChildren().get(0));
 86  0 IDataFlowNode lastNode = (IDataFlowNode) node.getFlow().get(node.getFlow().size() - 1);
 87  0 node.addPathToChild(lastNode);
 88  0 continueBreakReturnStack.remove(0);
 89  0 break;
 90  5 case NodeType.BREAK_STATEMENT:
 91  5 IDataFlowNode last = getNodeToBreakStatement(node);
 92  5 node.removePathToChild((IDataFlowNode) node.getChildren().get(0));
 93  5 node.addPathToChild(last);
 94  5 continueBreakReturnStack.remove(0);
 95  5 break;
 96   
 97  1 case NodeType.CONTINUE_STATEMENT:
 98    //List cList = node.getFlow();
 99    /* traverse up the tree and find the first loop start node
 100    */
 101    /*
 102    for(int i = cList.indexOf(node)-1;i>=0;i--) {
 103    IDataFlowNode n = (IDataFlowNode)cList.get(i);
 104   
 105    if(n.isType(NodeType.FOR_UPDATE) ||
 106    n.isType(NodeType.FOR_EXPR) ||
 107    n.isType(NodeType.WHILE_EXPR)) {
 108    */
 109    /*
 110    * while(..) {
 111    * while(...) {
 112    * ...
 113    * }
 114    * continue;
 115    * }
 116    *
 117    * Without this Expression he continues the second
 118    * WHILE loop. The continue statement and the while loop
 119    * have to be in different scopes.
 120    *
 121    * TODO An error occurs if "continue" is even nested in
 122    * scopes other than local loop scopes, like "if".
 123    * The result is, that the data flow isn't build right
 124    * and the pathfinder runs in invinity loop.
 125    * */
 126    /* if(n.getSimpleNode().getScope().equals(node.getSimpleNode().getScope())) {
 127    System.err.println("equals");
 128    continue;
 129    }
 130    else {
 131    System.err.println("don't equals");
 132    }
 133   
 134    //remove all children (should contain only one child)
 135    node.removePathToChild((IDataFlowNode)node.getChildren().get(0));
 136   
 137    node.addPathToChild(n);
 138    cbrStack.remove(0);
 139    break;
 140   
 141    }else if(n.isType(NodeType.DO_BEFOR_FIRST_STATEMENT)) {
 142   
 143    IDataFlowNode inode = (IDataFlowNode)n.getFlow().get(n.getIndex()1);
 144   
 145    for(int j=0;j<inode.getParents().size();j) {
 146    IDataFlowNode parent = (IDataFlowNode)inode.getParents().get(j);
 147   
 148    if(parent.isType(NodeType.DO_EXPR)) {
 149    node.removePathToChild((IDataFlowNode)node.getChildren().get(0));
 150    node.addPathToChild(parent);
 151   
 152    cbrStack.remove(0);
 153    break;
 154    }
 155    }
 156    break;
 157    }
 158    }
 159  1 */continueBreakReturnStack.remove(0); // delete this statement if you uncomment the stuff above
 160    }
 161    }
 162    }
 163   
 164  5 private IDataFlowNode getNodeToBreakStatement(IDataFlowNode node) {
 165    // What about breaks to labels above if statements?
 166  5 List bList = node.getFlow();
 167  5 int findEnds = 1; // ignore ends of other for's while's etc.
 168   
 169   
 170    // find out index of the node where the path goes to after the break
 171  5 int index = bList.indexOf(node);
 172  5 for (; index < bList.size()-2; index++) {
 173  4 IDataFlowNode n = (IDataFlowNode) bList.get(index);
 174  4 if (n.isType(NodeType.DO_EXPR) ||
 175    n.isType(NodeType.FOR_INIT) ||
 176    n.isType(NodeType.WHILE_EXPR) ||
 177    n.isType(NodeType.SWITCH_START)) {
 178  0 findEnds++;
 179    }
 180  4 if (n.isType(NodeType.WHILE_LAST_STATEMENT) ||
 181    n.isType(NodeType.SWITCH_END) ||
 182    n.isType(NodeType.FOR_END) ||
 183    n.isType(NodeType.DO_EXPR)) {
 184  1 if (findEnds > 1) {
 185    // thats not the right node
 186  0 findEnds--;
 187    } else {
 188  1 break;
 189    }
 190    }
 191   
 192  3 if (n.isType(NodeType.LABEL_LAST_STATEMENT)) {
 193  0 SimpleNode parentNode = (SimpleNode) n.getSimpleNode().getFirstParentOfType(ASTLabeledStatement.class);
 194  0 if (parentNode == null) {
 195  0 break;
 196    } else {
 197  0 String label = node.getSimpleNode().getImage();
 198  0 if (label == null || label.equals(parentNode.getImage())) {
 199  0 node.removePathToChild((IDataFlowNode) node.getChildren().get(0));
 200  0 IDataFlowNode last = (IDataFlowNode) bList.get(index + 1);
 201  0 node.addPathToChild(last);
 202  0 break;
 203    }
 204    }
 205    }
 206    }
 207  5 return (IDataFlowNode)node.getFlow().get(index+1);
 208    }
 209   
 210  3 private void computeDo(int first, int last) {
 211  3 IDataFlowNode doSt = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
 212  3 IDataFlowNode doExpr = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
 213  3 IDataFlowNode doFirst = (IDataFlowNode) doSt.getFlow().get(doSt.getIndex() + 1);
 214  3 if (doFirst.getIndex() != doExpr.getIndex()) {
 215  3 doExpr.addPathToChild(doFirst);
 216    }
 217    }
 218   
 219  26 private void computeFor(int firstIndex, int lastIndex) {
 220  26 IDataFlowNode fExpr = null;
 221  26 IDataFlowNode fUpdate = null;
 222  26 IDataFlowNode fSt = null;
 223  26 IDataFlowNode fEnd = null;
 224  26 boolean isUpdate = false;
 225   
 226  26 for (int i = firstIndex; i <= lastIndex; i++) {
 227  120 StackObject so = (StackObject) this.braceStack.get(i);
 228  120 IDataFlowNode node = so.getDataFlowNode();
 229   
 230  120 if (so.getType() == NodeType.FOR_EXPR) {
 231  26 fExpr = node;
 232  94 } else if (so.getType() == NodeType.FOR_UPDATE) {
 233  21 fUpdate = node;
 234  21 isUpdate = true;
 235  73 } else if (so.getType() == NodeType.FOR_BEFORE_FIRST_STATEMENT) {
 236  26 fSt = node;
 237  47 } else if (so.getType() == NodeType.FOR_END) {
 238  26 fEnd = node;
 239    }
 240    }
 241  26 IDataFlowNode end = (IDataFlowNode) fEnd.getFlow().get(fEnd.getIndex() + 1);
 242   
 243  26 IDataFlowNode firstSt = (IDataFlowNode) fSt.getChildren().get(0);
 244   
 245  26 if (isUpdate) {
 246  21 if (fSt.getIndex() != fEnd.getIndex()) {
 247  14 end.reverseParentPathsTo(fUpdate);
 248  14 fExpr.removePathToChild(fUpdate);
 249  14 fUpdate.addPathToChild(fExpr);
 250  14 fUpdate.removePathToChild(firstSt);
 251  14 fExpr.addPathToChild(firstSt);
 252  14 fExpr.addPathToChild(end);
 253    } else {
 254  7 fSt.removePathToChild(end);
 255  7 fExpr.removePathToChild(fUpdate);
 256  7 fUpdate.addPathToChild(fExpr);
 257  7 fExpr.addPathToChild(fUpdate);
 258  7 fExpr.addPathToChild(end);
 259    }
 260    } else {
 261  5 if (fSt.getIndex() != fEnd.getIndex()) {
 262  1 end.reverseParentPathsTo(fExpr);
 263  1 fExpr.addPathToChild(end);
 264    }
 265    }
 266    }
 267   
 268  3 private void computeSwitch(int firstIndex, int lastIndex) {
 269   
 270  3 int diff = lastIndex - firstIndex;
 271  3 boolean defaultStatement = false;
 272   
 273  3 IDataFlowNode sStart = ((StackObject) this.braceStack.get(firstIndex)).getDataFlowNode();
 274  3 IDataFlowNode sEnd = ((StackObject) this.braceStack.get(lastIndex)).getDataFlowNode();
 275  3 IDataFlowNode end = (IDataFlowNode) sEnd.getChildren().get(0);
 276   
 277  3 for (int i = 0; i < diff - 2; i++) {
 278  2 StackObject so = (StackObject) this.braceStack.get(firstIndex + 2 + i);
 279  2 IDataFlowNode node = so.getDataFlowNode();
 280   
 281  2 sStart.addPathToChild((IDataFlowNode) node.getChildren().get(0));
 282   
 283  2 if (so.getType() == NodeType.SWITCH_LAST_DEFAULT_STATEMENT)
 284  1 defaultStatement = true;
 285    }
 286   
 287  3 if (!defaultStatement)
 288  2 sStart.addPathToChild(end);
 289    }
 290   
 291  3 private void computeWhile(int first, int last) {
 292  3 IDataFlowNode wStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
 293  3 IDataFlowNode wEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
 294   
 295  3 IDataFlowNode end = (IDataFlowNode) wEnd.getFlow().get(wEnd.getIndex() + 1);
 296   
 297  3 if (wStart.getIndex() != wEnd.getIndex()) {
 298  2 end.reverseParentPathsTo(wStart);
 299  2 wStart.addPathToChild(end);
 300    }
 301    }
 302   
 303  11 private void computeIf(int first, int second, int last) {
 304  11 IDataFlowNode ifStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
 305  11 IDataFlowNode ifEnd = ((StackObject) this.braceStack.get(second)).getDataFlowNode();
 306  11 IDataFlowNode elseEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
 307   
 308  11 IDataFlowNode elseStart = (IDataFlowNode) ifEnd.getFlow().get(ifEnd.getIndex() + 1);
 309  11 IDataFlowNode end = (IDataFlowNode) elseEnd.getFlow().get(elseEnd.getIndex() + 1);
 310   
 311    // if if-statement and else-statement contains statements or expressions
 312  11 if (ifStart.getIndex() != ifEnd.getIndex() &&
 313    ifEnd.getIndex() != elseEnd.getIndex()) {
 314  11 elseStart.reverseParentPathsTo(end);
 315  11 ifStart.addPathToChild(elseStart);
 316    }
 317    // if only if-statement contains no expressions
 318  0 else if (ifStart.getIndex() == ifEnd.getIndex() &&
 319    ifEnd.getIndex() != elseEnd.getIndex()) {
 320  0 ifStart.addPathToChild(end);
 321    }
 322    // if only else-statement contains no expressions
 323  0 else if (ifEnd.getIndex() == elseEnd.getIndex() &&
 324    ifStart.getIndex() != ifEnd.getIndex()) {
 325  0 ifStart.addPathToChild(end);
 326    }
 327    }
 328   
 329  16 private void computeIf(int first, int last) {
 330  16 IDataFlowNode ifStart = ((StackObject) this.braceStack.get(first)).getDataFlowNode();
 331  16 IDataFlowNode ifEnd = ((StackObject) this.braceStack.get(last)).getDataFlowNode();
 332   
 333    // only if the if-statement contains another Statement or Expression
 334  16 if (ifStart.getIndex() != ifEnd.getIndex()) {
 335  13 IDataFlowNode end = (IDataFlowNode) ifEnd.getFlow().get(ifEnd.getIndex() + 1);
 336  13 ifStart.addPathToChild(end);
 337    }
 338    }
 339    }