javac ast indices: inheritor/lambda search: cache only candidate's ids (in read action) and restore psi-elements only when a search client asks

This commit is contained in:
Dmitry Batkovich
2016-10-31 15:13:00 +03:00
parent 8dbf43a904
commit 5bfddbb3f6
10 changed files with 132 additions and 124 deletions
@@ -16,38 +16,75 @@
package com.intellij.compiler.backwardRefs;
import com.intellij.compiler.CompilerDirectHierarchyInfo;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.stream.Stream;
class CompilerHierarchyInfoImpl implements CompilerDirectHierarchyInfo {
private final static Logger LOG = Logger.getInstance(CompilerHierarchyInfoImpl.class);
private final PsiNamedElement myBaseClass;
private final GlobalSearchScope myDirtyScope;
private final GlobalSearchScope mySearchScope;
private final Couple<Map<VirtualFile, PsiElement[]>> myCandidatePerFile;
private final Project myProject;
private final FileType mySearchFileType;
private final CompilerHierarchySearchType mySearchType;
private final Map<VirtualFile, Object[]> myCandidatePerFile;
CompilerHierarchyInfoImpl(Couple<Map<VirtualFile, PsiElement[]>> candidatePerFile,
CompilerHierarchyInfoImpl(Map<VirtualFile, Object[]> candidatesPerFile,
PsiNamedElement baseClass,
GlobalSearchScope dirtyScope,
GlobalSearchScope searchScope) {
myCandidatePerFile = candidatePerFile;
GlobalSearchScope searchScope,
Project project,
FileType searchFileType,
CompilerHierarchySearchType searchType) {
myCandidatePerFile = candidatesPerFile;
myBaseClass = baseClass;
myDirtyScope = dirtyScope;
mySearchScope = searchScope;
myProject = project;
mySearchFileType = searchFileType;
mySearchType = searchType;
}
@Override
@NotNull
public Stream<PsiElement> getHierarchyChildren() {
return selectClassesInScope(myCandidatePerFile.getFirst(), mySearchScope);
}
PsiManager psiManager = PsiManager.getInstance(myProject);
final LanguageLightRefAdapter adapter = ObjectUtils.notNull(CompilerReferenceServiceImpl.findAdapterForFileType(mySearchFileType));
return myCandidatePerFile
.entrySet()
.stream()
.filter(e -> mySearchScope.contains(e.getKey()))
.flatMap(e -> {
final VirtualFile file = e.getKey();
final Object[] definitions = e.getValue();
@Override
@NotNull
public Stream<PsiElement> getHierarchyChildCandidates() {
return selectClassesInScope(myCandidatePerFile.getSecond(), mySearchScope);
final PsiElement[] hierarchyChildren = ReadAction.compute(() -> {
final PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport)psiManager.findFile(file);
return mySearchType.performSearchInFile(definitions, myBaseClass, psiFile, adapter);
});
if (hierarchyChildren.length == definitions.length) {
return Stream.of(hierarchyChildren);
}
else {
LOG.assertTrue(mySearchType == CompilerHierarchySearchType.DIRECT_INHERITOR, "Should not happens for functional expression search");
return Stream.of(hierarchyChildren).filter(c -> ReadAction.compute(() -> adapter.isDirectInheritor(c, myBaseClass)));
}
});
}
@Override
@@ -55,8 +92,4 @@ class CompilerHierarchyInfoImpl implements CompilerDirectHierarchyInfo {
public GlobalSearchScope getDirtyScope() {
return myDirtyScope;
}
private static <T extends PsiElement> Stream<T> selectClassesInScope(Map<VirtualFile, T[]> classesPerFile, GlobalSearchScope searchScope) {
return classesPerFile.entrySet().stream().filter(e -> searchScope.contains(e.getKey())).flatMap(e -> Stream.of(e.getValue()));
}
}
@@ -26,40 +26,49 @@ import java.util.Collection;
enum CompilerHierarchySearchType {
DIRECT_INHERITOR {
@Override
PsiElement[] performSearchInFile(Collection<? extends LightRef> definitions,
PsiElement[] performSearchInFile(Object[] definitions,
PsiNamedElement baseElement,
ByteArrayEnumerator nameEnumerator,
PsiFileWithStubSupport file,
LanguageLightRefAdapter adapter) {
return adapter.findDirectInheritorCandidatesInFile((Collection<LightRef.LightClassHierarchyElementDef>)definitions, nameEnumerator, file, baseElement);
return adapter.findDirectInheritorCandidatesInFile((String[])definitions, file, baseElement);
}
@Override
Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter adapter) {
return adapter.getHierarchyObjectClass();
}
@Override
Object[] convertIdToSearchableArray(Collection<LightRef> lightRef, ByteArrayEnumerator byteArrayEnumerator) {
return lightRef.stream().map(r -> byteArrayEnumerator.getName(((LightRef.LightClassHierarchyElementDef)r).getName())).toArray(String[]::new);
}
},
FUNCTIONAL_EXPRESSION {
@Override
PsiElement[] performSearchInFile(Collection<? extends LightRef> definitions,
PsiElement[] performSearchInFile(Object[] definitions,
PsiNamedElement baseElement,
ByteArrayEnumerator nameEnumerator,
PsiFileWithStubSupport file,
LanguageLightRefAdapter adapter) {
return adapter.findFunExpressionsInFile((Collection<LightRef.LightFunExprDef>)definitions, file);
return adapter.findFunExpressionsInFile((Integer[])definitions, file);
}
@Override
Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter adapter) {
return adapter.getFunExprClass();
}
@Override
Object[] convertIdToSearchableArray(Collection<LightRef> lightRef, ByteArrayEnumerator byteArrayEnumerator) {
return lightRef.stream().map(r -> ((LightRef.LightFunExprDef) r).getId()).toArray(Integer[]::new);
}
};
abstract PsiElement[] performSearchInFile(Collection<? extends LightRef> definitions,
abstract PsiElement[] performSearchInFile(Object[] definitions,
PsiNamedElement baseElement,
ByteArrayEnumerator nameEnumerator,
PsiFileWithStubSupport file,
LanguageLightRefAdapter adapter);
abstract Class<? extends LightRef> getRequiredClass(LanguageLightRefAdapter adapter);
abstract Object[] convertIdToSearchableArray(Collection<LightRef> lightRef, ByteArrayEnumerator byteArrayEnumerator);
}
@@ -16,21 +16,14 @@
package com.intellij.compiler.backwardRefs;
import com.intellij.compiler.server.BuildManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.Queue;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
@@ -78,25 +71,23 @@ class CompilerReferenceReader {
* 1st map: inheritors. Can be used without explicit inheritance verification
* 2nd map: candidates. One need to check that these classes are really direct inheritors
*/
@Nullable
Couple<Map<VirtualFile, PsiElement[]>> getDirectInheritors(@NotNull PsiNamedElement baseClass,
@NotNull LightRef searchElement,
@NotNull GlobalSearchScope searchScope,
@NotNull GlobalSearchScope dirtyScope,
@NotNull Project project,
@NotNull FileType fileType,
@NotNull CompilerHierarchySearchType searchType) {
@NotNull
Map<VirtualFile, Object[]> getDirectInheritors(@NotNull LightRef searchElement,
@NotNull GlobalSearchScope searchScope,
@NotNull GlobalSearchScope dirtyScope,
@NotNull FileType fileType,
@NotNull CompilerHierarchySearchType searchType) {
Collection<CompilerBackwardReferenceIndex.LightDefinition> candidates;
synchronized (myHierarchyLock) {
candidates = myIndex.getBackwardHierarchyMap().get(searchElement);
}
if (candidates == null) return Couple.of(Collections.emptyMap(), Collections.emptyMap());
if (candidates == null) return Collections.emptyMap();
GlobalSearchScope effectiveSearchScope = GlobalSearchScope.notScope(dirtyScope).intersectWith(searchScope);
LanguageLightRefAdapter adapter = CompilerReferenceServiceImpl.findAdapterForFileType(fileType);
LOG.assertTrue(adapter != null, "adapter is null for file type: " + fileType);
Class<? extends LightRef> requiredLightRefClass = searchType.getRequiredClass(adapter);
Map<VirtualFile, List<LightRef>> candidatesPerFile;
Map<VirtualFile, Object[]> candidatesPerFile;
synchronized (myReferenceLock) {
candidatesPerFile = candidates
.stream()
@@ -114,28 +105,10 @@ class CompilerReferenceReader {
}
})
.filter(Objects::nonNull)
.collect(groupingBy(x -> x.containingFile, mapping(x -> x.def, toList())));
.collect(groupingBy(x -> x.containingFile, mapping(x -> x.def, collectingAndThen(toList(), l -> searchType.convertIdToSearchableArray(l, myIndex.getByteSeqEum())))));
}
if (candidatesPerFile.isEmpty()) return Couple.of(Collections.emptyMap(), Collections.emptyMap());
Map<VirtualFile, PsiElement[]> inheritors = new THashMap<>(candidatesPerFile.size());
Map<VirtualFile, PsiElement[]> inheritorCandidates = new THashMap<>();
final PsiManager psiManager = ReadAction.compute(() -> PsiManager.getInstance(project));
candidatesPerFile.forEach((file, directInheritors) -> ReadAction.run(() -> {
final PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport) psiManager.findFile(file);
final PsiElement[] currInheritors = searchType.performSearchInFile(directInheritors, baseClass, myIndex.getByteSeqEum(), psiFile, adapter);
if (currInheritors.length == directInheritors.size()) {
inheritors.put(file, currInheritors);
}
else {
inheritorCandidates.put(file, currInheritors);
}
}));
return Couple.of(inheritors, inheritorCandidates);
return candidatesPerFile.isEmpty() ? Collections.emptyMap() : candidatesPerFile;
}
@NotNull
@@ -30,7 +30,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.impl.LibraryScopeCache;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
@@ -185,32 +184,31 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
}
@Nullable
private CompilerDirectHierarchyInfo getHierarchyInfo(@NotNull PsiNamedElement aClass,
@NotNull GlobalSearchScope useScope,
@NotNull GlobalSearchScope searchScope,
@NotNull FileType searchFileType,
@NotNull CompilerHierarchySearchType searchType) {
private CompilerHierarchyInfoImpl getHierarchyInfo(@NotNull PsiNamedElement aClass,
@NotNull GlobalSearchScope useScope,
@NotNull GlobalSearchScope searchScope,
@NotNull FileType searchFileType,
@NotNull CompilerHierarchySearchType searchType) {
if (!isServiceEnabledFor(aClass) || searchScope == LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope()) return null;
Couple<Map<VirtualFile, PsiElement[]>> directInheritorsAndCandidates =
CachedValuesManager.getCachedValue(aClass, () -> CachedValueProvider.Result.create(
new ConcurrentFactoryMap<HierarchySearchKey, Couple<Map<VirtualFile, PsiElement[]>>>() {
Map<VirtualFile, Object[]> candidatesPerFile = ReadAction.compute(() -> CachedValuesManager.getCachedValue(aClass, () -> CachedValueProvider.Result.create(
new ConcurrentFactoryMap<HierarchySearchKey, Map<VirtualFile, Object[]>>() {
@Nullable
@Override
protected Couple<Map<VirtualFile, PsiElement[]>> create(HierarchySearchKey key) {
protected Map<VirtualFile, Object[]> create(HierarchySearchKey key) {
return calculateDirectInheritors(aClass,
useScope,
key.mySearchFileType,
key.mySearchType);
}
}, PsiModificationTracker.MODIFICATION_COUNT, this)).get(new HierarchySearchKey(searchType, searchFileType));
}, PsiModificationTracker.MODIFICATION_COUNT, this)).get(new HierarchySearchKey(searchType, searchFileType)));
if (directInheritorsAndCandidates == null) return null;
if (candidatesPerFile == null) return null;
GlobalSearchScope dirtyScope = myDirtyModulesHolder.getDirtyScope();
if (ElementPlace.LIB == ReadAction.compute(() -> ElementPlace.get(aClass.getContainingFile().getVirtualFile(), myProjectFileIndex))) {
dirtyScope = dirtyScope.union(LibraryScopeCache.getInstance(myProject).getLibrariesOnlyScope());
}
return new CompilerHierarchyInfoImpl(directInheritorsAndCandidates, dirtyScope, searchScope);
return new CompilerHierarchyInfoImpl(candidatesPerFile, aClass, dirtyScope, searchScope, myProject, searchFileType, searchType);
}
private boolean isServiceEnabledFor(PsiElement element) {
@@ -223,11 +221,10 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
return myReader != null && isEnabled();
}
private Couple<Map<VirtualFile, PsiElement[]>> calculateDirectInheritors(@NotNull PsiNamedElement aClass,
@NotNull GlobalSearchScope useScope,
@NotNull FileType searchFileType,
@NotNull CompilerHierarchySearchType searchType) {
private Map<VirtualFile, Object[]> calculateDirectInheritors(@NotNull PsiNamedElement aClass,
@NotNull GlobalSearchScope useScope,
@NotNull FileType searchFileType,
@NotNull CompilerHierarchySearchType searchType) {
final CompilerElementInfo searchElementInfo = asCompilerElements(aClass, false);
if (searchElementInfo == null) return null;
LightRef searchElement = searchElementInfo.searchElements[0];
@@ -235,7 +232,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
myReadDataLock.lock();
try {
if (myReader == null) return null;
return myReader.getDirectInheritors(aClass, searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), myProject, searchFileType, searchType);
return myReader.getDirectInheritors(searchElement, useScope, myDirtyModulesHolder.getDirtyScope(), searchFileType, searchType);
} finally {
myReadDataLock.unlock();
}
@@ -276,14 +273,15 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
myReadDataLock.lock();
try {
if (myReader == null) return null;
VirtualFile file = ReadAction.compute(() -> PsiUtilCore.getVirtualFile(psiElement));
VirtualFile file = PsiUtilCore.getVirtualFile(psiElement);
if (file == null) return null;
ElementPlace place = ElementPlace.get(file, myProjectFileIndex);
if (place == null || (place == ElementPlace.SRC && myDirtyModulesHolder.contains(file))) {
return null;
}
final LanguageLightRefAdapter adapter = findAdapterForFileType(file.getFileType());
if (adapter == null) return null;
final LightRef ref = ReadAction.compute(() -> adapter.asLightUsage(psiElement, myReader.getNameEnumerator()));
final LightRef ref = adapter.asLightUsage(psiElement, myReader.getNameEnumerator());
if (ref == null) return null;
if (place == ElementPlace.LIB && buildHierarchyForLibraryElements) {
final List<LightRef> elements = adapter.getHierarchyRestrictedToLibraryScope(ref,
@@ -304,8 +302,6 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
} finally {
myReadDataLock.unlock();
}
}
private void closeReaderIfNeed() {
@@ -454,4 +450,8 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple
return 31 * mySearchType.hashCode() + mySearchFileType.hashCode();
}
}
private static class RawSearchResult {
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.PsiDocumentManager;
@@ -70,23 +71,27 @@ class DirtyModulesHolder extends UserDataHolderBase {
}
GlobalSearchScope getDirtyScope() {
return CachedValuesManager.getManager(myService.getProject()).getCachedValue(this, () ->
CachedValueProvider.Result.create(calculateDirtyModules(), PsiModificationTracker.MODIFICATION_COUNT, VirtualFileManager.getInstance(), myService));
final Project project = myService.getProject();
synchronized (myLock) {
if (myCompilationPhase) {
return GlobalSearchScope.allScope(project);
}
return ReadAction.compute(() -> CachedValuesManager.getManager(project).getCachedValue(this, () ->
CachedValueProvider.Result.create(calculateDirtyModules(), PsiModificationTracker.MODIFICATION_COUNT, VirtualFileManager.getInstance(), myService)));
}
}
private GlobalSearchScope calculateDirtyModules() {
synchronized (myLock) {
final Set<Module> dirtyModules = new THashSet<>(myVFSChangedModules);
for (Document document : myFileDocManager.getUnsavedDocuments()) {
final Module m = getModuleForSourceContentFile(myFileDocManager.getFile(document));
if (m != null) dirtyModules.add(m);
}
for (Document document : ReadAction.compute(() -> myPsiDocManager.getUncommittedDocuments())) {
final Module m = getModuleForSourceContentFile(ObjectUtils.notNull(myPsiDocManager.getPsiFile(document)).getVirtualFile());
if (m != null) dirtyModules.add(m);
}
return dirtyModules.stream().map(Module::getModuleWithDependentsScope).reduce(GlobalSearchScope.EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
final Set<Module> dirtyModules = new THashSet<>(myVFSChangedModules);
for (Document document : myFileDocManager.getUnsavedDocuments()) {
final Module m = getModuleForSourceContentFile(myFileDocManager.getFile(document));
if (m != null) dirtyModules.add(m);
}
for (Document document : myPsiDocManager.getUncommittedDocuments()) {
final Module m = getModuleForSourceContentFile(ObjectUtils.notNull(myPsiDocManager.getPsiFile(document)).getVirtualFile());
if (m != null) dirtyModules.add(m);
}
return dirtyModules.stream().map(Module::getModuleWithDependentsScope).reduce(GlobalSearchScope.EMPTY_SCOPE, (s1, s2) -> s1.union(s2));
}
boolean contains(VirtualFile file) {
@@ -35,7 +35,6 @@ import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
import org.jetbrains.jps.backwardRefs.LightRef;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -113,25 +112,28 @@ public class JavaLightUsageAdapter implements LanguageLightRefAdapter {
@NotNull
@Override
public PsiClass[] findDirectInheritorCandidatesInFile(@NotNull Collection<LightRef.LightClassHierarchyElementDef> classes,
@NotNull ByteArrayEnumerator byteArrayEnumerator,
public PsiClass[] findDirectInheritorCandidatesInFile(@NotNull String[] internalNames,
@NotNull PsiFileWithStubSupport file,
@NotNull PsiNamedElement superClass) {
String[] internalNames = classes.stream().map(LightRef.NamedLightRef::getName).map(byteArrayEnumerator::getName).toArray(String[]::new);
return JavaCompilerElementRetriever.retrieveClassesByInternalNames(internalNames, superClass, file);
}
@NotNull
@Override
public PsiFunctionalExpression[] findFunExpressionsInFile(@NotNull Collection<LightRef.LightFunExprDef> funExpressions,
public PsiFunctionalExpression[] findFunExpressionsInFile(@NotNull Integer[] funExpressions,
@NotNull PsiFileWithStubSupport file) {
TIntHashSet requiredIndices = new TIntHashSet(funExpressions.size());
for (LightRef.LightFunExprDef funExpr : funExpressions) {
requiredIndices.add(funExpr.getId());
TIntHashSet requiredIndices = new TIntHashSet(funExpressions.length);
for (int funExpr : funExpressions) {
requiredIndices.add(funExpr);
}
return JavaCompilerElementRetriever.retrieveFunExpressionsByIndices(requiredIndices, file);
}
@Override
public boolean isDirectInheritor(PsiElement candidate, PsiNamedElement baseClass) {
return ((PsiClass) candidate).isInheritor((PsiClass) baseClass, false);
}
private static boolean mayBeVisibleOutsideOwnerFile(@NotNull PsiElement element) {
if (!(element instanceof PsiModifierListOwner)) return true;
if (((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.PRIVATE)) return false;
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator;
import org.jetbrains.jps.backwardRefs.LightRef;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -77,8 +76,7 @@ public interface LanguageLightRefAdapter {
* found elements really inheritors.
*/
@NotNull
PsiElement[] findDirectInheritorCandidatesInFile(@NotNull Collection<LightRef.LightClassHierarchyElementDef> internalNames,
@NotNull ByteArrayEnumerator byteArrayEnumerator,
PsiElement[] findDirectInheritorCandidatesInFile(@NotNull String[] internalNames,
@NotNull PsiFileWithStubSupport file,
@NotNull PsiNamedElement superClass);
@@ -87,6 +85,8 @@ public interface LanguageLightRefAdapter {
* @return functional expressions for given functional type. Should return
*/
@NotNull
PsiElement[] findFunExpressionsInFile(@NotNull Collection<LightRef.LightFunExprDef> indices,
PsiElement[] findFunExpressionsInFile(@NotNull Integer[] indices,
@NotNull PsiFileWithStubSupport file);
boolean isDirectInheritor(PsiElement candidate, PsiNamedElement baseClass);
}
@@ -31,12 +31,6 @@ public interface CompilerDirectHierarchyInfo {
@NotNull
Stream<PsiElement> getHierarchyChildren();
/**
* Must be explicitly checked do they are really direct children in hierarchy of classes or functional expressions
*/
@NotNull
Stream<PsiElement> getHierarchyChildCandidates();
/**
* A scope where compiler based index search was not performed
*/
@@ -81,8 +81,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
CompilerDirectHierarchyInfo info = performSearchUsingCompilerIndices(parameters, scope, project);
if (info != null) {
if (!processInheritorCandidates(info.getHierarchyChildren(), consumer, parameters.includeAnonymous(), false, baseClass)) return false;
if (!processInheritorCandidates(info.getHierarchyChildCandidates(), consumer, parameters.includeAnonymous(), true, baseClass)) return false;
if (!processInheritorCandidates(info.getHierarchyChildren(), consumer, parameters.includeAnonymous())) return false;
scope = scope.intersectWith(info.getDirtyScope());
useScope = useScope.intersectWith(info.getDirtyScope());
}
@@ -294,16 +293,13 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
private static boolean processInheritorCandidates(@NotNull Stream<PsiElement> classStream,
@NotNull Processor<PsiClass> consumer,
boolean acceptAnonymous,
boolean checkInheritance,
PsiClass baseClass) {
boolean acceptAnonymous) {
if (!acceptAnonymous) {
classStream = classStream.filter(c -> !(c instanceof PsiAnonymousClass));
}
return ContainerUtil.process(classStream.iterator(), e -> {
ProgressManager.checkCanceled();
PsiClass c = (PsiClass) e;
if (checkInheritance && ReadAction.compute(() -> !c.isInheritor(baseClass, false))) return true;
return consumer.process(c);
});
}
@@ -16,7 +16,6 @@
package com.intellij.compiler;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.completion.AbstractCompilerAwareTest;
import com.intellij.compiler.backwardRefs.CompilerReferenceServiceImpl;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.vfs.VirtualFile;
@@ -104,9 +103,6 @@ public class CompilerReferencesTest extends CompilerReferencesTestBase {
assertOneOf(inheritor.getName(), "FooImpl", "FooImpl2", "FooInsideMethodImpl");
}
}
Collection<PsiClass> candidates = directInheritorInfo.getHierarchyChildCandidates().map(PsiClass.class::cast).collect(Collectors.toList());
assertEmpty(candidates);
}
public void testHierarchyOfLibClass() {