View Javadoc

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