View Javadoc

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