diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 921577667cb9..5f84c94de0ee 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -736,38 +736,7 @@ public class PsiClassImplUtil { } public static List getScopeCorrectedSuperTypes(final PsiClass aClass, GlobalSearchScope resolveScope) { - Map> cache = - CachedValuesManager.getCachedValue(aClass, new CachedValueProvider>>() { - @Nullable - @Override - public Result>> compute() { - Map> map = new ConcurrentFactoryMap>() { - @NotNull - @Override - protected List create(final GlobalSearchScope resolveScope) { - return calcScopeCorrectedSuperTypes(resolveScope, aClass); - } - }; - return Result.create(map, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); - } - }); - return cache.get(resolveScope); - } - - @NotNull - private static List calcScopeCorrectedSuperTypes(GlobalSearchScope resolveScope, PsiClass aClass) { - List answer = ContainerUtil.newArrayList(); - for (PsiClassType type : aClass.getSuperTypes()) { - PsiClassType corrected = correctType(type, resolveScope); - if (corrected == null) continue; - - PsiClassType.ClassResolveResult result = ((PsiClassType)PsiUtil.captureToplevelWildcards(corrected, aClass)).resolveGenerics(); - PsiClass superClass = result.getElement(); - if (superClass == null || !PsiSearchScopeUtil.isInScope(resolveScope, superClass)) continue; - - answer.add(result); - } - return answer; + return ScopedClassHierarchy.getHierarchy(aClass, resolveScope).getImmediateSupersWithCapturing(); } private static boolean processSuperTypes(@NotNull PsiClass aClass, diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/ScopedClassHierarchy.java b/java/java-psi-impl/src/com/intellij/psi/impl/ScopedClassHierarchy.java index 7ae3eae09471..c60a0e1d78f7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/ScopedClassHierarchy.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/ScopedClassHierarchy.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiSearchScopeUtil; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; @@ -53,26 +54,30 @@ class ScopedClassHierarchy { return o1.getManager().areElementsEquivalent(o1, o2); } }; - private final Map mySupersWithSubstitutors = ContainerUtil.newTroveMap(CLASS_HASHING_STRATEGY); + private final PsiClass myPlaceClass; + private final GlobalSearchScope myResolveScope; + private volatile Map mySupersWithSubstitutors; + private volatile List myImmediateSupersWithCapturing; private ScopedClassHierarchy(PsiClass psiClass, GlobalSearchScope resolveScope) { - visitType(resolveScope, JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, PsiSubstitutor.EMPTY)); + myPlaceClass = psiClass; + myResolveScope = resolveScope; } - private void visitType(GlobalSearchScope resolveScope, @NotNull PsiClassType type) { + private void visitType(@NotNull PsiClassType type, Map map) { PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics(); PsiClass psiClass = resolveResult.getElement(); - if (psiClass == null || InheritanceImplUtil.hasObjectQualifiedName(psiClass) || mySupersWithSubstitutors.containsKey(psiClass)) { + if (psiClass == null || InheritanceImplUtil.hasObjectQualifiedName(psiClass) || map.containsKey(psiClass)) { return; } - mySupersWithSubstitutors.put(psiClass, resolveResult); + map.put(psiClass, resolveResult); for (PsiType superType : getSuperTypes(psiClass)) { superType = type.isRaw() && superType instanceof PsiClassType ? ((PsiClassType)superType).rawType() : resolveResult.getSubstitutor().substitute(superType); - superType = PsiClassImplUtil.correctType(superType, resolveScope); + superType = PsiClassImplUtil.correctType(superType, myResolveScope); if (superType instanceof PsiClassType) { - visitType(resolveScope, (PsiClassType)superType); + visitType((PsiClassType)superType, map); } } } @@ -89,7 +94,7 @@ class ScopedClassHierarchy { } @NotNull - private static ScopedClassHierarchy getHierarchy(@NotNull final PsiClass psiClass, @NotNull final GlobalSearchScope resolveScope) { + static ScopedClassHierarchy getHierarchy(@NotNull final PsiClass psiClass, @NotNull final GlobalSearchScope resolveScope) { return CachedValuesManager.getCachedValue(psiClass, new CachedValueProvider>() { @Nullable @Override @@ -108,7 +113,14 @@ class ScopedClassHierarchy { @Nullable static PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass derivedClass, @NotNull GlobalSearchScope scope, @NotNull PsiClass superClass) { - PsiClassType.ClassResolveResult resolveResult = getHierarchy(derivedClass, scope).mySupersWithSubstitutors.get(superClass); + ScopedClassHierarchy hierarchy = getHierarchy(derivedClass, scope); + Map map = hierarchy.mySupersWithSubstitutors; + if (map == null) { + map = ContainerUtil.newTroveMap(CLASS_HASHING_STRATEGY); + hierarchy.visitType(JavaPsiFacade.getElementFactory(derivedClass.getProject()).createType(derivedClass, PsiSubstitutor.EMPTY), map); + hierarchy.mySupersWithSubstitutors = map; + } + PsiClassType.ClassResolveResult resolveResult = map.get(superClass); if (resolveResult == null) return null; PsiClass cachedClass = assertNotNull(resolveResult.getElement()); @@ -131,4 +143,23 @@ class ScopedClassHierarchy { return answer; } + @NotNull + List getImmediateSupersWithCapturing() { + List list = myImmediateSupersWithCapturing; + if (list == null) { + list = ContainerUtil.newArrayList(); + for (PsiClassType type : myPlaceClass.getSuperTypes()) { + PsiClassType corrected = PsiClassImplUtil.correctType(type, myResolveScope); + if (corrected == null) continue; + + PsiClassType.ClassResolveResult result = ((PsiClassType)PsiUtil.captureToplevelWildcards(corrected, myPlaceClass)).resolveGenerics(); + PsiClass superClass = result.getElement(); + if (superClass == null || !PsiSearchScopeUtil.isInScope(myResolveScope, superClass)) continue; + + list.add(result); + } + myImmediateSupersWithCapturing = list; + } + return list; + } }