/* 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.getJavaModelManager().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;
int suffix = documentPath.toLowerCase().lastIndexOf(SUFFIX_STRING_class);
if (suffix != -1){
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
// just handle isCanceled() (seehttps://bugs.eclipse.org/bugs/show_bug.cgi?id=179511)
public void setCanceled(boolean value) {
progressMonitor.setCanceled(value);
}