KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > code > flow > InputFlowAnalyzer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
11  * o inline call that is used in a field initializer
12  * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38137)
13  *******************************************************************************/

14 package org.eclipse.jdt.internal.corext.refactoring.code.flow;
15
16 import org.eclipse.core.runtime.Assert;
17
18 import org.eclipse.jface.text.IRegion;
19
20 import org.eclipse.jdt.core.dom.ASTNode;
21 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
22 import org.eclipse.jdt.core.dom.BodyDeclaration;
23 import org.eclipse.jdt.core.dom.ConditionalExpression;
24 import org.eclipse.jdt.core.dom.DoStatement;
25 import org.eclipse.jdt.core.dom.EnhancedForStatement;
26 import org.eclipse.jdt.core.dom.Expression;
27 import org.eclipse.jdt.core.dom.ForStatement;
28 import org.eclipse.jdt.core.dom.IfStatement;
29 import org.eclipse.jdt.core.dom.ReturnStatement;
30 import org.eclipse.jdt.core.dom.Statement;
31 import org.eclipse.jdt.core.dom.SwitchStatement;
32 import org.eclipse.jdt.core.dom.WhileStatement;
33
34 import org.eclipse.jdt.internal.corext.dom.Selection;
35
36 public class InputFlowAnalyzer extends FlowAnalyzer {
37     
38     private static class LoopReentranceVisitor extends FlowAnalyzer {
39         private Selection fSelection;
40         private ASTNode fLoopNode;
41         public LoopReentranceVisitor(FlowContext context, Selection selection, ASTNode loopNode) {
42             super(context);
43             fSelection= selection;
44             fLoopNode= loopNode;
45         }
46         protected boolean traverseNode(ASTNode node) {
47             return true; // end <= fSelection.end || fSelection.enclosedBy(start, end);
48
}
49         protected boolean createReturnFlowInfo(ReturnStatement node) {
50             // Make sure that the whole return statement is selected or located before the selection.
51
return node.getStartPosition() + node.getLength() <= fSelection.getExclusiveEnd();
52         }
53         protected ASTNode getLoopNode() {
54             return fLoopNode;
55         }
56         public void process(ASTNode node) {
57             try {
58                 fFlowContext.setLoopReentranceMode(true);
59                 node.accept(this);
60             } finally {
61                 fFlowContext.setLoopReentranceMode(false);
62             }
63         }
64         public void endVisit(DoStatement node) {
65             if (skipNode(node))
66                 return;
67             DoWhileFlowInfo info= createDoWhile();
68             setFlowInfo(node, info);
69             info.mergeAction(getFlowInfo(node.getBody()), fFlowContext);
70             // No need to merge the condition. It was already considered by the InputFlowAnalyzer.
71
info.removeLabel(null);
72         }
73         public void endVisit(EnhancedForStatement node) {
74             if (skipNode(node))
75                 return;
76             FlowInfo paramInfo= getFlowInfo(node.getParameter());
77             FlowInfo expressionInfo= getFlowInfo(node.getExpression());
78             FlowInfo actionInfo= getFlowInfo(node.getBody());
79             EnhancedForFlowInfo forInfo= createEnhancedFor();
80             setFlowInfo(node, forInfo);
81             // If the for statement is the outermost loop then we only have to consider
82
// the action. The parameter and expression are only evaluated once.
83
if (node == fLoopNode) {
84                 forInfo.mergeAction(actionInfo, fFlowContext);
85             } else {
86                 // Inner for loops are evaluated in the sequence expression, parameter,
87
// action.
88
forInfo.mergeExpression(expressionInfo, fFlowContext);
89                 forInfo.mergeParameter(paramInfo, fFlowContext);
90                 forInfo.mergeAction(actionInfo, fFlowContext);
91             }
92             forInfo.removeLabel(null);
93         }
94         public void endVisit(ForStatement node) {
95             if (skipNode(node))
96                 return;
97             FlowInfo initInfo= createSequential(node.initializers());
98             FlowInfo conditionInfo= getFlowInfo(node.getExpression());
99             FlowInfo incrementInfo= createSequential(node.updaters());
100             FlowInfo actionInfo= getFlowInfo(node.getBody());
101             ForFlowInfo forInfo= createFor();
102             setFlowInfo(node, forInfo);
103             // the for statement is the outermost loop. In this case we only have
104
// to consider the increment, condition and action.
105
if (node == fLoopNode) {
106                 forInfo.mergeIncrement(incrementInfo, fFlowContext);
107                 forInfo.mergeCondition(conditionInfo, fFlowContext);
108                 forInfo.mergeAction(actionInfo, fFlowContext);
109             } else {
110                 // we have to merge two different cases. One if we reenter the for statement
111
// immediatelly (that means we have to consider increments, condition and action)
112
// and the other case if we reenter the for in the next loop of
113
// the outer loop. Then we have to consider initializations, condtion and action.
114
// For a conditional flow info that means:
115
// (initializations | increments) & condition & action.
116
GenericConditionalFlowInfo initIncr= new GenericConditionalFlowInfo();
117                 initIncr.merge(initInfo, fFlowContext);
118                 initIncr.merge(incrementInfo, fFlowContext);
119                 forInfo.mergeAccessModeSequential(initIncr, fFlowContext);
120                 forInfo.mergeCondition(conditionInfo, fFlowContext);
121                 forInfo.mergeAction(actionInfo, fFlowContext);
122             }
123             forInfo.removeLabel(null);
124         }
125     }
126     
127     private Selection fSelection;
128     private boolean fDoLoopReentrance;
129     private LoopReentranceVisitor fLoopReentranceVisitor;
130
131     public InputFlowAnalyzer(FlowContext context, Selection selection, boolean doLoopReentrance) {
132         super(context);
133         fSelection= selection;
134         Assert.isNotNull(fSelection);
135         fDoLoopReentrance= doLoopReentrance;
136     }
137
138     public FlowInfo perform(BodyDeclaration node) {
139         Assert.isTrue(!(node instanceof AbstractTypeDeclaration));
140         node.accept(this);
141         return getFlowInfo(node);
142     }
143     
144     protected boolean traverseNode(ASTNode node) {
145         return node.getStartPosition() + node.getLength() > fSelection.getInclusiveEnd();
146     }
147     
148     protected boolean createReturnFlowInfo(ReturnStatement node) {
149         // Make sure that the whole return statement is located after the selection. There can be cases like
150
// return i + [x + 10] * 10; In this case we must not create a return info node.
151
return node.getStartPosition() >= fSelection.getInclusiveEnd();
152     }
153     
154     public boolean visit(DoStatement node) {
155         createLoopReentranceVisitor(node);
156         return super.visit(node);
157     }
158     
159     public boolean visit(EnhancedForStatement node) {
160         createLoopReentranceVisitor(node);
161         return super.visit(node);
162     }
163     
164     public boolean visit(ForStatement node) {
165         createLoopReentranceVisitor(node);
166         return super.visit(node);
167     }
168     
169     public boolean visit(WhileStatement node) {
170         createLoopReentranceVisitor(node);
171         return super.visit(node);
172     }
173     
174     private void createLoopReentranceVisitor(ASTNode node) {
175         if (fLoopReentranceVisitor == null && fDoLoopReentrance)
176             fLoopReentranceVisitor= new LoopReentranceVisitor(fFlowContext, fSelection, node);
177     }
178     
179     public void endVisit(ConditionalExpression node) {
180         if (skipNode(node))
181             return;
182         Expression thenPart= node.getThenExpression();
183         Expression elsePart= node.getElseExpression();
184         if ((thenPart != null && fSelection.coveredBy(thenPart)) ||
185                 (elsePart != null && fSelection.coveredBy(elsePart))) {
186             GenericSequentialFlowInfo info= createSequential();
187             setFlowInfo(node, info);
188             endVisitConditional(info, node.getExpression(), new ASTNode[] {thenPart, elsePart});
189         } else {
190             super.endVisit(node);
191         }
192     }
193     
194     public void endVisit(DoStatement node) {
195         super.endVisit(node);
196         handleLoopReentrance(node);
197     }
198
199     public void endVisit(IfStatement node) {
200         if (skipNode(node))
201             return;
202         Statement thenPart= node.getThenStatement();
203         Statement elsePart= node.getElseStatement();
204         if ((thenPart != null && fSelection.coveredBy(thenPart)) ||
205                 (elsePart != null && fSelection.coveredBy(elsePart))) {
206             GenericSequentialFlowInfo info= createSequential();
207             setFlowInfo(node, info);
208             endVisitConditional(info, node.getExpression(), new ASTNode[] {thenPart, elsePart});
209         } else {
210             super.endVisit(node);
211         }
212     }
213     
214     public void endVisit(EnhancedForStatement node) {
215         super.endVisit(node);
216         handleLoopReentrance(node);
217     }
218     
219     public void endVisit(ForStatement node) {
220         super.endVisit(node);
221         handleLoopReentrance(node);
222     }
223     
224     public void endVisit(SwitchStatement node) {
225         if (skipNode(node))
226             return;
227         SwitchData data= createSwitchData(node);
228         IRegion[] ranges= data.getRanges();
229         for (int i= 0; i < ranges.length; i++) {
230             IRegion range= ranges[i];
231             if (fSelection.coveredBy(range)) {
232                 GenericSequentialFlowInfo info= createSequential();
233                 setFlowInfo(node, info);
234                 info.merge(getFlowInfo(node.getExpression()), fFlowContext);
235                 info.merge(data.getInfo(i), fFlowContext);
236                 info.removeLabel(null);
237                 return;
238             }
239         }
240         super.endVisit(node, data);
241     }
242     
243     public void endVisit(WhileStatement node) {
244         super.endVisit(node);
245         handleLoopReentrance(node);
246     }
247     
248     private void endVisitConditional(GenericSequentialFlowInfo info, ASTNode condition, ASTNode[] branches) {
249         info.merge(getFlowInfo(condition), fFlowContext);
250         for (int i= 0; i < branches.length; i++) {
251             ASTNode branch= branches[i];
252             if (branch != null && fSelection.coveredBy(branch)) {
253                 info.merge(getFlowInfo(branch), fFlowContext);
254                 break;
255             }
256         }
257     }
258     
259     private void handleLoopReentrance(ASTNode node) {
260         if (!fSelection.coveredBy(node) || fLoopReentranceVisitor == null || fLoopReentranceVisitor.getLoopNode() != node)
261             return;
262         
263         fLoopReentranceVisitor.process(node);
264         GenericSequentialFlowInfo info= createSequential();
265         info.merge(getFlowInfo(node), fFlowContext);
266         info.merge(fLoopReentranceVisitor.getFlowInfo(node), fFlowContext);
267         setFlowInfo(node, info);
268     }
269 }
270
Popular Tags