1 11 package org.eclipse.jdt.internal.ui.search; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.List ; 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 fResult; 58 private List fCatchedExceptions; 59 60 public String initialize(CompilationUnit root, int offset, int length) { 61 return initialize(root, NodeFinder.perform(root, offset, length)); 62 } 63 64 public String 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 perform() { 94 fResult= new ArrayList (); 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 (); 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 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"); name.setSourceRange(fMethodDeclaration.getStartPosition() + fMethodDeclaration.getLength() - 1, 1); 131 fResult.add(name); 132 } 133 } 134 135 public boolean visit(TypeDeclaration node) { 136 return false; 138 } 139 140 public boolean visit(AnonymousClassDeclaration node) { 141 return false; 143 } 144 145 public boolean visit(AnnotationTypeDeclaration node) { 146 return false; 148 } 149 150 public boolean visit(EnumDeclaration node) { 151 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 catchClauses= node.catchClauses(); 163 for (Iterator 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 for (Iterator 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; 184 } 185 186 public boolean visit(ThrowStatement node) { 187 ITypeBinding exception= node.getExpression().resolveTypeBinding(); 188 if (isExitPoint(exception)) { 189 SimpleName name= fAST.newSimpleName("xxxxx"); 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 SimpleName name= fAST.newSimpleName("xxxx"); 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"); 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 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 |