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