diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/NamedObjectProviderBinding.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/NamedObjectProviderBinding.java index 96241a9dbbd5..386a0c2dfb3a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/NamedObjectProviderBinding.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/NamedObjectProviderBinding.java @@ -21,38 +21,37 @@ import com.intellij.patterns.ElementPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.PsiReferenceService; -import com.intellij.util.ConcurrencyUtil; import com.intellij.util.ProcessingContext; -import com.intellij.util.containers.ConcurrentHashMap; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.SmartList; +import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ConcurrentMap; +import java.util.Map; /** * @author maxim */ public abstract class NamedObjectProviderBinding implements ProviderBinding { - private final ConcurrentMap>> myNamesToProvidersMap = new ConcurrentHashMap>>(5); - private final ConcurrentMap>> myNamesToProvidersMapInsensitive = new ConcurrentHashMap>>(5); + private final Map>> myNamesToProvidersMap = new THashMap>>(5); + private final Map>> myNamesToProvidersMapInsensitive = new THashMap>>(5); public void registerProvider(@NonNls @NotNull String[] names, @NotNull ElementPattern filter, boolean caseSensitive, @NotNull Provider provider, final double priority) { - final ConcurrentMap>> map = caseSensitive ? myNamesToProvidersMap : myNamesToProvidersMapInsensitive; + final Map>> map = caseSensitive ? myNamesToProvidersMap : myNamesToProvidersMapInsensitive; for (final String attributeName : names) { List> psiReferenceProviders = map.get(attributeName); if (psiReferenceProviders == null) { String key = caseSensitive ? attributeName : attributeName.toLowerCase(); - psiReferenceProviders = ConcurrencyUtil.cacheOrGet(map, key, ContainerUtil.>createLockFreeCopyOnWriteList()); + map.put(key, psiReferenceProviders = new SmartList>()); } psiReferenceProviders.add(new ProviderInfo(provider, filter, priority)); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/PsiReferenceRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/PsiReferenceRegistrarImpl.java index 8dd2a2e1e508..8d7b62023f72 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/PsiReferenceRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/PsiReferenceRegistrarImpl.java @@ -15,32 +15,30 @@ */ package com.intellij.psi.impl.source.resolve.reference; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.patterns.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.PsiReferenceRegistrar; import com.intellij.psi.PsiReferenceService; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.filters.position.FilterPattern; import com.intellij.util.ArrayUtil; -import com.intellij.util.ConcurrencyUtil; import com.intellij.util.ProcessingContext; import com.intellij.util.SmartList; import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.ConcurrentHashMap; import com.intellij.util.containers.FactoryMap; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.ConcurrentMap; /** * @author Dmitry Avdeev */ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar { - private final ConcurrentMap> myBindingsMap = new ConcurrentHashMap>(); - private final ConcurrentMap> myNamedBindingsMap = new ConcurrentHashMap>(); + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl"); + private final Map> myBindingsMap = new THashMap>(); + private final Map> myNamedBindingsMap = new THashMap>(); private final FactoryMap myKnownSupers = new ConcurrentFactoryMap() { @Override protected Class[] create(Class key) { @@ -61,22 +59,20 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar { return result.toArray(new Class[result.size()]); } }; + private boolean myInitialized; - /** - * @deprecated {@see com.intellij.psi.PsiReferenceContributor - */ - public void registerReferenceProvider(@Nullable ElementFilter elementFilter, - @NotNull Class scope, - @NotNull PsiReferenceProvider provider, - double priority) { - PsiElementPattern.Capture capture = PlatformPatterns.psiElement(scope); - registerReferenceProvider(capture.and(new FilterPattern(elementFilter)), provider, priority); + public void markInitialized() { + myInitialized = true; } @Override public void registerReferenceProvider(@NotNull ElementPattern pattern, @NotNull PsiReferenceProvider provider, double priority) { + if (myInitialized && !ApplicationManager.getApplication().isUnitTestMode()) { + LOG.error("Reference provider registration is only allowed from PsiReferenceContributor"); + } + myKnownSupers.clear(); // we should clear the cache final Class scope = pattern.getCondition().getInitialCondition().getAcceptedClass(); final List> conditions = pattern.getCondition().getConditions(); @@ -101,26 +97,11 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar { break; } - while (true) { - SimpleProviderBinding providerBinding = myBindingsMap.get(scope); - if (providerBinding != null) { - providerBinding.registerProvider(provider, pattern, priority); - return; - } - - SimpleProviderBinding binding = new SimpleProviderBinding(); - binding.registerProvider(provider, pattern, priority); - if (myBindingsMap.putIfAbsent(scope, binding) == null) break; + SimpleProviderBinding providerBinding = myBindingsMap.get(scope); + if (providerBinding == null) { + myBindingsMap.put(scope, providerBinding = new SimpleProviderBinding()); } - } - - /** - * @deprecated {@link com.intellij.psi.PsiReferenceContributor} - */ - public void registerReferenceProvider(@Nullable ElementFilter elementFilter, - @NotNull Class scope, - @NotNull PsiReferenceProvider provider) { - registerReferenceProvider(elementFilter, scope, provider, DEFAULT_PRIORITY); + providerBinding.registerProvider(provider, pattern, priority); } public void unregisterReferenceProvider(@NotNull Class scope, @NotNull PsiReferenceProvider provider) { @@ -139,14 +120,13 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar { NamedObjectProviderBinding providerBinding = myNamedBindingsMap.get(scopeClass); if (providerBinding == null) { - providerBinding = ConcurrencyUtil.cacheOrGet(myNamedBindingsMap, scopeClass, new NamedObjectProviderBinding() { + myNamedBindingsMap.put(scopeClass, providerBinding = new NamedObjectProviderBinding() { @Override protected String getName(final PsiElement position) { return nameCondition.getPropertyValue(position); } }); } - providerBinding.registerProvider(names, pattern, caseSensitive, provider, priority); } @@ -155,7 +135,7 @@ public class PsiReferenceRegistrarImpl extends PsiReferenceRegistrar { * @deprecated */ public void registerReferenceProvider(@NotNull Class scope, @NotNull PsiReferenceProvider provider) { - registerReferenceProvider(null, scope, provider); + registerReferenceProvider(PlatformPatterns.psiElement(scope), provider, DEFAULT_PRIORITY); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistryImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistryImpl.java index 456f6e6e6594..80e794d19e14 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistryImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistryImpl.java @@ -73,6 +73,9 @@ public class ReferenceProvidersRegistryImpl extends ReferenceProvidersRegistry { }); } } + + registrar.markInitialized(); + return registrar; } }; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/SimpleProviderBinding.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/SimpleProviderBinding.java index 1619f7ac26e4..69ea3dc5dc9d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/SimpleProviderBinding.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/SimpleProviderBinding.java @@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.PsiReferenceService; import com.intellij.util.ProcessingContext; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -36,7 +36,7 @@ import java.util.List; * To change this template use Options | File Templates. */ public class SimpleProviderBinding implements ProviderBinding { - private final List> myProviderPairs = ContainerUtil.createLockFreeCopyOnWriteList(); + private final List> myProviderPairs = new SmartList>(); public void registerProvider(Provider provider, ElementPattern pattern, double priority) { myProviderPairs.add(new ProviderInfo(provider, pattern, priority));