View Javadoc

    1   package net.sourceforge.pmd.dfa;
    2
    3   import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
    4   import net.sourceforge.pmd.ast.ASTMethodDeclaration;
    5   import net.sourceforge.pmd.ast.SimpleNode;
    6
    7   import java.util.ArrayList;
    8   import java.util.BitSet;
    9   import java.util.HashMap;
    10  import java.util.LinkedList;
    11  import java.util.List;
    12  import java.util.Map;
    13  import java.util.StringTokenizer;
    14
    15  /***
    16   * @author raik
    17   *         <p/>
    18   *         Each data flow contains a set of DataFlowNodes.
    19   */
    20  public class DataFlowNode implements IDataFlowNode {
    21
    22      private SimpleNode node;
    23      private Map typeMap = new HashMap();
    24
    25      protected List parents = new ArrayList();
    26      protected List children = new ArrayList();
    27      protected BitSet type = new BitSet();
    28      protected List variableAccess = new ArrayList();
    29      protected LinkedList dataFlow;
    30      protected int line;
    31
    32      protected DataFlowNode() {
    33      }
    34
    35      public DataFlowNode(SimpleNode node, LinkedList dataFlow) {
    36          this.dataFlow = dataFlow;
    37          this.node = node;
    38
    39          node.setDataFlowNode(this);
    40          this.line = node.getBeginLine();
    41
    42          if (!this.dataFlow.isEmpty()) {
    43              DataFlowNode parent = (DataFlowNode) this.dataFlow.getLast();
    44              parent.addPathToChild(this);
    45          }
    46          this.dataFlow.addLast(this);
    47      }
    48
    49      public void addPathToChild(IDataFlowNode child) {
    50          DataFlowNode thisChild = (DataFlowNode) child;
    51          // TODO - throw an exception if already contained in children list?
    52          if (!this.children.contains(thisChild) || this.equals(thisChild)) {
    53              this.children.add(thisChild);
    54              thisChild.parents.add(this);
    55          }
    56      }
    57
    58      public boolean removePathToChild(IDataFlowNode child) {
    59          DataFlowNode thisChild = (DataFlowNode) child;
    60          thisChild.parents.remove(this);
    61          return this.children.remove(thisChild);
    62      }
    63
    64      public void reverseParentPathsTo(IDataFlowNode destination) {
    65          while (!parents.isEmpty()) {
    66              DataFlowNode parent = (DataFlowNode) parents.get(0);
    67              parent.removePathToChild(this);
    68              parent.addPathToChild(destination);
    69          }
    70      }
    71
    72      public int getLine() {
    73          return this.line;
    74      }
    75
    76      public void setType(int type) {
    77          this.type.set(type);
    78      }
    79
    80      public boolean isType(int intype) {
    81          try {
    82              return type.get(intype);
    83          } catch (IndexOutOfBoundsException e) {
    84              e.printStackTrace();
    85          }
    86          return false;
    87      }
    88
    89      public SimpleNode getSimpleNode() {
    90          return this.node;
    91      }
    92
    93      public List getChildren() {
    94          return this.children;
    95      }
    96
    97      public List getParents() {
    98          return this.parents;
    99      }
    100
    101     public List getFlow() {
    102         return this.dataFlow;
    103     }
    104
    105     public int getIndex() {
    106         return this.dataFlow.indexOf(this);
    107     }
    108
    109     public void setVariableAccess(List variableAccess) {
    110         if (this.variableAccess.isEmpty()) {
    111             this.variableAccess = variableAccess;
    112         } else {
    113             this.variableAccess.addAll(variableAccess);
    114         }
    115     }
    116
    117     public List getVariableAccess() {
    118         return this.variableAccess;
    119     }
    120
    121     public String toString() {
    122         String res = "DataFlowNode: line " + this.getLine() + ", ";
    123         if (node instanceof ASTMethodDeclaration || node instanceof ASTConstructorDeclaration) {
    124             res += (node instanceof ASTMethodDeclaration) ? "(method)" : "(constructor)";
    125         } else {
    126             String tmp = type.toString();
    127             String newTmp = "";
    128             for (int i = 0; i < tmp.length(); i++) {
    129                 if (tmp.charAt(i) != '{' && tmp.charAt(i) != '}' && tmp.charAt(i) != ' ') {
    130                     newTmp += tmp.charAt(i);
    131                 }
    132             }
    133             for (StringTokenizer st = new StringTokenizer(newTmp, ","); st.hasMoreTokens();) {
    134                 int newTmpInt = Integer.parseInt(st.nextToken());
    135                 res += "(" + stringFromType(newTmpInt) + ")";
    136             }
    137             res += ", " + this.node.getClass().getName().substring(node.getClass().getName().lastIndexOf('.') + 1);
    138             res += (node.getImage() == null ? "" : "(" + this.node.getImage() + ")");
    139         }
    140         return res;
    141     }
    142
    143     private String stringFromType(int intype) {
    144         if (typeMap.isEmpty()) {
    145             typeMap.put(new Integer(NodeType.IF_EXPR), "IF_EXPR");
    146             typeMap.put(new Integer(NodeType.IF_LAST_STATEMENT), "IF_LAST_STATEMENT");
    147             typeMap.put(new Integer(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE), "IF_LAST_STATEMENT_WITHOUT_ELSE");
    148             typeMap.put(new Integer(NodeType.ELSE_LAST_STATEMENT), "ELSE_LAST_STATEMENT");
    149             typeMap.put(new Integer(NodeType.WHILE_LAST_STATEMENT), "WHILE_LAST_STATEMENT");
    150             typeMap.put(new Integer(NodeType.WHILE_EXPR), "WHILE_EXPR");
    151             typeMap.put(new Integer(NodeType.SWITCH_START), "SWITCH_START");
    152             typeMap.put(new Integer(NodeType.CASE_LAST_STATEMENT), "CASE_LAST_STATEMENT");
    153             typeMap.put(new Integer(NodeType.SWITCH_LAST_DEFAULT_STATEMENT), "SWITCH_LAST_DEFAULT_STATEMENT");
    154             typeMap.put(new Integer(NodeType.SWITCH_END), "SWITCH_END");
    155             typeMap.put(new Integer(NodeType.FOR_INIT), "FOR_INIT");
    156             typeMap.put(new Integer(NodeType.FOR_EXPR), "FOR_EXPR");
    157             typeMap.put(new Integer(NodeType.FOR_UPDATE), "FOR_UPDATE");
    158             typeMap.put(new Integer(NodeType.FOR_BEFORE_FIRST_STATEMENT), "FOR_BEFORE_FIRST_STATEMENT");
    159             typeMap.put(new Integer(NodeType.FOR_END), "FOR_END");
    160             typeMap.put(new Integer(NodeType.DO_BEFORE_FIRST_STATEMENT), "DO_BEFORE_FIRST_STATEMENT");
    161             typeMap.put(new Integer(NodeType.DO_EXPR), "DO_EXPR");
    162             typeMap.put(new Integer(NodeType.RETURN_STATEMENT), "RETURN_STATEMENT");
    163             typeMap.put(new Integer(NodeType.BREAK_STATEMENT), "BREAK_STATEMENT");
    164             typeMap.put(new Integer(NodeType.CONTINUE_STATEMENT), "CONTINUE_STATEMENT");
    165             typeMap.put(new Integer(NodeType.LABEL_STATEMENT), "LABEL_STATEMENT");
    166             typeMap.put(new Integer(NodeType.LABEL_LAST_STATEMENT), "LABEL_END");
    167         }
    168         if (!typeMap.containsKey(new Integer(intype))) {
    169             throw new RuntimeException("Couldn't find type id " + intype);
    170         }
    171         return (String) typeMap.get(new Integer(intype));
    172     }
    173
    174 }