Refactor JavaClassResolver

This commit is contained in:
Pavel V. Talanov
2012-10-10 19:17:46 +04:00
parent bdec46ac27
commit c0b68684b8
@@ -148,13 +148,11 @@ public final class JavaClassResolver {
@NotNull DescriptorSearchRule searchRule, @NotNull DescriptorSearchRule searchRule,
@NotNull List<Runnable> tasks @NotNull List<Runnable> tasks
) { ) {
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) { if (isTraitImplementation(qualifiedName)) {
// TODO: only if -$$TImpl class is created by Kotlin
return null; return null;
} }
ClassDescriptor builtinClassDescriptor = ClassDescriptor builtinClassDescriptor = semanticServices.getKotlinBuiltinClassDescriptor(qualifiedName);
semanticServices.getKotlinBuiltinClassDescriptor(qualifiedName);
if (builtinClassDescriptor != null) { if (builtinClassDescriptor != null) {
return builtinClassDescriptor; return builtinClassDescriptor;
} }
@@ -167,99 +165,129 @@ 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(qualifiedName); ResolverClassData classData = classDescriptorCache.get(qualifiedName);
if (classData == null) { if (classData != null) {
PsiClass psiClass = return classData.getClassDescriptor();
psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW);
if (psiClass == null) {
ResolverClassData oldValue =
classDescriptorCache
.put(qualifiedName, ResolverBinaryClassData.NEGATIVE);
if (oldValue != null) {
throw new IllegalStateException("rewrite at " + qualifiedName);
}
return null;
}
classData = createJavaClassDescriptor(psiClass, tasks);
} }
return doResolveClass(qualifiedName, tasks);
}
@Nullable
private ClassDescriptor doResolveClass(@NotNull FqName qualifiedName, List<Runnable> tasks) {
PsiClass psiClass = psiClassFinder.findPsiClass(qualifiedName, PsiClassFinder.RuntimeClassesHandleMode.THROW);
if (psiClass == null) {
cacheValue(qualifiedName);
return null;
}
ResolverClassData classData = createJavaClassDescriptor(qualifiedName, psiClass, tasks);
return classData.getClassDescriptor(); return classData.getClassDescriptor();
} }
private void cacheValue(@NotNull FqName qualifiedName) {
ResolverClassData oldValue = classDescriptorCache.put(qualifiedName, ResolverBinaryClassData.NEGATIVE);
if (oldValue != null) {
throw new IllegalStateException("rewrite at " + qualifiedName);
}
}
private static boolean isTraitImplementation(@NotNull FqName qualifiedName) {
// TODO: only if -$$TImpl class is created by Kotlin
return qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX);
}
@NotNull @NotNull
private ResolverClassData createJavaClassDescriptor( private ResolverClassData createJavaClassDescriptor(
@NotNull final PsiClass psiClass, @NotNull FqName fqName, @NotNull final PsiClass psiClass,
List<Runnable> taskList List<Runnable> taskList
) { ) {
final String qualifiedName = psiClass.getQualifiedName();
assert qualifiedName != null;
FqName fqName = new FqName(qualifiedName);
if (classDescriptorCache.containsKey(fqName)) {
throw new IllegalStateException(qualifiedName);
}
checkFqNamesAreConsistent(psiClass, fqName);
DescriptorResolverUtils.checkPsiClassIsNotJet(psiClass); DescriptorResolverUtils.checkPsiClassIsNotJet(psiClass);
Name name = Name.identifier(psiClass.getName());
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
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(fqName); ResolverClassData classData = classDescriptorCache.get(fqName);
if (classData != null) { if (classData != null) {
return classData; return classData;
} }
classData = new ClassDescriptorFromJvmBytecode( return doCreateClassDescriptor(fqName, psiClass, taskList, containingDeclaration);
containingDeclaration, kind, psiClass, fqName, javaDescriptorResolver) }
.getResolverBinaryClassData();
classDescriptorCache.put(fqName, classData);
classData.getClassDescriptor().setName(name);
List<JetType> supertypes = new ArrayList<JetType>(); @NotNull
private ResolverClassData doCreateClassDescriptor(
@NotNull FqName fqName,
@NotNull PsiClass psiClass,
@NotNull List<Runnable> taskList,
@NotNull ClassOrNamespaceDescriptor containingDeclaration
) {
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
ClassDescriptorFromJvmBytecode classDescriptor
= new ClassDescriptorFromJvmBytecode(containingDeclaration, kind, psiClass, fqName, javaDescriptorResolver);
ResolverClassData classData = classDescriptor.getResolverBinaryClassData();
classDescriptorCache.put(fqName, classData);
classDescriptor.setName(Name.identifier(psiClass.getName()));
List<JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations List<JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations
= signatureResolver.createUninitializedClassTypeParameters(psiClass, classData); = signatureResolver.createUninitializedClassTypeParameters(psiClass, classData);
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(); classDescriptor.setTypeParameterDescriptors(getTypeParametersDescriptors(typeParameterDescriptorInitializations));
List<JetType> supertypes = Lists.newArrayList();
classDescriptor.setSupertypes(supertypes);
classDescriptor.setVisibility(DescriptorResolverUtils.resolveVisibility(psiClass, jetClassAnnotation));
classDescriptor.setModality(resolveModality(psiClass, classData));
classDescriptor.createTypeConstructor();
classDescriptor.setScopeForMemberLookup(new JavaClassMembersScope(semanticServices, classData));
String context = "class " + psiClass.getQualifiedName();
signatureResolver.initializeTypeParameters(typeParameterDescriptorInitializations, classDescriptor, context);
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
List<TypeParameterDescriptor> classTypeParameters = classDescriptor.getTypeConstructor().getParameters();
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters));
MutableClassDescriptorLite classObject = createClassObjectDescriptor(classDescriptor, psiClass);
if (classObject != null) {
classDescriptor.getBuilder().setClassObjectDescriptor(classObject);
}
classDescriptor.setAnnotations(annotationResolver.resolveAnnotations(psiClass, taskList));
trace.record(BindingContext.CLASS, psiClass, classDescriptor);
return classData;
}
@NotNull
private static List<TypeParameterDescriptor> getTypeParametersDescriptors(List<JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization> typeParameterDescriptorInitializations) {
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
for (JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization typeParameter : typeParameterDescriptorInitializations) { for (JavaDescriptorSignatureResolver.TypeParameterDescriptorInitialization typeParameter : typeParameterDescriptorInitializations) {
typeParameters.add(typeParameter.getDescriptor()); typeParameters.add(typeParameter.getDescriptor());
} }
return typeParameters;
}
classData.getClassDescriptor().setTypeParameterDescriptors(typeParameters); @NotNull
classData.getClassDescriptor().setSupertypes(supertypes); private static Modality resolveModality(@NotNull PsiClass psiClass, @NotNull ResolverClassData classData) {
classData.getClassDescriptor().setVisibility(DescriptorResolverUtils.resolveVisibility(psiClass, jetClassAnnotation));
Modality modality;
if (classData.getClassDescriptor().getKind() == ClassKind.ANNOTATION_CLASS) { if (classData.getClassDescriptor().getKind() == ClassKind.ANNOTATION_CLASS) {
modality = Modality.FINAL; return Modality.FINAL;
} }
else { return Modality.convertFromFlags(
modality = Modality.convertFromFlags(
psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(),
!psiClass.hasModifierProperty(PsiModifier.FINAL)); !psiClass.hasModifierProperty(PsiModifier.FINAL));
}
void checkFqNamesAreConsistent(@NotNull PsiClass psiClass, @NotNull FqName desiredFqName) {
final String qualifiedName = psiClass.getQualifiedName();
assert qualifiedName != null;
FqName fqName = new FqName(qualifiedName);
assert fqName.equals(desiredFqName);
if (classDescriptorCache.containsKey(fqName)) {
throw new IllegalStateException(qualifiedName);
} }
classData.getClassDescriptor().setModality(modality);
classData.getClassDescriptor().createTypeConstructor();
classData.getClassDescriptor()
.setScopeForMemberLookup(new JavaClassMembersScope(semanticServices, classData));
signatureResolver
.initializeTypeParameters(typeParameterDescriptorInitializations, classData.getClassDescriptor(), "class " + qualifiedName);
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
List<TypeParameterDescriptor> classTypeParameters = classData.getClassDescriptor().getTypeConstructor().getParameters();
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classTypeParameters));
MutableClassDescriptorLite classObject = createClassObjectDescriptor(classData.getClassDescriptor(), psiClass);
if (classObject != null) {
classData.getClassDescriptor().getBuilder().setClassObjectDescriptor(classObject);
}
classData.getClassDescriptor().setAnnotations(annotationResolver.resolveAnnotations(psiClass, taskList));
trace.record(BindingContext.CLASS, psiClass, classData.getClassDescriptor());
return classData;
} }
@Nullable @Nullable