cleanup (part of IJPL-1128 java.util.ConcurrentModificationException on exit app from NamedObjectProviderBinding.unregisterProvider)

GitOrigin-RevId: 83216b6ba6fc480a6e5f547c749264d53bc65cd9
This commit is contained in:
Alexey Kudravtsev
2025-10-07 18:28:10 +00:00
committed by intellij-monorepo-bot
parent 2bfe62a1fc
commit 39b6deb709
2 changed files with 18 additions and 9 deletions
@@ -45,12 +45,20 @@ public abstract class NamedObjectProviderBinding implements ProviderBinding {
ProviderInfo<ElementPattern<?>>[] psiReferenceProviders = map.get(key);
ProviderInfo<ElementPattern<?>> newInfo = new ProviderInfo<>(provider, filter, priority);
ProviderInfo<ElementPattern<?>>[] newProviders = psiReferenceProviders == null ? new ProviderInfo[]{newInfo} : ArrayUtil.append(psiReferenceProviders, newInfo);
ProviderInfo<ElementPattern<?>>[] newProviders = appendToArray(psiReferenceProviders, newInfo);
map.put(key, newProviders);
}
}
static @NotNull ProviderInfo<ElementPattern<?>> @NotNull [] appendToArray(@NotNull ProviderInfo<ElementPattern<?>> @Nullable [] psiReferenceProviders,
@NotNull ProviderInfo<ElementPattern<?>> newInfo) {
@SuppressWarnings("unchecked")
ProviderInfo<ElementPattern<?>>[] newProviders = psiReferenceProviders == null ? new ProviderInfo[]{newInfo}
: ArrayUtil.append(psiReferenceProviders, newInfo);
return newProviders;
}
@Override
public void addAcceptableReferenceProviders(@NotNull PsiElement position,
@NotNull List<? super ProviderInfo<ProcessingContext>> list,
@@ -65,17 +73,18 @@ public abstract class NamedObjectProviderBinding implements ProviderBinding {
@Override
public synchronized void unregisterProvider(@NotNull PsiReferenceProvider provider) {
for (Map.Entry<String, @NotNull ProviderInfo<ElementPattern<?>>[]> entry : myNamesToProvidersMap.entrySet()) {
entry.setValue((ProviderInfo<ElementPattern<?>>[])removeFromArray(provider, entry.getValue()));
entry.setValue(removeFromArray(provider, entry.getValue()));
}
for (Map.Entry<String, @NotNull ProviderInfo<ElementPattern<?>>[]> entry : myNamesToProvidersMapInsensitive.entrySet()) {
entry.setValue((ProviderInfo<ElementPattern<?>>[])removeFromArray(provider, entry.getValue()));
entry.setValue(removeFromArray(provider, entry.getValue()));
}
}
static @NotNull ProviderInfo<?> @NotNull [] removeFromArray(@NotNull PsiReferenceProvider provider, @NotNull ProviderInfo<?> @NotNull [] array) {
static @NotNull ProviderInfo<ElementPattern<?>> @NotNull [] removeFromArray(@NotNull PsiReferenceProvider provider, @NotNull ProviderInfo<ElementPattern<?>> @NotNull [] array) {
int i = ContainerUtil.indexOf(array, trinity -> trinity.provider.equals(provider));
if (i != -1) {
return ArrayUtil.remove(array, i, ProviderInfo.ARRAY_FACTORY);
//noinspection unchecked
return (ProviderInfo<ElementPattern<?>>[])ArrayUtil.remove(array, i, ProviderInfo.ARRAY_FACTORY);
}
return array;
}
@@ -6,7 +6,6 @@ import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.PsiReferenceService;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -16,18 +15,19 @@ class SimpleProviderBinding implements ProviderBinding {
/**
* the array must be copy-on-write to avoid data races, since it can be read concurrently, via {@link #addAcceptableReferenceProviders}
*/
private volatile @NotNull ProviderInfo<?> @NotNull [] myProviderInfos = ProviderInfo.EMPTY_ARRAY;
@SuppressWarnings("unchecked")
private volatile @NotNull ProviderInfo<ElementPattern<?>> @NotNull [] myProviderInfos = (ProviderInfo<ElementPattern<?>>[])ProviderInfo.EMPTY_ARRAY;
synchronized
void registerProvider(@NotNull PsiReferenceProvider provider, @NotNull ElementPattern<?> pattern, double priority) {
myProviderInfos = ArrayUtil.append(myProviderInfos, new ProviderInfo<>(provider, pattern, priority), ProviderInfo.ARRAY_FACTORY);
myProviderInfos = NamedObjectProviderBinding.appendToArray(myProviderInfos, new ProviderInfo<>(provider, pattern, priority));
}
@Override
public void addAcceptableReferenceProviders(@NotNull PsiElement position,
@NotNull List<? super ProviderInfo<ProcessingContext>> list,
@NotNull PsiReferenceService.Hints hints) {
NamedObjectProviderBinding.addMatchingProviders(position, (ProviderInfo<ElementPattern<?>>[])myProviderInfos, list, hints);
NamedObjectProviderBinding.addMatchingProviders(position, myProviderInfos, list, hints);
}
@Override