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.*;
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(ASTLabeledStatement node, Object data) {
99          dataFlow.createNewNode(node);
100         dataFlow.pushOnStack(NodeType.LABEL_STATEMENT, dataFlow.getLast());
101         return super.visit(node, data);
102     }
103 
104     public Object visit(ASTForUpdate node, Object data) {
105         if (!(data instanceof Structure)) {
106             return data;
107         }
108         Structure dataFlow = (Structure) data;
109         this.addForExpressionNode(node, dataFlow);
110         super.visit(node, data);
111         dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
112         return data;
113     }
114 
115 // 	----------------------------------------------------------------------------
116 //  BRANCH OUT
117 
118     public Object visit(ASTStatement node, Object data) {
119         if (!(data instanceof Structure)) {
120             return data;
121         }
122         Structure dataFlow = (Structure) data;
123 
124         if (node.jjtGetParent() instanceof ASTForStatement) {
125             this.addForExpressionNode(node, dataFlow);
126             dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
127         } else if (node.jjtGetParent() instanceof ASTDoStatement) {
128             dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
129             dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
130         }
131 
132         super.visit(node, data);
133 
134         if (node.jjtGetParent() instanceof ASTIfStatement) {
135             ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
136             if (!st.hasElse()) {
137                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
138             } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
139                 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
140             } else {
141                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
142             }
143         } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
144             dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
145         } else if (node.jjtGetParent() instanceof ASTForStatement) {
146             dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
147         } else if (node.jjtGetParent() instanceof ASTLabeledStatement) {
148             dataFlow.pushOnStack(NodeType.LABEL_LAST_STATEMENT, dataFlow.getLast());
149         }
150         return data;
151     }
152 
153     public Object visit(ASTSwitchStatement node, Object data) {
154         if (!(data instanceof Structure)) {
155             return data;
156         }
157         Structure dataFlow = (Structure) data;
158         super.visit(node, data);
159         dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
160         return data;
161     }
162 
163     public Object visit(ASTSwitchLabel node, Object data) {
164         if (!(data instanceof Structure)) {
165             return data;
166         }
167         Structure dataFlow = (Structure) data;
168         //super.visit(node, data);
169         if (node.jjtGetNumChildren() == 0) {
170             dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
171         } else {
172             dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
173         }
174         return data;
175     }
176 
177     public Object visit(ASTBreakStatement node, Object data) {
178         if (!(data instanceof Structure)) {
179             return data;
180         }
181         Structure dataFlow = (Structure) data;
182         dataFlow.createNewNode(node);
183         dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
184         return super.visit(node, data);
185     }
186 
187 
188     public Object visit(ASTContinueStatement node, Object data) {
189         if (!(data instanceof Structure)) {
190             return data;
191         }
192         Structure dataFlow = (Structure) data;
193         dataFlow.createNewNode(node);
194         dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
195         return super.visit(node, data);
196     }
197 
198     public Object visit(ASTReturnStatement node, Object data) {
199         if (!(data instanceof Structure)) {
200             return data;
201         }
202         Structure dataFlow = (Structure) data;
203         dataFlow.createNewNode(node);
204         dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
205         return super.visit(node, data);
206     }
207 
208     public Object visit(ASTThrowStatement node, Object data) {
209         if (!(data instanceof Structure)) {
210             return data;
211         }
212         Structure dataFlow = (Structure) data;
213         dataFlow.createNewNode(node);
214         dataFlow.pushOnStack(NodeType.THROW_STATEMENT, dataFlow.getLast());
215         return super.visit(node, data);
216     }
217 
218     /*
219      * The method handles the special "for" loop. It creates always an
220      * expression node even if the loop looks like for(;;).
221      * */
222     private void addForExpressionNode(SimpleNode node, Structure dataFlow) {
223         ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
224         boolean hasExpressionChild = false;
225         boolean hasForInitNode = false;
226         boolean hasForUpdateNode = false;
227 
228         for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
229             if (parent.jjtGetChild(i) instanceof ASTExpression)
230                 hasExpressionChild = true;
231             else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
232                 hasForUpdateNode = true;
233             else if (parent.jjtGetChild(i) instanceof ASTForInit)
234                 hasForInitNode = true;
235         }
236         if (!hasExpressionChild) {
237             if (node instanceof ASTForInit) {
238                 dataFlow.createNewNode(node);
239                 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
240             } else if (node instanceof ASTForUpdate) {
241                 if (!hasForInitNode) {
242                     dataFlow.createNewNode(node);
243                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
244                 }
245             } else if (node instanceof ASTStatement) {
246                 if (!hasForInitNode && !hasForUpdateNode) {
247                     dataFlow.createNewNode(node);
248                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
249                 }
250             }
251         }
252     }
253 }