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(); Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors();
ClassDescriptorWithResolutionScopes classObj = classDescriptor.getClassObjectDescriptor(); ClassDescriptor classObj = classDescriptor.getClassObjectDescriptor();
if (classObj != null) { if (classObj instanceof ClassDescriptorWithResolutionScopes) {
Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors(); Collection<DeclarationDescriptor> classObjDescriptors =
((ClassDescriptorWithResolutionScopes) classObj).getScopeForMemberLookup().getOwnDeclaredDescriptors();
if (!classObjDescriptors.isEmpty()) { if (!classObjDescriptors.isEmpty()) {
allDescriptors = Lists.newArrayList(allDescriptors); allDescriptors = Lists.newArrayList(allDescriptors);
allDescriptors.addAll(classObjDescriptors); allDescriptors.addAll(classObjDescriptors);
@@ -85,9 +85,9 @@ public class OverrideResolver {
if (ourClasses.contains(klass)) { if (ourClasses.contains(klass)) {
generateOverridesAndDelegationInAClass(klass, processed, ourClasses); generateOverridesAndDelegationInAClass(klass, processed, ourClasses);
MutableClassDescriptor classObject = klass.getClassObjectDescriptor(); ClassDescriptor classObject = klass.getClassObjectDescriptor();
if (classObject != null) { if (classObject instanceof MutableClassDescriptor) {
generateOverridesAndDelegationInAClass(classObject, processed, ourClasses); generateOverridesAndDelegationInAClass((MutableClassDescriptor) classObject, processed, ourClasses);
} }
} }
} }
@@ -245,7 +245,7 @@ public class TopDownAnalyzer {
} }
@Override @Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
return ClassObjectStatus.NOT_ALLOWED; return ClassObjectStatus.NOT_ALLOWED;
} }
}, },
@@ -21,10 +21,7 @@ import com.intellij.psi.PsiNameIdentifierOwner;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.*;
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.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames; 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.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope; import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
import org.jetbrains.jet.lang.types.JetType; 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 org.jetbrains.jet.utils.DFS;
import javax.inject.Inject; import javax.inject.Inject;
@@ -203,22 +200,16 @@ public class TypeHierarchyResolver {
descriptor.createTypeConstructor(); descriptor.createTypeConstructor();
ClassKind kind = descriptor.getKind(); ClassKind kind = descriptor.getKind();
if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT || kind == ClassKind.ENUM_CLASS) { if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT) {
MutableClassDescriptor classObject = descriptor.getClassObjectDescriptor(); MutableClassDescriptor classObject = (MutableClassDescriptor) descriptor.getClassObjectDescriptor();
assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText(); assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText();
JetType supertype; // This is a clever hack: each enum entry and object declaration (i.e. singleton) has a synthetic class object.
if (kind == ClassKind.ENUM_CLASS) { // We make this class object inherit from the singleton here, thus allowing to use the singleton's class object where
supertype = KotlinBuiltIns.getInstance().getAnyType(); // 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()
else { classObject.setSupertypes(Collections.singleton(descriptor.getDefaultType()));
// 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));
classObject.createTypeConstructor(); classObject.createTypeConstructor();
} }
} }
@@ -377,7 +368,7 @@ public class TypeHierarchyResolver {
owner.addClassifierDescriptor(descriptor); owner.addClassifierDescriptor(descriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(declaration), descriptor); trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(declaration), descriptor);
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor)); descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObjectForSingleton(descriptor));
} }
@Override @Override
@@ -387,7 +378,7 @@ public class TypeHierarchyResolver {
owner.addClassifierDescriptor(descriptor); owner.addClassifierDescriptor(descriptor);
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor)); descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObjectForSingleton(descriptor));
} }
@Override @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 @NotNull
private MutableClassDescriptor createSyntheticClassObject(@NotNull ClassDescriptor classDescriptor) { private MutableClassDescriptor createSyntheticClassObjectForSingleton(@NotNull ClassDescriptor classDescriptor) {
MutableClassDescriptor classObject = new MutableClassDescriptor(classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false, MutableClassDescriptor classObject = new MutableClassDescriptor(classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false,
getClassObjectName(classDescriptor.getName())); 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 // 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) // (otherwise it would be impossible to create a class object in the enum)
boolean isInner = kind == ClassKind.CLASS && klass.isInner(); boolean isInner = kind == ClassKind.CLASS && klass.isInner();
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor( MutableClassDescriptor descriptor = new MutableClassDescriptor(containingDeclaration, outerScope, kind, isInner,
containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName())); JetPsiUtil.safeName(klass.getName()));
c.getDeclaredClasses().put(klass, mutableClassDescriptor); c.getDeclaredClasses().put(klass, descriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetNamedDeclarationUtil.getUnsafeFQName(klass), mutableClassDescriptor); 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 descriptor;
return mutableClassDescriptor;
} }
@NotNull @NotNull
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly; import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -36,10 +35,6 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor {
@NotNull @NotNull
JetScope getScopeForMemberLookup(); JetScope getScopeForMemberLookup();
@Nullable
@Override
ClassDescriptorWithResolutionScopes getClassObjectDescriptor();
@NotNull @NotNull
@ReadOnly @ReadOnly
Collection<CallableMemberDescriptor> getDeclaredCallableMembers(); Collection<CallableMemberDescriptor> getDeclaredCallableMembers();
@@ -50,7 +50,9 @@ public class EnumClassObjectDescriptor(
private val scope = WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "MemberLookup") 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) val enumArrayType = KotlinBuiltIns.getInstance().getArrayType(enumType)
scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValuesMethod(this, enumArrayType)) scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValuesMethod(this, enumArrayType))
scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValueOfMethod(this, enumType)) scope.addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValueOfMethod(this, enumType))
@@ -44,7 +44,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
private List<TypeParameterDescriptor> typeParameters; private List<TypeParameterDescriptor> typeParameters;
private Collection<JetType> supertypes = new ArrayList<JetType>(); private Collection<JetType> supertypes = new ArrayList<JetType>();
private MutableClassDescriptor classObjectDescriptor; private ClassDescriptor classObjectDescriptor;
private final Set<ConstructorDescriptor> constructors = Sets.newLinkedHashSet(); private final Set<ConstructorDescriptor> constructors = Sets.newLinkedHashSet();
private ConstructorDescriptor primaryConstructor; private ConstructorDescriptor primaryConstructor;
@@ -88,7 +88,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
@Nullable @Nullable
@Override @Override
public MutableClassDescriptor getClassObjectDescriptor() { public ClassDescriptor getClassObjectDescriptor() {
return classObjectDescriptor; return classObjectDescriptor;
} }
@@ -296,8 +296,8 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
public void lockScopes() { public void lockScopes() {
getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING); getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
if (classObjectDescriptor != null) { if (classObjectDescriptor instanceof MutableClassDescriptor) {
classObjectDescriptor.lockScopes(); ((MutableClassDescriptor) classObjectDescriptor).lockScopes();
} }
scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING); scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING); scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING);
@@ -334,7 +334,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
} }
@Override @Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
if (getKind() == ClassKind.CLASS_OBJECT || isInner()) { if (getKind() == ClassKind.CLASS_OBJECT || isInner()) {
return ClassObjectStatus.NOT_ALLOWED; return ClassObjectStatus.NOT_ALLOWED;
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl; package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull; 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.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -37,5 +38,5 @@ public interface PackageLikeBuilder {
NOT_ALLOWED NOT_ALLOWED
} }
ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor); ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor);
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl; package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull; 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.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -44,7 +45,7 @@ public class PackageLikeBuilderDummy implements PackageLikeBuilder {
} }
@Override @Override
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { public ClassObjectStatus setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.descriptors.impl; package org.jetbrains.jet.lang.descriptors.impl;
import org.jetbrains.annotations.NotNull; 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.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -56,7 +57,7 @@ public class ScopeBasedPackageLikeBuilder implements PackageLikeBuilder {
} }
@Override @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"); throw new IllegalStateException("Must be guaranteed not to happen by the parser");
} }
} }