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