faster supertypes caching

This commit is contained in:
peter
2010-07-06 23:07:46 +01:00
parent a3ac07e7e9
commit 3e398c62cb
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.scope.JavaScopeProcessorEvent;
@@ -26,10 +25,6 @@ import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.FactoryMap;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.dsl.GroovyDslFileIndex;
@@ -56,6 +51,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProc
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author ven
@@ -63,28 +59,6 @@ import java.util.*;
@SuppressWarnings({"StringBufferReplaceableByString"})
public class ResolveUtil {
public static final PsiScopeProcessor.Event DECLARATION_SCOPE_PASSED = new PsiScopeProcessor.Event() {};
private static final Key<CachedValue<FactoryMap<PsiType, Map<String, PsiType>>>> SUPER_TYPES = Key.create("SUPER_TYPES");
private static final TObjectHashingStrategy<PsiType> RAW_TYPE_HASHING_STRATEGY = new TObjectHashingStrategy<PsiType>() {
@Override
public int computeHashCode(PsiType object) {
return stringify(object).hashCode();
}
@Override
public boolean equals(PsiType o1, PsiType o2) {
return stringify(o1).equals(stringify(o2));
}
private String stringify(PsiType type) {
final PsiClass cls = PsiUtil.resolveClassInType(type);
if (cls instanceof PsiTypeParameter) {
return cls.getName() + cls.getSuperClass().getName();
}
return rawCanonicalText(type);
}
};
private ResolveUtil() {
}
@@ -186,46 +160,47 @@ public class ResolveUtil {
return true;
}
private static void collectSuperTypes(PsiType type, Map<String, PsiType> visited) {
private static void collectSuperTypes(PsiType type, Map<String, PsiType> visited, Project project) {
String qName = rawCanonicalText(type);
if (visited.put(qName, type) != null) {
return;
}
for (PsiType superType : type.getSuperTypes()) {
collectSuperTypes(TypeConversionUtil.erasure(superType), visited);
final PsiType[] superTypes = type.getSuperTypes();
for (PsiType superType : superTypes) {
collectSuperTypes(TypeConversionUtil.erasure(superType), visited, project);
}
if (type instanceof PsiArrayType && superTypes.length == 0) {
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
collectSuperTypes(factory.createTypeFromText(CommonClassNames.JAVA_LANG_COMPARABLE, null), visited, project);
collectSuperTypes(factory.createTypeFromText(CommonClassNames.JAVA_IO_SERIALIZABLE, null), visited, project);
}
}
public static Map<String, PsiType> getAllSuperTypes(PsiType base, final PsiElement place) {
final Project project = place.getProject();
return CachedValuesManager.getManager(project).getCachedValue(project, SUPER_TYPES, new CachedValueProvider<FactoryMap<PsiType, Map<String, PsiType>>>() {
@Override
public Result<FactoryMap<PsiType, Map<String, PsiType>>> compute() {
final FactoryMap<PsiType, Map<String, PsiType>> map = new ConcurrentFactoryMap<PsiType, Map<String, PsiType>>() {
final Map<String, Map<String, PsiType>> cache =
CachedValuesManager.getManager(project).getCachedValue(project, new CachedValueProvider<Map<String, Map<String, PsiType>>>() {
@Override
public Result<Map<String, Map<String, PsiType>>> compute() {
final Map<String, Map<String, PsiType>> result = new ConcurrentHashMap<String, Map<String, PsiType>>();
return Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
});
@Override
protected Map<PsiType, Map<String, PsiType>> createMap() {
return new ConcurrentHashMap<PsiType, Map<String, PsiType>>(RAW_TYPE_HASHING_STRATEGY);
}
@Override
protected Map<String, PsiType> create(PsiType key) {
final HashMap<String, PsiType> visited = new HashMap<String, PsiType>();
collectSuperTypes(key, visited);
if (key instanceof PsiArrayType) {
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
collectSuperTypes(factory.createTypeFromText(CommonClassNames.JAVA_LANG_COMPARABLE, null), visited);
collectSuperTypes(factory.createTypeFromText(CommonClassNames.JAVA_IO_SERIALIZABLE, null), visited);
}
return visited;
}
};
return Result.create(map, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
}, false).get(base);
final PsiClass cls = PsiUtil.resolveClassInType(base);
//noinspection ConstantConditions
String key = cls instanceof PsiTypeParameter ? cls.getName() + cls.getSuperClass().getName() : rawCanonicalText(base);
Map<String, PsiType> result = cache.get(key);
if (result == null) {
result = new HashMap<String, PsiType>();
collectSuperTypes(base, result, project);
cache.put(key, result);
}
return result;
}
public static boolean isInheritor(PsiType type, @NotNull String baseClass, PsiElement place) {