KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > search > MethodExitsFinder


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.search;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.jdt.core.dom.AST;
18 import org.eclipse.jdt.core.dom.ASTNode;
19 import org.eclipse.jdt.core.dom.ASTVisitor;
20 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
21 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
22 import org.eclipse.jdt.core.dom.Block;
23 import org.eclipse.jdt.core.dom.CatchClause;
24 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
25 import org.eclipse.jdt.core.dom.CompilationUnit;
26 import org.eclipse.jdt.core.dom.ConstructorInvocation;
27 import org.eclipse.jdt.core.dom.EnumDeclaration;
28 import org.eclipse.jdt.core.dom.IMethodBinding;
29 import org.eclipse.jdt.core.dom.ITypeBinding;
30 import org.eclipse.jdt.core.dom.IVariableBinding;
31 import org.eclipse.jdt.core.dom.MethodDeclaration;
32 import org.eclipse.jdt.core.dom.MethodInvocation;
33 import org.eclipse.jdt.core.dom.Name;
34 import org.eclipse.jdt.core.dom.ReturnStatement;
35 import org.eclipse.jdt.core.dom.SimpleName;
36 import org.eclipse.jdt.core.dom.Statement;
37 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
38 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
39 import org.eclipse.jdt.core.dom.ThrowStatement;
40 import org.eclipse.jdt.core.dom.TryStatement;
41 import org.eclipse.jdt.core.dom.Type;
42 import org.eclipse.jdt.core.dom.TypeDeclaration;
43
44 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
45 import org.eclipse.jdt.internal.corext.dom.Bindings;
46 import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex;
47 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
48 import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext;
49 import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowInfo;
50 import org.eclipse.jdt.internal.corext.refactoring.code.flow.InOutFlowAnalyzer;
51
52
53 public class MethodExitsFinder extends ASTVisitor {
54     
55     private AST fAST;
56     private MethodDeclaration fMethodDeclaration;
57     private List JavaDoc fResult;
58     private List JavaDoc fCatchedExceptions;
59
60     public String JavaDoc initialize(CompilationUnit root, int offset, int length) {
61         return initialize(root, NodeFinder.perform(root, offset, length));
62     }
63     
64     public String JavaDoc initialize(CompilationUnit root, ASTNode node) {
65         fAST= root.getAST();
66         
67         if (node instanceof ReturnStatement) {
68             fMethodDeclaration= (MethodDeclaration)ASTNodes.getParent(node, ASTNode.METHOD_DECLARATION);
69             if (fMethodDeclaration == null)
70                 return SearchMessages.MethodExitsFinder_no_return_type_selected;
71             return null;
72             
73         }
74         
75         Type type= null;
76         if (node instanceof Type) {
77             type= (Type)node;
78         } else if (node instanceof Name) {
79             Name name= ASTNodes.getTopMostName((Name)node);
80             if (name.getParent() instanceof Type) {
81                 type= (Type)name.getParent();
82             }
83         }
84         if (type == null)
85             return SearchMessages.MethodExitsFinder_no_return_type_selected;
86         type= ASTNodes.getTopMostType(type);
87         if (!(type.getParent() instanceof MethodDeclaration))
88             return SearchMessages.MethodExitsFinder_no_return_type_selected;
89         fMethodDeclaration= (MethodDeclaration)type.getParent();
90         return null;
91     }
92
93     public List JavaDoc perform() {
94         fResult= new ArrayList JavaDoc();
95         markReferences();
96         if (fResult.size() > 0) {
97             Type returnType= fMethodDeclaration.getReturnType2();
98             if (returnType != null)
99                 fResult.add(fMethodDeclaration.getReturnType2());
100         }
101         return fResult;
102     }
103     
104     private void markReferences() {
105         fCatchedExceptions= new ArrayList JavaDoc();
106         boolean isVoid= true;
107         Type returnType= fMethodDeclaration.getReturnType2();
108         if (returnType != null) {
109             ITypeBinding returnTypeBinding= returnType.resolveBinding();
110             isVoid= returnTypeBinding != null && Bindings.isVoidType(returnTypeBinding);
111         }
112         fMethodDeclaration.accept(this);
113         Block block= fMethodDeclaration.getBody();
114         if (block != null) {
115             List JavaDoc statements= block.statements();
116             if (statements.size() > 0) {
117                 Statement last= (Statement)statements.get(statements.size() - 1);
118                 int maxVariableId= LocalVariableIndex.perform(fMethodDeclaration);
119                 FlowContext flowContext= new FlowContext(0, maxVariableId + 1);
120                 flowContext.setConsiderAccessMode(false);
121                 flowContext.setComputeMode(FlowContext.ARGUMENTS);
122                 InOutFlowAnalyzer flowAnalyzer= new InOutFlowAnalyzer(flowContext);
123                 FlowInfo info= flowAnalyzer.perform(new ASTNode[] {last});
124                 if (!info.isNoReturn() && !isVoid) {
125                     if (!info.isPartialReturn())
126                         return;
127                 }
128             }
129             SimpleName name= fAST.newSimpleName("x"); //$NON-NLS-1$
130
name.setSourceRange(fMethodDeclaration.getStartPosition() + fMethodDeclaration.getLength() - 1, 1);
131             fResult.add(name);
132         }
133     }
134
135     public boolean visit(TypeDeclaration node) {
136         // Don't dive into a local type.
137
return false;
138     }
139
140     public boolean visit(AnonymousClassDeclaration node) {
141         // Don't dive into a local type.
142
return false;
143     }
144
145     public boolean visit(AnnotationTypeDeclaration node) {
146         // Don't dive into a local type.
147
return false;
148     }
149
150     public boolean visit(EnumDeclaration node) {
151         // Don't dive into a local type.
152
return false;
153     }
154
155     public boolean visit(ReturnStatement node) {
156         fResult.add(node);
157         return super.visit(node);
158     }
159     
160     public boolean visit(TryStatement node) {
161         int currentSize= fCatchedExceptions.size();
162         List JavaDoc catchClauses= node.catchClauses();
163         for (Iterator JavaDoc iter= catchClauses.iterator(); iter.hasNext();) {
164             IVariableBinding variable= ((CatchClause)iter.next()).getException().resolveBinding();
165             if (variable != null && variable.getType() != null) {
166                 fCatchedExceptions.add(variable.getType());
167             }
168         }
169         node.getBody().accept(this);
170         int toRemove= fCatchedExceptions.size() - currentSize;
171         for(int i= toRemove; i > 0; i--) {
172             fCatchedExceptions.remove(currentSize);
173         }
174         
175         // visit catch and finally
176
for (Iterator JavaDoc iter= catchClauses.iterator(); iter.hasNext(); ) {
177             ((CatchClause)iter.next()).accept(this);
178         }
179         if (node.getFinally() != null)
180             node.getFinally().accept(this);
181             
182         // return false. We have visited the body by ourselves.
183
return false;
184     }
185     
186     public boolean visit(ThrowStatement node) {
187         ITypeBinding exception= node.getExpression().resolveTypeBinding();
188         if (isExitPoint(exception)) {
189             SimpleName name= fAST.newSimpleName("xxxxx"); //$NON-NLS-1$
190
name.setSourceRange(node.getStartPosition(), 5);
191             fResult.add(name);
192         }
193         return true;
194     }
195     
196     public boolean visit(MethodInvocation node) {
197         if (isExitPoint(node.resolveMethodBinding())) {
198             fResult.add(node.getName());
199         }
200         return true;
201     }
202     
203     public boolean visit(SuperMethodInvocation node) {
204         if (isExitPoint(node.resolveMethodBinding())) {
205             fResult.add(node.getName());
206         }
207         return true;
208     }
209     
210     public boolean visit(ClassInstanceCreation node) {
211         if (isExitPoint(node.resolveConstructorBinding())) {
212             fResult.add(node.getType());
213         }
214         return true;
215     }
216     
217     public boolean visit(ConstructorInvocation node) {
218         if (isExitPoint(node.resolveConstructorBinding())) {
219             // mark this
220
SimpleName name= fAST.newSimpleName("xxxx"); //$NON-NLS-1$
221
name.setSourceRange(node.getStartPosition(), 4);
222             fResult.add(name);
223         }
224         return true;
225     }
226     
227     public boolean visit(SuperConstructorInvocation node) {
228         if (isExitPoint(node.resolveConstructorBinding())) {
229             SimpleName name= fAST.newSimpleName("xxxxx"); //$NON-NLS-1$
230
name.setSourceRange(node.getStartPosition(), 5);
231             fResult.add(name);
232         }
233         return true;
234     }
235     
236     private boolean isExitPoint(ITypeBinding binding) {
237         if (binding == null)
238             return false;
239         return !isCatched(binding);
240     }
241     
242     private boolean isExitPoint(IMethodBinding binding) {
243         if (binding == null)
244             return false;
245         ITypeBinding[] exceptions= binding.getExceptionTypes();
246         for (int i= 0; i < exceptions.length; i++) {
247             if (!isCatched(exceptions[i]))
248                 return true;
249         }
250         return false;
251     }
252     
253     private boolean isCatched(ITypeBinding binding) {
254         for (Iterator JavaDoc iter= fCatchedExceptions.iterator(); iter.hasNext();) {
255             ITypeBinding catchException= (ITypeBinding)iter.next();
256             if (catches(catchException, binding))
257                 return true;
258         }
259         return false;
260     }
261     
262     private boolean catches(ITypeBinding catchTypeBinding, ITypeBinding throwTypeBinding) {
263         while(throwTypeBinding != null) {
264             if (throwTypeBinding == catchTypeBinding)
265                 return true;
266             throwTypeBinding= throwTypeBinding.getSuperclass();
267         }
268         return false;
269     }
270 }
271
Popular Tags