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         }
166         if (!typeMap.containsKey(new Integer(intype))) {
167             throw new RuntimeException("Couldn't find type id " + intype);
168         }
169         return (String) typeMap.get(new Integer(intype));
170     }
171 
172 }