public void build(boolean computeSubtypes) { JavaModelManager manager = JavaModelManager.getJavaModelManager(); try { // optimize access to zip files while building hierarchy manager.cacheZipFiles(this); if (computeSubtypes) { // Note by construction there always is a focus type here IType focusType = getType(); boolean focusIsObject = focusType.getElementName().equals(new String(IIndexConstants.OBJECT)); int amountOfWorkForSubtypes = focusIsObject ? 5 : 80; // percentage of work needed to get possible subtypes IProgressMonitor possibleSubtypesMonitor = this.hierarchy.progressMonitor == null ? null : new SubProgressMonitor(this.hierarchy.progressMonitor, amountOfWorkForSubtypes); HashSet localTypes = new HashSet( 10); // contains the paths that have potential subtypes that are local/anonymous // types String[] allPossibleSubtypes; if (((Member) focusType).getOuterMostLocalContext() == null) { // top level or member type allPossibleSubtypes = determinePossibleSubTypes(localTypes, possibleSubtypesMonitor); } else { // local or anonymous type allPossibleSubtypes = CharOperation.NO_STRINGS; } if (allPossibleSubtypes != null) { IProgressMonitor buildMonitor = this.hierarchy.progressMonitor == null ? null : new SubProgressMonitor( this.hierarchy.progressMonitor, 100 - amountOfWorkForSubtypes); this.hierarchy.initialize(allPossibleSubtypes.length); buildFromPotentialSubtypes(allPossibleSubtypes, localTypes, buildMonitor); } } else { this.hierarchy.initialize(1); buildSupertypes(); } } finally { manager.flushZipFiles(this); } }
protected String[] getPathsOfDeclaringType() { if (this.typeQualification == null && this.typeSimpleName == null) return null; final PathCollector pathCollector = new PathCollector(); IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); IndexManager indexManager = JavaModelManager.getIndexManager(); SearchPattern searchPattern = new TypeDeclarationPattern( this.typeSimpleName != null ? null : this.typeQualification, // use the qualification only if no simple name null, // do find member types this.typeSimpleName, IIndexConstants.TYPE_SUFFIX, this.pattern.getMatchRule()); IndexQueryRequestor searchRequestor = new IndexQueryRequestor() { public boolean acceptIndexMatch( String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { TypeDeclarationPattern record = (TypeDeclarationPattern) indexRecord; if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) { // filter out local and anonymous classes pathCollector.acceptIndexMatch(documentPath, indexRecord, participant, access); } return true; } }; indexManager.performConcurrentJob( new PatternSearchJob(searchPattern, new JavaSearchParticipant(), scope, searchRequestor), IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100)); return pathCollector.getPaths(); }
/** * Find the set of candidate subtypes of a given type. * * <p>The requestor is notified of super type references (with actual path of its occurrence) for * all types which are potentially involved inside a particular hierarchy. The match locator is * not used here to narrow down the results, the type hierarchy resolver is rather used to compute * the whole hierarchy at once. * * @param type * @param scope * @param binariesFromIndexMatches * @param pathRequestor * @param waitingPolicy * @param progressMonitor */ public static void searchAllPossibleSubTypes( IType type, IJavaSearchScope scope, final Map binariesFromIndexMatches, final IPathRequestor pathRequestor, int waitingPolicy, // WaitUntilReadyToSearch | ForceImmediateSearch | CancelIfNotReadyToSearch final IProgressMonitor progressMonitor) { /* embed constructs inside arrays so as to pass them to (inner) collector */ final Queue queue = new Queue(); final HashtableOfObject foundSuperNames = new HashtableOfObject(5); IndexManager indexManager = JavaModelManager.getIndexManager(); /* use a special collector to collect paths and queue new subtype names */ IndexQueryRequestor searchRequestor = new IndexQueryRequestor() { public boolean acceptIndexMatch( String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { SuperTypeReferencePattern record = (SuperTypeReferencePattern) indexRecord; boolean isLocalOrAnonymous = record.enclosingTypeName == IIndexConstants.ONE_ZERO; pathRequestor.acceptPath(documentPath, isLocalOrAnonymous); char[] typeName = record.simpleName; if (documentPath.toLowerCase().endsWith(SUFFIX_STRING_class)) { int suffix = documentPath.length() - SUFFIX_STRING_class.length(); HierarchyBinaryType binaryType = (HierarchyBinaryType) binariesFromIndexMatches.get(documentPath); if (binaryType == null) { char[] enclosingTypeName = record.enclosingTypeName; if (isLocalOrAnonymous) { int lastSlash = documentPath.lastIndexOf('/'); int lastDollar = documentPath.lastIndexOf('$'); if (lastDollar == -1) { // malformed local or anonymous type: it doesn't contain a $ in its name // treat it as a top level type enclosingTypeName = null; typeName = documentPath.substring(lastSlash + 1, suffix).toCharArray(); } else { enclosingTypeName = documentPath.substring(lastSlash + 1, lastDollar).toCharArray(); typeName = documentPath.substring(lastDollar + 1, suffix).toCharArray(); } } binaryType = new HierarchyBinaryType( record.modifiers, record.pkgName, typeName, enclosingTypeName, record.typeParameterSignatures, record.classOrInterface); binariesFromIndexMatches.put(documentPath, binaryType); } binaryType.recordSuperType( record.superSimpleName, record.superQualification, record.superClassOrInterface); } if (!isLocalOrAnonymous // local or anonymous types cannot have subtypes outside the cu // that define them && !foundSuperNames.containsKey(typeName)) { foundSuperNames.put(typeName, typeName); queue.add(typeName); } return true; } }; int superRefKind; try { superRefKind = type.isClass() ? SuperTypeReferencePattern.ONLY_SUPER_CLASSES : SuperTypeReferencePattern.ALL_SUPER_TYPES; } catch (JavaModelException e) { superRefKind = SuperTypeReferencePattern.ALL_SUPER_TYPES; } SuperTypeReferencePattern pattern = new SuperTypeReferencePattern( null, null, superRefKind, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); MatchLocator.setFocus(pattern, type); SubTypeSearchJob job = new SubTypeSearchJob( pattern, new JavaSearchParticipant(), // java search only scope, searchRequestor); int ticks = 0; queue.add(type.getElementName().toCharArray()); try { while (queue.start <= queue.end) { if (progressMonitor != null && progressMonitor.isCanceled()) return; // all subclasses of OBJECT are actually all types char[] currentTypeName = queue.retrieve(); if (CharOperation.equals(currentTypeName, IIndexConstants.OBJECT)) currentTypeName = null; // search all index references to a given supertype pattern.superSimpleName = currentTypeName; indexManager.performConcurrentJob( job, waitingPolicy, progressMonitor == null ? null : new NullProgressMonitor() { // don't report progress since this is too costly for deep hierarchies (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=34078 ) // just handle isCanceled() (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=179511 ) public void setCanceled(boolean value) { progressMonitor.setCanceled(value); } public boolean isCanceled() { return progressMonitor.isCanceled(); } // and handle subTask(...) (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=34078 ) public void subTask(String name) { progressMonitor.subTask(name); } }); if (progressMonitor != null && ++ticks <= MAXTICKS) progressMonitor.worked(1); // in case, we search all subtypes, no need to search further if (currentTypeName == null) break; } } finally { job.finished(); } }