View Javadoc

1   /*
2    * Created on 11.07.2004
3    */
4   package net.sourceforge.pmd.dfa;
5   
6   import net.sourceforge.pmd.ast.*;
7   
8   /***
9    * @author raik
10   *         <p/>
11   *         Sublayer of DataFlowFacade. Finds all data flow nodes and stores the
12   *         type information (@see StackObject). At last it uses this information to
13   *         link the nodes.
14   */
15  public class StatementAndBraceFinder extends JavaParserVisitorAdapter {
16  
17      private Structure dataFlow;
18  
19      public void buildDataFlowFor(SimpleJavaNode node) {
20          if (!(node instanceof ASTMethodDeclaration) && !(node instanceof ASTConstructorDeclaration)) {
21              throw new RuntimeException("Can't build a data flow for anything other than a method or a constructor");
22          }
23  
24          this.dataFlow = new Structure();
25          this.dataFlow.createStartNode(node.getBeginLine());
26          this.dataFlow.createNewNode(node);
27  
28          node.jjtAccept(this, dataFlow);
29  
30          this.dataFlow.createEndNode(node.getEndLine());
31  
32          Linker linker = new Linker(dataFlow.getBraceStack(), dataFlow.getContinueBreakReturnStack());
33          try {
34              linker.computePaths();
35          } catch (LinkerException e) {
36              e.printStackTrace();
37          } catch (SequenceException e) {
38              e.printStackTrace();
39          }
40      }
41  
42      public Object visit(ASTStatementExpression node, Object data) {
43          if (!(data instanceof Structure)) {
44              return data;
45          }
46          Structure dataFlow = (Structure) data;
47          dataFlow.createNewNode(node);
48          return super.visit(node, data);
49      }
50  
51      public Object visit(ASTVariableDeclarator node, Object data) {
52          if (!(data instanceof Structure)) {
53              return data;
54          }
55          Structure dataFlow = (Structure) data;
56          dataFlow.createNewNode(node);
57          return super.visit(node, data);
58      }
59  
60      public Object visit(ASTExpression node, Object data) {
61          if (!(data instanceof Structure)) {
62              return data;
63          }
64          Structure dataFlow = (Structure) data;
65  
66          // TODO what about throw stmts?
67          if (node.jjtGetParent() instanceof ASTIfStatement) {
68              dataFlow.createNewNode(node); // START IF
69              dataFlow.pushOnStack(NodeType.IF_EXPR, dataFlow.getLast());
70          } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
71              dataFlow.createNewNode(node); // START WHILE
72              dataFlow.pushOnStack(NodeType.WHILE_EXPR, dataFlow.getLast());
73          } else if (node.jjtGetParent() instanceof ASTSwitchStatement) {
74              dataFlow.createNewNode(node); // START SWITCH
75              dataFlow.pushOnStack(NodeType.SWITCH_START, dataFlow.getLast());
76          } else if (node.jjtGetParent() instanceof ASTForStatement) {
77              dataFlow.createNewNode(node); // FOR EXPR
78              dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
79          } else if (node.jjtGetParent() instanceof ASTDoStatement) {
80              dataFlow.createNewNode(node); // DO EXPR
81              dataFlow.pushOnStack(NodeType.DO_EXPR, dataFlow.getLast());
82          }
83  
84          return super.visit(node, data);
85      }
86  
87      public Object visit(ASTForInit node, Object data) {
88          if (!(data instanceof Structure)) {
89              return data;
90          }
91          Structure dataFlow = (Structure) data;
92          super.visit(node, data);
93          dataFlow.pushOnStack(NodeType.FOR_INIT, dataFlow.getLast());
94          this.addForExpressionNode(node, dataFlow);
95          return data;
96      }
97  
98      public Object visit(ASTForUpdate node, Object data) {
99          if (!(data instanceof Structure)) {
100             return data;
101         }
102         Structure dataFlow = (Structure) data;
103         this.addForExpressionNode(node, dataFlow);
104         super.visit(node, data);
105         dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
106         return data;
107     }
108 
109 // 	----------------------------------------------------------------------------
110 //  BRANCH OUT
111 
112     public Object visit(ASTStatement node, Object data) {
113         if (!(data instanceof Structure)) {
114             return data;
115         }
116         Structure dataFlow = (Structure) data;
117 
118         if (node.jjtGetParent() instanceof ASTForStatement) {
119             this.addForExpressionNode(node, dataFlow);
120             dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
121         } else if (node.jjtGetParent() instanceof ASTDoStatement) {
122             dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
123             dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
124         }
125 
126         super.visit(node, data);
127 
128         if (node.jjtGetParent() instanceof ASTIfStatement) {
129             ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
130             if (!st.hasElse()) {
131                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
132             } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
133                 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
134             } else {
135                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
136             }
137         } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
138             dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
139         } else if (node.jjtGetParent() instanceof ASTForStatement) {
140             dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
141         }
142         return data;
143     }
144 
145     public Object visit(ASTSwitchStatement node, Object data) {
146         if (!(data instanceof Structure)) {
147             return data;
148         }
149         Structure dataFlow = (Structure) data;
150         super.visit(node, data);
151         dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
152         return data;
153     }
154 
155     public Object visit(ASTSwitchLabel node, Object data) {
156         if (!(data instanceof Structure)) {
157             return data;
158         }
159         Structure dataFlow = (Structure) data;
160         //super.visit(node, data);
161         if (node.jjtGetNumChildren() == 0) {
162             dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
163         } else {
164             dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
165         }
166         return data;
167     }
168 
169     public Object visit(ASTBreakStatement node, Object data) {
170         if (!(data instanceof Structure)) {
171             return data;
172         }
173         Structure dataFlow = (Structure) data;
174         dataFlow.createNewNode(node);
175         dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
176         return super.visit(node, data);
177     }
178 
179 
180     public Object visit(ASTContinueStatement node, Object data) {
181         if (!(data instanceof Structure)) {
182             return data;
183         }
184         Structure dataFlow = (Structure) data;
185         dataFlow.createNewNode(node);
186         dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
187         return super.visit(node, data);
188     }
189 
190     public Object visit(ASTReturnStatement node, Object data) {
191         if (!(data instanceof Structure)) {
192             return data;
193         }
194         Structure dataFlow = (Structure) data;
195         dataFlow.createNewNode(node);
196         dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
197         return super.visit(node, data);
198     }
199 
200     /*
201      * The method handles the special "for" loop. It creates always an
202      * expression node even if the loop looks like for(;;).
203      * */
204     private void addForExpressionNode(SimpleNode node, Structure dataFlow) {
205         ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
206         boolean hasExpressionChild = false;
207         boolean hasForInitNode = false;
208         boolean hasForUpdateNode = false;
209 
210         for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
211             if (parent.jjtGetChild(i) instanceof ASTExpression)
212                 hasExpressionChild = true;
213             else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
214                 hasForUpdateNode = true;
215             else if (parent.jjtGetChild(i) instanceof ASTForInit)
216                 hasForInitNode = true;
217         }
218         if (!hasExpressionChild) {
219             if (node instanceof ASTForInit) {
220                 dataFlow.createNewNode(node);
221                 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
222             } else if (node instanceof ASTForUpdate) {
223                 if (!hasForInitNode) {
224                     dataFlow.createNewNode(node);
225                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
226                 }
227             } else if (node instanceof ASTStatement) {
228                 if (!hasForInitNode && !hasForUpdateNode) {
229                     dataFlow.createNewNode(node);
230                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
231                 }
232             }
233         }
234     }
235 }