Restructure JavaClassResolver caches to contain ClassDescriptor instead of ResolverClassData

This commit is contained in:
Pavel V. Talanov
2012-11-02 21:08:52 +04:00
parent aa5793d6d0
commit 1eea128b29
2 changed files with 43 additions and 26 deletions
@@ -34,10 +34,4 @@ public class ResolverBinaryClassData extends ResolverClassData {
) {
super(psiClass, null, fqName, false, classDescriptor);
}
public ResolverBinaryClassData(boolean negative) {
super(negative);
}
public static final ResolverClassData NEGATIVE = new ResolverBinaryClassData(true);
}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
@@ -29,7 +30,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.data.ResolverBinaryClassData;
import org.jetbrains.jet.lang.resolve.java.data.ResolverClassData;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
@@ -45,12 +45,14 @@ import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public final class JavaClassResolver {
// NOTE: this complexity is introduced because class descriptors do not always have valid fqnames (class objects)
private final Map<FqNameBase, ResolverClassData> classDescriptorCache =
new THashMap<FqNameBase, ResolverClassData>(new TObjectHashingStrategy<FqNameBase>() {
@NotNull
private final Map<FqNameBase, ClassDescriptor> classDescriptorCache =
new THashMap<FqNameBase, ClassDescriptor>(new TObjectHashingStrategy<FqNameBase>() {
@Override
public int computeHashCode(FqNameBase o) {
if (o instanceof FqName) {
@@ -66,6 +68,9 @@ public final class JavaClassResolver {
}
});
@NotNull
private final Set<FqNameBase> unresolvedCache = Sets.newHashSet();
private BindingTrace trace;
private JavaDescriptorResolver javaDescriptorResolver;
private JavaSignatureResolver signatureResolver;
@@ -154,9 +159,14 @@ public final class JavaClassResolver {
}
// Not let's take a descriptor of a Java class
ResolverClassData classData = classDescriptorCache.get(javaClassToKotlinFqName(qualifiedName));
if (classData != null) {
return classData.getClassDescriptor();
FqNameUnsafe fqName = javaClassToKotlinFqName(qualifiedName);
ClassDescriptor cachedDescriptor = classDescriptorCache.get(fqName);
if (cachedDescriptor != null) {
return cachedDescriptor;
}
if (unresolvedCache.contains(fqName)) {
return null;
}
return doResolveClass(qualifiedName, tasks);
@@ -166,18 +176,17 @@ public final class JavaClassResolver {
private ClassDescriptor doResolveClass(@NotNull FqName qualifiedName, @NotNull PostponedTasks tasks) {
PsiClass psiClass = psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW);
if (psiClass == null) {
cacheNegativeValue(qualifiedName);
cacheNegativeValue(javaClassToKotlinFqName(qualifiedName));
return null;
}
ResolverClassData classData = createJavaClassDescriptor(qualifiedName, psiClass, tasks);
return classData.getClassDescriptor();
return createJavaClassDescriptor(qualifiedName, psiClass, tasks);
}
private void cacheNegativeValue(@NotNull FqName qualifiedName) {
ResolverClassData oldValue = classDescriptorCache.put(javaClassToKotlinFqName(qualifiedName), ResolverBinaryClassData.NEGATIVE);
if (oldValue != null) {
private void cacheNegativeValue(@NotNull FqNameBase qualifiedName) {
if (unresolvedCache.contains(qualifiedName) || classDescriptorCache.containsKey(qualifiedName)) {
throw new IllegalStateException("rewrite at " + qualifiedName);
}
unresolvedCache.add(qualifiedName);
}
private static boolean isTraitImplementation(@NotNull FqName qualifiedName) {
@@ -186,7 +195,7 @@ public final class JavaClassResolver {
}
@NotNull
private ResolverClassData createJavaClassDescriptor(
private ClassDescriptor createJavaClassDescriptor(
@NotNull FqName fqName, @NotNull final PsiClass psiClass,
@NotNull PostponedTasks taskList
) {
@@ -196,12 +205,14 @@ public final class JavaClassResolver {
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass);
// class may be resolved during resolution of parent
ResolverClassData classData = classDescriptorCache.get(javaClassToKotlinFqName(fqName));
if (classData != null) {
return classData;
ClassDescriptor cachedDescriptor = classDescriptorCache.get(fqName);
if (cachedDescriptor != null) {
return cachedDescriptor;
}
return doCreateClassDescriptor(fqName, psiClass, taskList, containingDeclaration);
assert (!unresolvedCache.contains(fqName)) : "We can resolve the class, so it can't be 'unresolved' during parent resolution";
return doCreateClassDescriptor(fqName, psiClass, taskList, containingDeclaration).getClassDescriptor();
}
@NotNull
@@ -217,7 +228,7 @@ public final class JavaClassResolver {
= new ClassDescriptorFromJvmBytecode(containingDeclaration, kind, psiClass, fqName, javaDescriptorResolver);
ResolverClassData classData = classDescriptor.getResolverBinaryClassData();
classDescriptorCache.put(javaClassToKotlinFqName(fqName), classData);
cache(javaClassToKotlinFqName(fqName), classDescriptor);
classDescriptor.setName(Name.identifier(psiClass.getName()));
List<JavaSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations
@@ -239,7 +250,8 @@ public final class JavaClassResolver {
supertypes.addAll(supertypesResolver.getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters));
ResolverClassData classObjectData = classObjectResolver.createClassObjectDescriptor(classDescriptor, psiClass);
classDescriptorCache.put(DescriptorResolverUtils.getFqNameForClassObject(psiClass), classObjectData);
cache(DescriptorResolverUtils.getFqNameForClassObject(psiClass),
classObjectData != null ? classObjectData.getClassDescriptor() : null);
if (classObjectData != null) {
ClassDescriptorFromJvmBytecode classObjectDescriptor = classObjectData.getClassDescriptor();
classDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
@@ -252,6 +264,16 @@ public final class JavaClassResolver {
return classData;
}
private void cache(@NotNull FqNameBase fqName, @Nullable ClassDescriptor classDescriptor) {
if (classDescriptor == null) {
cacheNegativeValue(fqName);
}
else {
ClassDescriptor oldValue = classDescriptorCache.put(fqName, classDescriptor);
assert oldValue == null;
}
}
@NotNull
private static List<TypeParameterDescriptor> getTypeParametersDescriptors(
@NotNull List<JavaSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations
@@ -279,7 +301,8 @@ public final class JavaClassResolver {
FqName fqName = new FqName(qualifiedName);
assert fqName.equals(desiredFqName);
if (classDescriptorCache.containsKey(javaClassToKotlinFqName(fqName))) {
FqNameUnsafe correctedName = javaClassToKotlinFqName(fqName);
if (classDescriptorCache.containsKey(correctedName) || unresolvedCache.contains(correctedName)) {
throw new IllegalStateException(qualifiedName);
}
}