Use EnumClassObjectDescriptor in TypeHierarchyResolver

This commit is contained in:
Alexander Udalov
2014-07-06 15:22:17 +04:00
parent de21f76e10
commit db3e5ed678
10 changed files with 45 additions and 61 deletions
@@ -344,9 +344,10 @@ public class DeclarationResolver {
Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors();
ClassDescriptorWithResolutionScopes classObj = classDescriptor.getClassObjectDescriptor();
if (classObj != null) {
Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors();
ClassDescriptor classObj = classDescriptor.getClassObjectDescriptor();
if (classObj instanceof ClassDescriptorWithResolutionScopes) {
Collection<DeclarationDescriptor> classObjDescriptors =
((ClassDescriptorWithResolutionScopes) classObj).getScopeForMemberLookup().getOwnDeclaredDescriptors();
if (!classObjDescriptors.isEmpty()) {
allDescriptors = Lists.newArrayList(allDescriptors);
allDescriptors.addAll(classObjDescriptors);
@@ -85,9 +85,9 @@ public class OverrideResolver {
if (ourClasses.contains(klass)) {
generateOverridesAndDelegationInAClass(klass, processed, ourClasses);
MutableClassDescriptor classObject = klass.getClassObjectDescriptor();
if (classObject != null) {
generateOverridesAndDelegationInAClass(classObject, processed, ourClasses);
ClassDescriptor classObject = klass.getClassObjectDescriptor();
if (classObject instanceof MutableClassDescriptor) {
generateOverridesAndDelegationInAClass((MutableClassDescriptor) classObject, processed, ourClasses);
}
}
}
@@ -245,7 +245,7 @@ public class TopDownAnalyzer {
}
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
return ClassObjectStatus.NOT_ALLOWED;
}
},
@@ -21,10 +21,7 @@ import com.intellij.psi.PsiNameIdentifierOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.PackageLikeBuilder;
import org.jetbrains.jet.lang.descriptors.impl.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
@@ -33,7 +30,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.utils.DFS;
import javax.inject.Inject;
@@ -203,22 +200,16 @@ public class TypeHierarchyResolver {
descriptor.createTypeConstructor();
ClassKind kind = descriptor.getKind();
if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT || kind == ClassKind.ENUM_CLASS) {
MutableClassDescriptor classObject = descriptor.getClassObjectDescriptor();
if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT) {
MutableClassDescriptor classObject = (MutableClassDescriptor) descriptor.getClassObjectDescriptor();
assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText();
JetType supertype;
if (kind == ClassKind.ENUM_CLASS) {
supertype = KotlinBuiltIns.getInstance().getAnyType();
}
else {
// This is a clever hack: each enum entry and object declaration (i.e. singleton) has a synthetic class object.
// We make this class object inherit from the singleton here, thus allowing to use the singleton's class object where
// the instance of the singleton is applicable. Effectively all members of the singleton would be present in its class
// object as fake overrides, so you can access them via standard class object notation: ObjectName.memberName()
supertype = descriptor.getDefaultType();
}
classObject.setSupertypes(Collections.singleton(supertype));
// This is a clever hack: each enum entry and object declaration (i.e. singleton) has a synthetic class object.
// We make this class object inherit from the singleton here, thus allowing to use the singleton's class object where
// the instance of the singleton is applicable. Effectively all members of the singleton would be present in its class
// object as fake overrides, so you can access them via standard class object notation: ObjectName.memberName()
classObject.setSupertypes(Collections.singleton(descriptor.getDefaultType()));
classObject.createTypeConstructor();
}
}
@@ -377,7 +368,7 @@ public class TypeHierarchyResolver {
owner.addClassifierDescriptor(descriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(declaration), descriptor);
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObjectForSingleton(descriptor));
}
@Override
@@ -387,7 +378,7 @@ public class TypeHierarchyResolver {
owner.addClassifierDescriptor(descriptor);
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObjectForSingleton(descriptor));
}
@Override
@@ -438,17 +429,8 @@ public class TypeHierarchyResolver {
}
private void createClassObjectForEnumClass(@NotNull MutableClassDescriptor mutableClassDescriptor) {
if (mutableClassDescriptor.getKind() == ClassKind.ENUM_CLASS) {
MutableClassDescriptor classObject = createSyntheticClassObject(mutableClassDescriptor);
mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObject);
classObject.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValuesMethod(classObject, trace));
classObject.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValueOfMethod(classObject, trace));
}
}
@NotNull
private MutableClassDescriptor createSyntheticClassObject(@NotNull ClassDescriptor classDescriptor) {
private MutableClassDescriptor createSyntheticClassObjectForSingleton(@NotNull ClassDescriptor classDescriptor) {
MutableClassDescriptor classObject = new MutableClassDescriptor(classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false,
getClassObjectName(classDescriptor.getName()));
@@ -468,18 +450,19 @@ public class TypeHierarchyResolver {
// Kind check is needed in order to not consider enums as inner in any case
// (otherwise it would be impossible to create a class object in the enum)
boolean isInner = kind == ClassKind.CLASS && klass.isInner();
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName()));
c.getDeclaredClasses().put(klass, mutableClassDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(klass), mutableClassDescriptor);
MutableClassDescriptor descriptor = new MutableClassDescriptor(containingDeclaration, outerScope, kind, isInner,
JetPsiUtil.safeName(klass.getName()));
c.getDeclaredClasses().put(klass, descriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(klass), descriptor);
createClassObjectForEnumClass(mutableClassDescriptor);
if (descriptor.getKind() == ClassKind.ENUM_CLASS) {
ClassDescriptor classObject = new EnumClassObjectDescriptor(LockBasedStorageManager.NO_LOCKS, descriptor);
descriptor.getBuilder().setClassObjectDescriptor(classObject);
}
JetScope classScope = mutableClassDescriptor.getScopeForMemberDeclarationResolution();
prepareForDeferredCall(descriptor.getScopeForMemberDeclarationResolution(), descriptor, klass);
prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
return mutableClassDescriptor;
return descriptor;
}
@NotNull
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -36,10 +35,6 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor {
@NotNull
JetScope getScopeForMemberLookup();
@Nullable
@Override
ClassDescriptorWithResolutionScopes getClassObjectDescriptor();
@NotNull
@ReadOnly
Collection<CallableMemberDescriptor> getDeclaredCallableMembers();
@@ -50,7 +50,9 @@ public class EnumClassObjectDescriptor(
private val scope = WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "MemberLookup")
;{
val enumType = (getContainingDeclaration() as ClassDescriptor).getDefaultType()
val enumType = object : DelegatingType() {
override fun getDelegate() = (getContainingDeclaration() as ClassDescriptor).getDefaultType()
}
val enumArrayType = KotlinBuiltIns.getInstance().getArrayType(enumType)
scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValuesMethod(this, enumArrayType))
scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValueOfMethod(this, enumType))
@@ -44,7 +44,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
private List<TypeParameterDescriptor> typeParameters;
private Collection<JetType> supertypes = new ArrayList<JetType>();
private MutableClassDescriptor classObjectDescriptor;
private ClassDescriptor classObjectDescriptor;
private final Set<ConstructorDescriptor> constructors = Sets.newLinkedHashSet();
private ConstructorDescriptor primaryConstructor;
@@ -88,7 +88,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
@Nullable
@Override
public MutableClassDescriptor getClassObjectDescriptor() {
public ClassDescriptor getClassObjectDescriptor() {
return classObjectDescriptor;
}
@@ -296,8 +296,8 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
public void lockScopes() {
getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
if (classObjectDescriptor != null) {
classObjectDescriptor.lockScopes();
if (classObjectDescriptor instanceof MutableClassDescriptor) {
((MutableClassDescriptor) classObjectDescriptor).lockScopes();
}
scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING);
@@ -334,7 +334,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
}
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
if (getKind() == ClassKind.CLASS_OBJECT || isInner()) {
return ClassObjectStatus.NOT_ALLOWED;
}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -37,5 +38,5 @@ public interface PackageLikeBuilder {
NOT_ALLOWED
}
ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor);
ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor);
}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -44,7 +45,7 @@ public class PackageLikeBuilderDummy implements PackageLikeBuilder {
}
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
throw new IllegalStateException();
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -56,7 +57,7 @@ public class ScopeBasedPackageLikeBuilder implements PackageLikeBuilder {
}
@Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
}
}