mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
EA-476002 IAE: JavaClassInheritorsSearcher.$$$reportNull$$$0
GitOrigin-RevId: 08b0c9a377283954c4978bad963d2d78f5331cc7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
24406fbd3d
commit
9493da7062
@@ -82,6 +82,10 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
|
||||
for (final PsiClass subClass : cached) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (subClass == null) {
|
||||
// PsiAnchor failed to retrieve?
|
||||
continue;
|
||||
}
|
||||
if (ReadAction.compute(() ->
|
||||
checkCandidate(subClass, parameters) && !consumer.process(subClass))) {
|
||||
return;
|
||||
@@ -90,17 +94,17 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Iterable<PsiClass> getOrComputeSubClasses(@NotNull Project project,
|
||||
@NotNull PsiClass baseClass,
|
||||
@NotNull SearchScope searchScopeForNonPhysical,
|
||||
boolean includeAnonymous) {
|
||||
private static Iterable<@NotNull PsiClass> getOrComputeSubClasses(@NotNull Project project,
|
||||
@NotNull PsiClass baseClass,
|
||||
@NotNull SearchScope searchScopeForNonPhysical,
|
||||
boolean includeAnonymous) {
|
||||
HighlightingCaches caches = HighlightingCaches.getInstance(project);
|
||||
ConcurrentMap<PsiClass, Iterable<PsiClass>> map = includeAnonymous ? caches.ALL_SUB_CLASSES : caches.ALL_SUB_CLASSES_NO_ANONYMOUS;
|
||||
Iterable<PsiClass> cached = map.get(baseClass);
|
||||
if (cached == null) {
|
||||
// returns lazy collection of subclasses. Each call to next() leads to calculation of next batch of subclasses.
|
||||
Function<PsiAnchor, PsiClass> converter =
|
||||
anchor -> ReadAction.compute(() -> (PsiClass)anchor.retrieve());
|
||||
Function<@NotNull PsiAnchor, @NotNull PsiClass> converter =
|
||||
anchor -> ReadAction.compute(() -> (@NotNull PsiClass)anchor.retrieve());
|
||||
Predicate<PsiClass> applicableFilter =
|
||||
candidate -> !(candidate instanceof PsiAnonymousClass) && candidate != null && !candidate.hasModifierProperty(PsiModifier.FINAL);
|
||||
// for non-physical elements ignore the cache completely because non-physical elements created so often/unpredictably so I can't figure out when to clear caches in this case
|
||||
@@ -109,7 +113,7 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase<PsiClass, Cla
|
||||
LazyConcurrentCollection.MoreElementsGenerator<PsiAnchor, PsiClass> generator = (candidate, processor) ->
|
||||
DirectClassInheritorsSearch.search(candidate, scopeToUse, includeAnonymous).allowParallelProcessing().forEach(subClass -> {
|
||||
ProgressManager.checkCanceled();
|
||||
PsiAnchor pointer = ReadAction.compute(() -> PsiAnchor.create(subClass));
|
||||
@NotNull PsiAnchor pointer = ReadAction.compute(() -> PsiAnchor.create(subClass));
|
||||
// append found result to subClasses as early as possible to allow other waiting threads to continue
|
||||
processor.accept(pointer);
|
||||
return true;
|
||||
|
||||
@@ -37,7 +37,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
// - 'candidatesToFindSubclassesIterator' points to the next element for which direct inheritors haven't been searched yet.
|
||||
// - 'subClassIterator' created in AllSubClassesLazyCollection.iterator() maintains state of the AllSubClassesLazyCollection iterator in a lazy fashion.
|
||||
// If more elements requested for this iterator, the processMoreSubclasses() is called which tries to populate 'subClasses' with more inheritors.
|
||||
private final HashSetQueue<T> subClasses; // guarded by lock
|
||||
private final HashSetQueue<@NotNull T> subClasses = new HashSetQueue<>(); // guarded by lock
|
||||
private final Object lock = new Object(); // MUST NOT acquire read action inside this lock
|
||||
@NotNull private final Function<? super T, ? extends V> myAnchorToValueConvertor;
|
||||
@NotNull private final MoreElementsGenerator<? extends T, ? super V> myGenerator;
|
||||
@@ -58,7 +58,6 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
@NotNull Function<? super T, ? extends V> convertor,
|
||||
@NotNull Predicate<? super V> applicableForGenerationFilter,
|
||||
@NotNull MoreElementsGenerator<? extends T, ? super V> generator) {
|
||||
subClasses = new HashSetQueue<>();
|
||||
subClasses.add(seedElement);
|
||||
myAnchorToValueConvertor = convertor;
|
||||
myGenerator = generator;
|
||||
@@ -68,7 +67,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
|
||||
@FunctionalInterface
|
||||
interface MoreElementsGenerator<T,V> {
|
||||
void generateMoreElementsFor(@NotNull V element, @NotNull Consumer<? super T> processor);
|
||||
void generateMoreElementsFor(@NotNull V element, @NotNull Consumer<? super @NotNull T> processor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -107,7 +106,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
};
|
||||
}
|
||||
|
||||
// polls 'subClasses' for more sub classes and call generator.generateMoreElementsFor() on them
|
||||
// polls 'subClasses' for more subclasses and call generator.generateMoreElementsFor() on them
|
||||
// adds found classes to "subClasses" queue
|
||||
// returns as soon as something was added
|
||||
private void processMoreSubclasses(@NotNull Iterator<T> subClassIterator) {
|
||||
@@ -119,7 +118,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
ProgressManager.checkCanceled();
|
||||
synchronized (lock) {
|
||||
// Find the classes in subClasses collection to operate on
|
||||
// (without advancing the candidatesToFindSubclassesIterator iterator - it will be moved after the class successfully handled - to protect against PCE, INRE, etc)
|
||||
// (without advancing the candidatesToFindSubclassesIterator iterator - it will be moved after the class successfully handled - to protect against PCE, INRE, etc.)
|
||||
// The found class will be marked as being analyzed - placed in classesBeingProcessed collection
|
||||
HashSetQueue.PositionalIterator.IteratorPosition<T> startPosition = candidatesToFindSubclassesIterator.position().next();
|
||||
Pair.NonNull<T,V> next = startPosition == null ? null : findNextClassInQueue(startPosition);
|
||||
@@ -147,7 +146,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
|
||||
// aaaaaaaa! Other threads were unable to produce anything. That can be because:
|
||||
// - the whole queue has been processed. => exit, return false
|
||||
// - the other thread has been interrupted. => check the queue again to pickup the work it dropped.
|
||||
// - the other thread has been interrupted. => check the queue again to pick up the work it dropped.
|
||||
synchronized (lock) {
|
||||
advanceIteratorOnSuccess(); // to skip unsuitable classes like final etc from the queue
|
||||
if (!candidatesToFindSubclassesIterator.hasNext()) {
|
||||
@@ -171,7 +170,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
classesProcessed.add(anchor);
|
||||
advanceIteratorOnSuccess();
|
||||
if (subClassIterator.hasNext()) {
|
||||
// we've added something to subClasses so we can return and the iterator can move forward at least once;
|
||||
// we've added something to subClasses, so we can return and the iterator can move forward at least once;
|
||||
// more elements will be added on the subsequent call to .next()
|
||||
return;
|
||||
}
|
||||
@@ -190,7 +189,7 @@ class LazyConcurrentCollection<T,V> implements Iterable<V> {
|
||||
// Found nothing, have to wait for other threads because:
|
||||
// The first thread comes and takes a class off the queue to search for inheritors,
|
||||
// the second thread comes and sees there is no classes in the queue.
|
||||
// The second thread should not return nothing, it should wait for the first thread to finish.
|
||||
// The second thread should not return nothing, it should wait for the first thread to finish instead.
|
||||
//
|
||||
// Wait within managedBlock to signal FJP this thread is locked (to avoid thread starvation and deadlocks)
|
||||
AtomicBoolean hasNext = new AtomicBoolean();
|
||||
|
||||
Reference in New Issue
Block a user