1 12 package org.eclipse.jdt.internal.corext.callhierarchy; 13 14 import java.util.Collection ; 15 import java.util.Map ; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 import org.eclipse.core.runtime.OperationCanceledException; 19 20 import org.eclipse.jdt.core.IMember; 21 import org.eclipse.jdt.core.IMethod; 22 import org.eclipse.jdt.core.ISourceRange; 23 import org.eclipse.jdt.core.IType; 24 import org.eclipse.jdt.core.JavaModelException; 25 import org.eclipse.jdt.core.dom.ASTNode; 26 import org.eclipse.jdt.core.dom.ASTVisitor; 27 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 28 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 29 import org.eclipse.jdt.core.dom.CompilationUnit; 30 import org.eclipse.jdt.core.dom.ConstructorInvocation; 31 import org.eclipse.jdt.core.dom.IMethodBinding; 32 import org.eclipse.jdt.core.dom.ITypeBinding; 33 import org.eclipse.jdt.core.dom.MethodDeclaration; 34 import org.eclipse.jdt.core.dom.MethodInvocation; 35 import org.eclipse.jdt.core.dom.SuperConstructorInvocation; 36 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 37 import org.eclipse.jdt.core.search.IJavaSearchScope; 38 39 import org.eclipse.jdt.internal.corext.dom.Bindings; 40 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 41 42 import org.eclipse.jdt.internal.ui.JavaPlugin; 43 44 class CalleeAnalyzerVisitor extends ASTVisitor { 45 private CallSearchResultCollector fSearchResults; 46 private IMethod fMethod; 47 private CompilationUnit fCompilationUnit; 48 private IProgressMonitor fProgressMonitor; 49 private int fMethodEndPosition; 50 private int fMethodStartPosition; 51 52 CalleeAnalyzerVisitor(IMethod method, CompilationUnit compilationUnit, IProgressMonitor progressMonitor) { 53 fSearchResults = new CallSearchResultCollector(); 54 this.fMethod = method; 55 this.fCompilationUnit= compilationUnit; 56 this.fProgressMonitor = progressMonitor; 57 58 try { 59 ISourceRange sourceRange = method.getSourceRange(); 60 this.fMethodStartPosition = sourceRange.getOffset(); 61 this.fMethodEndPosition = fMethodStartPosition + sourceRange.getLength(); 62 } catch (JavaModelException jme) { 63 JavaPlugin.log(jme); 64 } 65 } 66 67 72 public Map getCallees() { 73 return fSearchResults.getCallers(); 74 } 75 76 79 public boolean visit(ClassInstanceCreation node) { 80 progressMonitorWorked(1); 81 if (!isFurtherTraversalNecessary(node)) { 82 return false; 83 } 84 85 if (isNodeWithinMethod(node)) { 86 addMethodCall(node.resolveConstructorBinding(), node); 87 } 88 89 return true; 90 } 91 92 99 public boolean visit(ConstructorInvocation node) { 100 progressMonitorWorked(1); 101 if (!isFurtherTraversalNecessary(node)) { 102 return false; 103 } 104 105 if (isNodeWithinMethod(node)) { 106 addMethodCall(node.resolveConstructorBinding(), node); 107 } 108 109 return true; 110 } 111 112 115 public boolean visit(MethodDeclaration node) { 116 progressMonitorWorked(1); 117 return isFurtherTraversalNecessary(node); 118 } 119 120 127 public boolean visit(MethodInvocation node) { 128 progressMonitorWorked(1); 129 if (!isFurtherTraversalNecessary(node)) { 130 return false; 131 } 132 133 if (isNodeWithinMethod(node)) { 134 addMethodCall(node.resolveMethodBinding(), node); 135 } 136 137 return true; 138 } 139 140 148 public boolean visit(SuperConstructorInvocation node) { 149 progressMonitorWorked(1); 150 if (!isFurtherTraversalNecessary(node)) { 151 return false; 152 } 153 154 if (isNodeWithinMethod(node)) { 155 addMethodCall(node.resolveConstructorBinding(), node); 156 } 157 158 return true; 159 } 160 161 168 public boolean visit(SuperMethodInvocation node) { 169 progressMonitorWorked(1); 170 if (!isFurtherTraversalNecessary(node)) { 171 return false; 172 } 173 174 if (isNodeWithinMethod(node)) { 175 addMethodCall(node.resolveMethodBinding(), node); 176 } 177 178 return true; 179 } 180 181 187 public boolean visit(AnonymousClassDeclaration node) { 188 return isNodeEnclosingMethod(node); 189 } 190 191 192 198 protected void addMethodCall(IMethodBinding calledMethodBinding, ASTNode node) { 199 try { 200 if (calledMethodBinding != null) { 201 fProgressMonitor.worked(1); 202 203 ITypeBinding calledTypeBinding = calledMethodBinding.getDeclaringClass(); 204 IType calledType = null; 205 206 if (!calledTypeBinding.isAnonymous()) { 207 calledType = (IType) calledTypeBinding.getJavaElement(); 208 } else { 209 if (!"java.lang.Object".equals(calledTypeBinding.getSuperclass().getQualifiedName())) { calledType= (IType) calledTypeBinding.getSuperclass().getJavaElement(); 211 } else { 212 calledType = (IType) calledTypeBinding.getInterfaces()[0].getJavaElement(); 213 } 214 } 215 216 IMethod calledMethod = findIncludingSupertypes(calledMethodBinding, 217 calledType, fProgressMonitor); 218 219 IMember referencedMember= null; 220 if (calledMethod == null) { 221 if (calledMethodBinding.isConstructor() && calledMethodBinding.getParameterTypes().length == 0) { 222 referencedMember= calledType; 223 } 224 } else { 225 if (calledType.isInterface()) { 226 calledMethod = findImplementingMethods(calledMethod); 227 } 228 229 if (!isIgnoredBySearchScope(calledMethod)) { 230 referencedMember= calledMethod; 231 } 232 } 233 final int position= node.getStartPosition(); 234 final int number= fCompilationUnit.getLineNumber(position); 235 fSearchResults.addMember(fMethod, referencedMember, position, position + node.getLength(), number < 1 ? 1 : number); 236 } 237 } catch (JavaModelException jme) { 238 JavaPlugin.log(jme); 239 } 240 } 241 242 private static IMethod findIncludingSupertypes(IMethodBinding method, IType type, IProgressMonitor pm) throws JavaModelException { 243 IMethod inThisType= Bindings.findMethod(method, type); 244 if (inThisType != null) 245 return inThisType; 246 IType[] superTypes= JavaModelUtil.getAllSuperTypes(type, pm); 247 for (int i= 0; i < superTypes.length; i++) { 248 IMethod m= Bindings.findMethod(method, superTypes[i]); 249 if (m != null) 250 return m; 251 } 252 return null; 253 } 254 255 private boolean isIgnoredBySearchScope(IMethod enclosingElement) { 256 if (enclosingElement != null) { 257 return !getSearchScope().encloses(enclosingElement); 258 } else { 259 return false; 260 } 261 } 262 263 private IJavaSearchScope getSearchScope() { 264 return CallHierarchy.getDefault().getSearchScope(); 265 } 266 267 private boolean isNodeWithinMethod(ASTNode node) { 268 int nodeStartPosition = node.getStartPosition(); 269 int nodeEndPosition = nodeStartPosition + node.getLength(); 270 271 if (nodeStartPosition < fMethodStartPosition) { 272 return false; 273 } 274 275 if (nodeEndPosition > fMethodEndPosition) { 276 return false; 277 } 278 279 return true; 280 } 281 282 private boolean isNodeEnclosingMethod(ASTNode node) { 283 int nodeStartPosition = node.getStartPosition(); 284 int nodeEndPosition = nodeStartPosition + node.getLength(); 285 286 if (nodeStartPosition < fMethodStartPosition && nodeEndPosition > fMethodEndPosition) { 287 return true; 289 } 290 return false; 291 } 292 293 private boolean isFurtherTraversalNecessary(ASTNode node) { 294 return isNodeWithinMethod(node) || isNodeEnclosingMethod(node); 295 } 296 297 private IMethod findImplementingMethods(IMethod calledMethod) { 298 Collection implementingMethods = CallHierarchy.getDefault() 299 .getImplementingMethods(calledMethod); 300 301 if ((implementingMethods.size() == 0) || (implementingMethods.size() > 1)) { 302 return calledMethod; 303 } else { 304 return (IMethod) implementingMethods.iterator().next(); 305 } 306 } 307 308 private void progressMonitorWorked(int work) { 309 if (fProgressMonitor != null) { 310 fProgressMonitor.worked(work); 311 if (fProgressMonitor.isCanceled()) { 312 throw new OperationCanceledException(); 313 } 314 } 315 } 316 } 317 | Popular Tags |