use of com.intellij.compiler.CompilerDirectHierarchyInfo in project intellij-community by JetBrains.
the class JavaDirectInheritorsSearcher method execute.
@Override
public boolean execute(@NotNull final DirectClassInheritorsSearch.SearchParameters parameters, @NotNull final Processor<PsiClass> consumer) {
final PsiClass baseClass = parameters.getClassToProcess();
assert parameters.isCheckInheritance();
final Project project = PsiUtilCore.getProjectInReadAction(baseClass);
if (JavaClassInheritorsSearcher.isJavaLangObject(baseClass)) {
SearchScope useScope = ReadAction.compute(baseClass::getUseScope);
return AllClassesSearch.search(useScope, project).forEach(psiClass -> {
ProgressManager.checkCanceled();
if (psiClass.isInterface()) {
return consumer.process(psiClass);
}
final PsiClass superClass = psiClass.getSuperClass();
return superClass == null || !JavaClassInheritorsSearcher.isJavaLangObject(superClass) || consumer.process(psiClass);
});
}
SearchScope scope;
SearchScope useScope;
CompilerDirectHierarchyInfo info = performSearchUsingCompilerIndices(parameters, parameters.getScope(), project);
if (info == null) {
scope = parameters.getScope();
useScope = ReadAction.compute(baseClass::getUseScope);
} else {
if (!processInheritorCandidates(info.getHierarchyChildren(), consumer, parameters.includeAnonymous()))
return false;
scope = ReadAction.compute(() -> parameters.getScope().intersectWith(info.getDirtyScope()));
useScope = ReadAction.compute(() -> baseClass.getUseScope().intersectWith(info.getDirtyScope()));
}
PsiClass[] cache = getOrCalculateDirectSubClasses(project, baseClass, useScope);
if (cache.length == 0) {
return true;
}
VirtualFile baseClassJarFile = null;
// iterate by same-FQN groups. For each group process only same-jar subclasses, or all of them if they are all outside the jarFile.
int groupStart = 0;
boolean sameJarClassFound = false;
String currentFQN = null;
// here we cache results of isInScope(scope, subClass) to avoid calculating it twice
boolean[] isOutOfScope = new boolean[cache.length];
for (int i = 0; i <= cache.length; i++) {
ProgressManager.checkCanceled();
PsiClass subClass = i == cache.length ? null : cache[i];
if (subClass instanceof PsiAnonymousClass) {
// we reached anonymous classes tail, process them all and exit
if (!parameters.includeAnonymous()) {
return true;
}
}
if (i != cache.length && !isInScope(scope, subClass)) {
isOutOfScope[i] = true;
continue;
}
String fqn = i == cache.length ? null : ReadAction.compute(subClass::getQualifiedName);
if (currentFQN != null && Comparing.equal(fqn, currentFQN)) {
VirtualFile currentJarFile = getJarFile(subClass);
if (baseClassJarFile == null) {
baseClassJarFile = getJarFile(baseClass);
}
boolean fromSameJar = Comparing.equal(currentJarFile, baseClassJarFile);
if (fromSameJar) {
if (!consumer.process(subClass))
return false;
sameJarClassFound = true;
}
} else {
currentFQN = fqn;
// the end of the same-FQN group. Process only same-jar classes in subClasses[groupStart..i-1] group or the whole group if there were none.
if (!sameJarClassFound) {
for (int g = groupStart; g < i; g++) {
ProgressManager.checkCanceled();
if (isOutOfScope[g])
continue;
PsiClass subClassCandidate = cache[g];
if (!consumer.process(subClassCandidate))
return false;
}
}
groupStart = i;
sameJarClassFound = false;
}
}
return true;
}
Aggregations