1 11 package org.eclipse.jdt.internal.corext.refactoring.rename; 12 13 import java.util.ArrayList ; 14 import java.util.Collection ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.runtime.Assert; 23 import org.eclipse.core.runtime.CoreException; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.OperationCanceledException; 26 import org.eclipse.core.runtime.SubProgressMonitor; 27 28 29 import org.eclipse.jdt.core.IMember; 30 import org.eclipse.jdt.core.IMethod; 31 import org.eclipse.jdt.core.IRegion; 32 import org.eclipse.jdt.core.IType; 33 import org.eclipse.jdt.core.ITypeHierarchy; 34 import org.eclipse.jdt.core.JavaCore; 35 import org.eclipse.jdt.core.JavaModelException; 36 import org.eclipse.jdt.core.WorkingCopyOwner; 37 import org.eclipse.jdt.core.search.IJavaSearchConstants; 38 import org.eclipse.jdt.core.search.IJavaSearchScope; 39 import org.eclipse.jdt.core.search.SearchMatch; 40 import org.eclipse.jdt.core.search.SearchPattern; 41 42 import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; 43 import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2; 44 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 45 46 public class RippleMethodFinder2 { 47 48 private final IMethod fMethod; 49 private List fDeclarations; 50 private ITypeHierarchy fHierarchy; 51 private Map fTypeToMethod; 52 private Set fRootTypes; 53 private MultiMap fRootReps; 54 private Map fRootHierarchies; 55 private UnionFind fUnionFind; 56 private boolean fExcludeBinaries; 57 58 private static class MultiMap { 59 HashMap fImplementation= new HashMap (); 60 61 public void put(IType key, IType value) { 62 Collection collection= (Collection ) fImplementation.get(key); 63 if (collection == null) { 64 collection= new HashSet (); 65 fImplementation.put(key, collection); 66 } 67 collection.add(value); 68 } 69 70 public Collection get(IType key) { 71 return (Collection ) fImplementation.get(key); 72 } 73 } 74 private static class UnionFind { 75 HashMap fElementToRepresentative= new HashMap (); 76 77 public void init(IType type) { 78 fElementToRepresentative.put(type, type); 79 } 80 81 public IType find(IType element) { 83 IType root= element; 84 IType rep= (IType) fElementToRepresentative.get(root); 85 while (rep != null && ! rep.equals(root)) { 86 root= rep; 87 rep= (IType) fElementToRepresentative.get(root); 88 } 89 if (rep == null) 90 return null; 91 92 rep= (IType) fElementToRepresentative.get(element); 93 while (! rep.equals(root)) { 94 IType temp= element; 95 element= rep; 96 fElementToRepresentative.put(temp, root); 97 rep= (IType) fElementToRepresentative.get(element); 98 } 99 return root; 100 } 101 102 116 public void union(IType rep1, IType rep2) { 117 fElementToRepresentative.put(rep1, rep2); 118 } 119 } 120 121 122 private RippleMethodFinder2(IMethod method, boolean excludeBinaries){ 123 fMethod= method; 124 fExcludeBinaries= excludeBinaries; 125 } 126 127 public static IMethod[] getRelatedMethods(IMethod method, boolean excludeBinaries, IProgressMonitor pm, WorkingCopyOwner owner) throws CoreException { 128 try{ 129 if (! MethodChecks.isVirtual(method)) 130 return new IMethod[]{ method }; 131 132 return new RippleMethodFinder2(method, excludeBinaries).getAllRippleMethods(pm, owner); 133 } finally{ 134 pm.done(); 135 } 136 } 137 public static IMethod[] getRelatedMethods(IMethod method, IProgressMonitor pm, WorkingCopyOwner owner) throws CoreException { 138 return getRelatedMethods(method, true, pm, owner); 139 } 140 141 private IMethod[] getAllRippleMethods(IProgressMonitor pm, WorkingCopyOwner owner) throws CoreException { 142 pm.beginTask("", 4); 144 findAllDeclarations(new SubProgressMonitor(pm, 1), owner); 145 Assert.isTrue(fDeclarations.contains(fMethod), "Search for method declaration did not find original element"); 150 createHierarchyOfDeclarations(new SubProgressMonitor(pm, 1), owner); 151 createTypeToMethod(); 152 createUnionFind(); 153 if (pm.isCanceled()) 154 throw new OperationCanceledException(); 155 156 fHierarchy= null; 157 fRootTypes= null; 158 159 Map partitioning= new HashMap (); 160 for (Iterator iter= fTypeToMethod.keySet().iterator(); iter.hasNext();) { 161 IType type= (IType) iter.next(); 162 IType rep= fUnionFind.find(type); 163 List types= (List ) partitioning.get(rep); 164 if (types == null) 165 types= new ArrayList (); 166 types.add(type); 167 partitioning.put(rep, types); 168 } 169 Assert.isTrue(partitioning.size() > 0); 170 if (partitioning.size() == 1) 171 return (IMethod[]) fDeclarations.toArray(new IMethod[fDeclarations.size()]); 172 173 IType methodTypeRep= fUnionFind.find(fMethod.getDeclaringType()); 176 List relatedTypes= (List ) partitioning.get(methodTypeRep); 177 boolean hasRelatedInterfaces= false; 178 List relatedMethods= new ArrayList (); 179 for (Iterator iter= relatedTypes.iterator(); iter.hasNext();) { 180 IType relatedType= (IType) iter.next(); 181 relatedMethods.add(fTypeToMethod.get(relatedType)); 182 if (relatedType.isInterface()) 183 hasRelatedInterfaces= true; 184 } 185 186 189 List alienDeclarations= new ArrayList (fDeclarations); 190 fDeclarations= null; 191 alienDeclarations.removeAll(relatedMethods); 192 List alienTypes= new ArrayList (); 193 boolean hasAlienInterfaces= false; 194 for (Iterator iter= alienDeclarations.iterator(); iter.hasNext();) { 195 IMethod alienDeclaration= (IMethod) iter.next(); 196 IType alienType= alienDeclaration.getDeclaringType(); 197 alienTypes.add(alienType); 198 if (alienType.isInterface()) 199 hasAlienInterfaces= true; 200 } 201 if (alienTypes.size() == 0) return (IMethod[]) relatedMethods.toArray(new IMethod[relatedMethods.size()]); 203 if (! hasRelatedInterfaces && ! hasAlienInterfaces) return (IMethod[]) relatedMethods.toArray(new IMethod[relatedMethods.size()]); 205 206 HashSet relatedSubTypes= new HashSet (); 208 List relatedTypesToProcess= new ArrayList (relatedTypes); 209 while (relatedTypesToProcess.size() > 0) { 210 for (Iterator iter= relatedTypesToProcess.iterator(); iter.hasNext();) { 212 if (pm.isCanceled()) 213 throw new OperationCanceledException(); 214 IType relatedType= (IType) iter.next(); 215 ITypeHierarchy hierarchy= getCachedHierarchy(relatedType, owner, new SubProgressMonitor(pm, 1)); 216 if (hierarchy == null) 217 hierarchy= relatedType.newTypeHierarchy(owner, new SubProgressMonitor(pm, 1)); 218 IType[] allSubTypes= hierarchy.getAllSubtypes(relatedType); 219 for (int i= 0; i < allSubTypes.length; i++) 220 relatedSubTypes.add(allSubTypes[i]); 221 } 222 relatedTypesToProcess.clear(); 224 HashSet marriedAlienTypeReps= new HashSet (); 225 for (Iterator iter= alienTypes.iterator(); iter.hasNext();) { 226 if (pm.isCanceled()) 227 throw new OperationCanceledException(); 228 IType alienType= (IType) iter.next(); 229 IMethod alienMethod= (IMethod) fTypeToMethod.get(alienType); 230 ITypeHierarchy hierarchy= getCachedHierarchy(alienType, owner, new SubProgressMonitor(pm, 1)); 231 if (hierarchy == null) 232 hierarchy= alienType.newTypeHierarchy(owner, new SubProgressMonitor(pm, 1)); 233 IType[] allSubtypes= hierarchy.getAllSubtypes(alienType); 234 for (int i= 0; i < allSubtypes.length; i++) { 235 IType subtype= allSubtypes[i]; 236 if (relatedSubTypes.contains(subtype)) { 237 if (JavaModelUtil.isVisibleInHierarchy(alienMethod, subtype.getPackageFragment())) { 238 marriedAlienTypeReps.add(fUnionFind.find(alienType)); 239 } else { 240 } 242 } 243 } 244 } 245 246 if (marriedAlienTypeReps.size() == 0) 247 return (IMethod[]) relatedMethods.toArray(new IMethod[relatedMethods.size()]); 248 249 for (Iterator iter= marriedAlienTypeReps.iterator(); iter.hasNext();) { 250 IType marriedAlienTypeRep= (IType) iter.next(); 251 List marriedAlienTypes= (List ) partitioning.get(marriedAlienTypeRep); 252 for (Iterator iterator= marriedAlienTypes.iterator(); iterator.hasNext();) { 253 IType marriedAlienInterfaceType= (IType) iterator.next(); 254 relatedMethods.add(fTypeToMethod.get(marriedAlienInterfaceType)); 255 } 256 alienTypes.removeAll(marriedAlienTypes); relatedTypesToProcess.addAll(marriedAlienTypes); } 259 } 260 261 fRootReps= null; 262 fRootHierarchies= null; 263 fTypeToMethod= null; 264 fUnionFind= null; 265 266 return (IMethod[]) relatedMethods.toArray(new IMethod[relatedMethods.size()]); 267 } 268 269 private ITypeHierarchy getCachedHierarchy(IType type, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { 270 IType rep= fUnionFind.find(type); 271 if (rep != null) { 272 Collection collection= fRootReps.get(rep); 273 for (Iterator iter= collection.iterator(); iter.hasNext();) { 274 IType root= (IType) iter.next(); 275 ITypeHierarchy hierarchy= (ITypeHierarchy) fRootHierarchies.get(root); 276 if (hierarchy == null) { 277 hierarchy= root.newTypeHierarchy(owner, new SubProgressMonitor(monitor, 1)); 278 fRootHierarchies.put(root, hierarchy); 279 } 280 if (hierarchy.contains(type)) 281 return hierarchy; 282 } 283 } 284 return null; 285 } 286 287 private void findAllDeclarations(IProgressMonitor monitor, WorkingCopyOwner owner) throws CoreException { 288 fDeclarations= new ArrayList (); 289 final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fMethod, IJavaSearchConstants.DECLARATIONS | IJavaSearchConstants.IGNORE_DECLARING_TYPE | IJavaSearchConstants.IGNORE_RETURN_TYPE, SearchPattern.R_ERASURE_MATCH | SearchPattern.R_CASE_SENSITIVE)); 290 if (owner != null) 291 engine.setOwner(owner); 292 engine.setScope(RefactoringScopeFactory.createRelatedProjectsScope(fMethod.getJavaProject(), IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES)); 293 engine.setFiltering(false, fExcludeBinaries); 294 engine.setGrouping(false); 295 engine.searchPattern(new SubProgressMonitor(monitor, 1)); 296 final SearchMatch[] matches= (SearchMatch[]) engine.getResults(); 297 IMethod method= null; 298 for (int index= 0; index < matches.length; index++) { 299 method= (IMethod) matches[index].getElement(); 300 if (method != null) 301 fDeclarations.add(method); 302 } 303 } 304 305 private void createHierarchyOfDeclarations(IProgressMonitor pm, WorkingCopyOwner owner) throws JavaModelException { 306 IRegion region= JavaCore.newRegion(); 307 for (Iterator iter= fDeclarations.iterator(); iter.hasNext();) { 308 IType declaringType= ((IMethod) iter.next()).getDeclaringType(); 309 region.add(declaringType); 310 } 311 fHierarchy= JavaCore.newTypeHierarchy(region, owner, pm); 312 } 313 314 private void createTypeToMethod() { 315 fTypeToMethod= new HashMap (); 316 for (Iterator iter= fDeclarations.iterator(); iter.hasNext();) { 317 IMethod declaration= (IMethod) iter.next(); 318 fTypeToMethod.put(declaration.getDeclaringType(), declaration); 319 } 320 } 321 322 private void createUnionFind() throws JavaModelException { 323 fRootTypes= new HashSet (fTypeToMethod.keySet()); 324 fUnionFind= new UnionFind(); 325 for (Iterator iter= fTypeToMethod.keySet().iterator(); iter.hasNext();) { 326 IType type= (IType) iter.next(); 327 fUnionFind.init(type); 328 } 329 for (Iterator iter= fTypeToMethod.keySet().iterator(); iter.hasNext();) { 330 IType type= (IType) iter.next(); 331 uniteWithSupertypes(type, type); 332 } 333 fRootReps= new MultiMap(); 334 for (Iterator iter= fRootTypes.iterator(); iter.hasNext();) { 335 IType type= (IType) iter.next(); 336 IType rep= fUnionFind.find(type); 337 if (rep != null) 338 fRootReps.put(rep, type); 339 } 340 fRootHierarchies= new HashMap (); 341 } 342 343 private void uniteWithSupertypes(IType anchor, IType type) throws JavaModelException { 344 IType[] supertypes= fHierarchy.getSupertypes(type); 345 for (int i= 0; i < supertypes.length; i++) { 346 IType supertype= supertypes[i]; 347 IType superRep= fUnionFind.find(supertype); 348 if (superRep == null) { 349 uniteWithSupertypes(anchor, supertype); 351 } else { 352 IMember superMethod= (IMember) fTypeToMethod.get(supertype); 354 if (JavaModelUtil.isVisibleInHierarchy(superMethod, anchor.getPackageFragment())) { 355 IType rep= fUnionFind.find(anchor); 356 fUnionFind.union(rep, superRep); 357 fRootTypes.remove(anchor); 359 uniteWithSupertypes(supertype, supertype); 360 } else { 361 } 363 } 364 } 365 } 366 } 367 | Popular Tags |