1 11 package org.eclipse.jdt.internal.core.hierarchy; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.IFile; 16 import org.eclipse.core.resources.IResource; 17 import org.eclipse.core.runtime.IPath; 18 import org.eclipse.core.runtime.IProgressMonitor; 19 import org.eclipse.core.runtime.NullProgressMonitor; 20 import org.eclipse.core.runtime.SubProgressMonitor; 21 import org.eclipse.jdt.core.*; 22 import org.eclipse.jdt.core.compiler.CharOperation; 23 import org.eclipse.jdt.core.search.*; 24 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; 25 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 26 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; 27 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 28 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; 29 import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt; 30 import org.eclipse.jdt.internal.compiler.util.SuffixConstants; 31 import org.eclipse.jdt.internal.core.*; 32 import org.eclipse.jdt.internal.core.search.IndexQueryRequestor; 33 import org.eclipse.jdt.internal.core.search.JavaSearchParticipant; 34 import org.eclipse.jdt.internal.core.search.SubTypeSearchJob; 35 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants; 36 import org.eclipse.jdt.internal.core.search.indexing.IndexManager; 37 import org.eclipse.jdt.internal.core.search.matching.MatchLocator; 38 import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern; 39 import org.eclipse.jdt.internal.core.util.HandleFactory; 40 import org.eclipse.jdt.internal.core.util.Util; 41 42 public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants { 43 public static final int MAXTICKS = 800; 50 protected Map cuToHandle; 51 52 55 protected IJavaSearchScope scope; 56 57 60 protected Map binariesFromIndexMatches; 61 62 65 static class Queue { 66 public char[][] names = new char[10][]; 67 public int start = 0; 68 public int end = -1; 69 public void add(char[] name){ 70 if (++this.end == this.names.length){ 71 this.end -= this.start; 72 System.arraycopy(this.names, this.start, this.names = new char[this.end*2][], 0, this.end); 73 this.start = 0; 74 } 75 this.names[this.end] = name; 76 } 77 public char[] retrieve(){ 78 if (this.start > this.end) return null; 80 char[] name = this.names[this.start++]; 81 if (this.start > this.end){ 82 this.start = 0; 83 this.end = -1; 84 } 85 return name; 86 } 87 public String toString(){ 88 StringBuffer buffer = new StringBuffer ("Queue:\n"); for (int i = this.start; i <= this.end; i++){ 90 buffer.append(this.names[i]).append('\n'); 91 } 92 return buffer.toString(); 93 } 94 } 95 public IndexBasedHierarchyBuilder(TypeHierarchy hierarchy, IJavaSearchScope scope) throws JavaModelException { 96 super(hierarchy); 97 this.cuToHandle = new HashMap(5); 98 this.binariesFromIndexMatches = new HashMap(10); 99 this.scope = scope; 100 } 101 public void build(boolean computeSubtypes) { 102 JavaModelManager manager = JavaModelManager.getJavaModelManager(); 103 try { 104 manager.cacheZipFiles(); 106 107 if (computeSubtypes) { 108 IType focusType = getType(); 110 boolean focusIsObject = focusType.getElementName().equals(new String (IIndexConstants.OBJECT)); 111 int amountOfWorkForSubtypes = focusIsObject ? 5 : 80; IProgressMonitor possibleSubtypesMonitor = 113 this.hierarchy.progressMonitor == null ? 114 null : 115 new SubProgressMonitor(this.hierarchy.progressMonitor, amountOfWorkForSubtypes); 116 HashSet localTypes = new HashSet(10); String [] allPossibleSubtypes; 118 if (((Member)focusType).getOuterMostLocalContext() == null) { 119 allPossibleSubtypes = this.determinePossibleSubTypes(localTypes, possibleSubtypesMonitor); 121 } else { 122 allPossibleSubtypes = CharOperation.NO_STRINGS; 124 } 125 if (allPossibleSubtypes != null) { 126 IProgressMonitor buildMonitor = 127 this.hierarchy.progressMonitor == null ? 128 null : 129 new SubProgressMonitor(this.hierarchy.progressMonitor, 100 - amountOfWorkForSubtypes); 130 this.hierarchy.initialize(allPossibleSubtypes.length); 131 buildFromPotentialSubtypes(allPossibleSubtypes, localTypes, buildMonitor); 132 } 133 } else { 134 this.hierarchy.initialize(1); 135 this.buildSupertypes(); 136 } 137 } finally { 138 manager.flushZipFiles(); 139 } 140 } 141 private void buildForProject(JavaProject project, ArrayList potentialSubtypes, org.eclipse.jdt.core.ICompilationUnit[] workingCopies, HashSet localTypes, IProgressMonitor monitor) throws JavaModelException { 142 int openablesLength = potentialSubtypes.size(); 144 if (openablesLength > 0) { 145 Openable[] openables = new Openable[openablesLength]; 147 potentialSubtypes.toArray(openables); 148 149 IPackageFragmentRoot[] roots = project.getPackageFragmentRoots(); 153 int rootsLength = roots.length; 154 final HashtableOfObjectToInt indexes = new HashtableOfObjectToInt(openablesLength); 155 for (int i = 0; i < openablesLength; i++) { 156 IJavaElement root = openables[i].getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); 157 int index; 158 for (index = 0; index < rootsLength; index++) { 159 if (roots[index].equals(root)) 160 break; 161 } 162 indexes.put(openables[i], index); 163 } 164 Arrays.sort(openables, new Comparator() { 165 public int compare(Object a, Object b) { 166 int aIndex = indexes.get(a); 167 int bIndex = indexes.get(b); 168 if (aIndex != bIndex) 169 return aIndex - bIndex; 170 return ((Openable) b).getElementName().compareTo(((Openable) a).getElementName()); 171 } 172 }); 173 174 IType focusType = this.getType(); 175 boolean inProjectOfFocusType = focusType != null && focusType.getJavaProject().equals(project); 176 org.eclipse.jdt.core.ICompilationUnit[] unitsToLookInside = null; 177 if (inProjectOfFocusType) { 178 org.eclipse.jdt.core.ICompilationUnit unitToLookInside = focusType.getCompilationUnit(); 179 if (unitToLookInside != null) { 180 int wcLength = workingCopies == null ? 0 : workingCopies.length; 181 if (wcLength == 0) { 182 unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[] {unitToLookInside}; 183 } else { 184 unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[wcLength+1]; 185 unitsToLookInside[0] = unitToLookInside; 186 System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength); 187 } 188 } else { 189 unitsToLookInside = workingCopies; 190 } 191 } 192 193 SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside); 194 this.nameLookup = searchableEnvironment.nameLookup; 195 Map options = project.getOptions(true); 196 options.put(JavaCore.COMPILER_TASK_TAGS, ""); this.hierarchyResolver = 199 new HierarchyResolver(searchableEnvironment, options, this, new DefaultProblemFactory()); 200 if (focusType != null) { 201 Member declaringMember = ((Member)focusType).getOuterMostLocalContext(); 202 if (declaringMember == null) { 203 if (!inProjectOfFocusType) { 205 char[] typeQualifiedName = focusType.getTypeQualifiedName('.').toCharArray(); 206 String [] packageName = ((PackageFragment) focusType.getPackageFragment()).names; 207 if (searchableEnvironment.findType(typeQualifiedName, Util.toCharArrays(packageName)) == null) { 208 return; 210 } 211 } 212 } else { 213 Openable openable; 215 if (declaringMember.isBinary()) { 216 openable = (Openable)declaringMember.getClassFile(); 217 } else { 218 openable = (Openable)declaringMember.getCompilationUnit(); 219 } 220 localTypes = new HashSet(); 221 localTypes.add(openable.getPath().toString()); 222 this.hierarchyResolver.resolve(new Openable[] {openable}, localTypes, monitor); 223 return; 224 } 225 } 226 this.hierarchyResolver.resolve(openables, localTypes, monitor); 227 } 228 } 229 232 private void buildFromPotentialSubtypes(String [] allPotentialSubTypes, HashSet localTypes, IProgressMonitor monitor) { 233 IType focusType = this.getType(); 234 235 HashMap wcPaths = new HashMap(); int wcLength; 238 org.eclipse.jdt.core.ICompilationUnit[] workingCopies = this.hierarchy.workingCopies; 239 if (workingCopies != null && (wcLength = workingCopies.length) > 0) { 240 String [] newPaths = new String [wcLength]; 241 for (int i = 0; i < wcLength; i++) { 242 org.eclipse.jdt.core.ICompilationUnit workingCopy = workingCopies[i]; 243 String path = workingCopy.getPath().toString(); 244 wcPaths.put(path, workingCopy); 245 newPaths[i] = path; 246 } 247 int potentialSubtypesLength = allPotentialSubTypes.length; 248 System.arraycopy(allPotentialSubTypes, 0, allPotentialSubTypes = new String [potentialSubtypesLength+wcLength], 0, potentialSubtypesLength); 249 System.arraycopy(newPaths, 0, allPotentialSubTypes, potentialSubtypesLength, wcLength); 250 } 251 252 int length = allPotentialSubTypes.length; 253 254 Openable focusCU = (Openable)focusType.getCompilationUnit(); 258 String focusPath = null; 259 if (focusCU != null) { 260 focusPath = focusCU.getPath().toString(); 261 if (length > 0) { 262 System.arraycopy(allPotentialSubTypes, 0, allPotentialSubTypes = new String [length+1], 0, length); 263 allPotentialSubTypes[length] = focusPath; 264 } else { 265 allPotentialSubTypes = new String [] {focusPath}; 266 } 267 length++; 268 } 269 270 273 Arrays.sort(allPotentialSubTypes); 274 275 ArrayList potentialSubtypes = new ArrayList(); 276 try { 277 HandleFactory factory = new HandleFactory(); 279 IJavaProject currentProject = null; 280 if (monitor != null) monitor.beginTask("", length*2 ); for (int i = 0; i < length; i++) { 282 try { 283 String resourcePath = allPotentialSubTypes[i]; 284 285 if (i > 0 && resourcePath.equals(allPotentialSubTypes[i-1])) continue; 287 288 Openable handle; 289 org.eclipse.jdt.core.ICompilationUnit workingCopy = (org.eclipse.jdt.core.ICompilationUnit)wcPaths.get(resourcePath); 290 if (workingCopy != null) { 291 handle = (Openable)workingCopy; 292 } else { 293 handle = 294 resourcePath.equals(focusPath) ? 295 focusCU : 296 factory.createOpenable(resourcePath, this.scope); 297 if (handle == null) continue; } 299 300 IJavaProject project = handle.getJavaProject(); 301 if (currentProject == null) { 302 currentProject = project; 303 potentialSubtypes = new ArrayList(5); 304 } else if (!currentProject.equals(project)) { 305 this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor); 307 currentProject = project; 308 potentialSubtypes = new ArrayList(5); 309 } 310 311 potentialSubtypes.add(handle); 312 } catch (JavaModelException e) { 313 continue; 314 } 315 } 316 317 try { 319 if (currentProject == null) { 320 currentProject = focusType.getJavaProject(); 322 if (focusType.isBinary()) { 323 potentialSubtypes.add(focusType.getClassFile()); 324 } else { 325 potentialSubtypes.add(focusType.getCompilationUnit()); 326 } 327 } 328 this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor); 329 } catch (JavaModelException e) { 330 } 332 333 if (!this.hierarchy.contains(focusType)) { 335 try { 336 currentProject = focusType.getJavaProject(); 337 potentialSubtypes = new ArrayList(); 338 if (focusType.isBinary()) { 339 potentialSubtypes.add(focusType.getClassFile()); 340 } else { 341 potentialSubtypes.add(focusType.getCompilationUnit()); 342 } 343 this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor); 344 } catch (JavaModelException e) { 345 } 347 } 348 349 if (!this.hierarchy.contains(focusType)) { 351 this.hierarchy.addRootClass(focusType); 352 } 353 } finally { 354 if (monitor != null) monitor.done(); 355 } 356 } 357 protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) { 358 ICompilationUnit unit = super.createCompilationUnitFromPath(handle, file); 359 this.cuToHandle.put(unit, handle); 360 return unit; 361 } 362 protected IBinaryType createInfoFromClassFile(Openable classFile, IResource file) { 363 String documentPath = classFile.getPath().toString(); 364 IBinaryType binaryType = (IBinaryType)this.binariesFromIndexMatches.get(documentPath); 365 if (binaryType != null) { 366 this.infoToHandle.put(binaryType, classFile); 367 return binaryType; 368 } else { 369 return super.createInfoFromClassFile(classFile, file); 370 } 371 } 372 protected IBinaryType createInfoFromClassFileInJar(Openable classFile) { 373 String filePath = (((ClassFile)classFile).getType().getFullyQualifiedName('$')).replace('.', '/') + SuffixConstants.SUFFIX_STRING_class; 374 IPackageFragmentRoot root = classFile.getPackageFragmentRoot(); 375 IPath path = root.getPath(); 376 String rootPath = path.getDevice() == null ? path.toString() : path.toOSString(); 378 String documentPath = rootPath + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + filePath; 379 IBinaryType binaryType = (IBinaryType)this.binariesFromIndexMatches.get(documentPath); 380 if (binaryType != null) { 381 this.infoToHandle.put(binaryType, classFile); 382 return binaryType; 383 } else { 384 return super.createInfoFromClassFileInJar(classFile); 385 } 386 } 387 391 private String [] determinePossibleSubTypes(final HashSet localTypes, IProgressMonitor monitor) { 392 393 class PathCollector implements IPathRequestor { 394 HashSet paths = new HashSet(10); 395 public void acceptPath(String path, boolean containsLocalTypes) { 396 this.paths.add(path); 397 if (containsLocalTypes) { 398 localTypes.add(path); 399 } 400 } 401 } 402 PathCollector collector = new PathCollector(); 403 404 try { 405 if (monitor != null) monitor.beginTask("", MAXTICKS); searchAllPossibleSubTypes( 407 this.getType(), 408 this.scope, 409 this.binariesFromIndexMatches, 410 collector, 411 IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, 412 monitor); 413 } finally { 414 if (monitor != null) monitor.done(); 415 } 416 417 HashSet paths = collector.paths; 418 int length = paths.size(); 419 String [] result = new String [length]; 420 int count = 0; 421 for (Iterator iter = paths.iterator(); iter.hasNext();) { 422 result[count++] = (String ) iter.next(); 423 } 424 return result; 425 } 426 427 442 public static void searchAllPossibleSubTypes( 443 IType type, 444 IJavaSearchScope scope, 445 final Map binariesFromIndexMatches, 446 final IPathRequestor pathRequestor, 447 int waitingPolicy, final IProgressMonitor progressMonitor) { 449 450 451 final Queue queue = new Queue(); 452 final HashtableOfObject foundSuperNames = new HashtableOfObject(5); 453 454 IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); 455 456 457 IndexQueryRequestor searchRequestor = new IndexQueryRequestor() { 458 public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { 459 SuperTypeReferencePattern record = (SuperTypeReferencePattern)indexRecord; 460 boolean isLocalOrAnonymous = record.enclosingTypeName == IIndexConstants.ONE_ZERO; 461 pathRequestor.acceptPath(documentPath, isLocalOrAnonymous); 462 char[] typeName = record.simpleName; 463 int suffix = documentPath.toLowerCase().lastIndexOf(SUFFIX_STRING_class); 464 if (suffix != -1){ 465 HierarchyBinaryType binaryType = (HierarchyBinaryType)binariesFromIndexMatches.get(documentPath); 466 if (binaryType == null){ 467 char[] enclosingTypeName = record.enclosingTypeName; 468 if (isLocalOrAnonymous) { 469 int lastSlash = documentPath.lastIndexOf('/'); 470 int lastDollar = documentPath.lastIndexOf('$'); 471 if (lastDollar == -1) { 472 enclosingTypeName = null; 475 typeName = documentPath.substring(lastSlash+1, suffix).toCharArray(); 476 } else { 477 enclosingTypeName = documentPath.substring(lastSlash+1, lastDollar).toCharArray(); 478 typeName = documentPath.substring(lastDollar+1, suffix).toCharArray(); 479 } 480 } 481 binaryType = new HierarchyBinaryType(record.modifiers, record.pkgName, typeName, enclosingTypeName, record.typeParameterSignatures, record.classOrInterface); 482 binariesFromIndexMatches.put(documentPath, binaryType); 483 } 484 binaryType.recordSuperType(record.superSimpleName, record.superQualification, record.superClassOrInterface); 485 } 486 if (!isLocalOrAnonymous && !foundSuperNames.containsKey(typeName)){ 488 foundSuperNames.put(typeName, typeName); 489 queue.add(typeName); 490 } 491 return true; 492 } 493 }; 494 495 int superRefKind; 496 try { 497 superRefKind = type.isClass() ? SuperTypeReferencePattern.ONLY_SUPER_CLASSES : SuperTypeReferencePattern.ALL_SUPER_TYPES; 498 } catch (JavaModelException e) { 499 superRefKind = SuperTypeReferencePattern.ALL_SUPER_TYPES; 500 } 501 SuperTypeReferencePattern pattern = 502 new SuperTypeReferencePattern(null, null, superRefKind, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); 503 MatchLocator.setFocus(pattern, type); 504 SubTypeSearchJob job = new SubTypeSearchJob( 505 pattern, 506 new JavaSearchParticipant(), scope, 508 searchRequestor); 509 510 int ticks = 0; 511 queue.add(type.getElementName().toCharArray()); 512 try { 513 while (queue.start <= queue.end) { 514 if (progressMonitor != null && progressMonitor.isCanceled()) return; 515 516 char[] currentTypeName = queue.retrieve(); 518 if (CharOperation.equals(currentTypeName, IIndexConstants.OBJECT)) 519 currentTypeName = null; 520 521 pattern.superSimpleName = currentTypeName; 523 indexManager.performConcurrentJob(job, waitingPolicy, progressMonitor == null ? null : new NullProgressMonitor() { 524 public void setCanceled(boolean value) { 527 progressMonitor.setCanceled(value); 528 } 529 public boolean isCanceled() { 530 return progressMonitor.isCanceled(); 531 } 532 }); 533 if (progressMonitor != null && ++ticks <= MAXTICKS) 534 progressMonitor.worked(1); 535 536 if (currentTypeName == null) break; 538 } 539 } finally { 540 job.finished(); 541 } 542 } 543 } 544 | Popular Tags |