Resolve enum entries similar to objects in TypeHierarchyResolver

This commit is contained in:
Alexander Udalov
2013-10-30 21:57:24 +04:00
parent c04f63e157
commit dd6cfcdc78
9 changed files with 103 additions and 71 deletions
@@ -137,8 +137,8 @@ public class DescriptorSerializer {
}
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
for (ClassDescriptor descriptor : getEnumEntriesScope(classDescriptor).getObjectDescriptors()) {
if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
for (DeclarationDescriptor descriptor : getEnumEntriesScope(classDescriptor).getAllDescriptors()) {
if (isEnumEntry(descriptor)) {
builder.addEnumEntry(nameTable.getSimpleNameIndex(descriptor.getName()));
}
}
@@ -21,16 +21,14 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptorForObject;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Collection;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getEnumEntriesScope;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry;
public final class WhenChecker {
private WhenChecker() {
@@ -54,13 +52,12 @@ public final class WhenChecker {
if (!(declarationDescriptor instanceof ClassDescriptor)) return false;
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
if (classDescriptor.getKind() != ClassKind.ENUM_CLASS || classDescriptor.getModality().isOverridable()) return false;
Collection<ClassDescriptor> objectDescriptors = getEnumEntriesScope(classDescriptor).getObjectDescriptors();
boolean isExhaust = true;
boolean notEmpty = false;
for (ClassDescriptor descriptor : objectDescriptors) {
if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
for (DeclarationDescriptor descriptor : getEnumEntriesScope(classDescriptor).getAllDescriptors()) {
if (isEnumEntry(descriptor)) {
notEmpty = true;
if (!containsEnumEntryCase(expression, descriptor, trace)) {
if (!containsEnumEntryCase(expression, (ClassDescriptor) descriptor, trace)) {
isExhaust = false;
}
}
@@ -100,12 +97,7 @@ public final class WhenChecker {
if (reference == null) return false;
DeclarationDescriptor target = trace.get(BindingContext.REFERENCE_TARGET, reference);
if (!(target instanceof VariableDescriptorForObject)) {
return false;
}
ClassDescriptor classDescriptor = ((VariableDescriptorForObject) target).getObjectClass();
return classDescriptor == enumEntry;
return target == enumEntry;
}
@Nullable
@@ -230,17 +230,6 @@ public class DeclarationResolver {
context.registerDeclaringScope(setter, scopeForPropertyAccessors);
}
}
@Override
public void visitEnumEntry(@NotNull JetEnumEntry enumEntry) {
// FIX: Bad cast
MutableClassDescriptorLite classObjectDescriptor =
((MutableClassDescriptorLite)namespaceLike.getOwnerForChildren()).getClassObjectDescriptor();
assert classObjectDescriptor != null;
PropertyDescriptor propertyDescriptor = descriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(
scopeForFunctions, classObjectDescriptor, enumEntry, context.getClasses().get(enumEntry), trace);
classObjectDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor);
}
});
}
}
@@ -181,22 +181,26 @@ public class TypeHierarchyResolver {
MutableClassDescriptor descriptor = entry.getValue();
if (classOrObject instanceof JetClass) {
descriptorResolver.resolveMutableClassDescriptor((JetClass) classOrObject, descriptor, trace);
descriptor.createTypeConstructor();
}
else if (classOrObject instanceof JetObjectDeclaration) {
initializeObject((JetObjectDeclaration) classOrObject, descriptor);
descriptor.setModality(Modality.FINAL);
descriptor.setVisibility(resolveVisibilityFromModifiers(classOrObject, getDefaultClassVisibility(descriptor)));
descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
}
}
}
private static void initializeObject(@NotNull JetObjectDeclaration declaration, @NotNull MutableClassDescriptor descriptor) {
descriptor.setModality(Modality.FINAL);
descriptor.setVisibility(resolveVisibilityFromModifiers(declaration, getDefaultClassVisibility(descriptor)));
descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
descriptor.createTypeConstructor();
MutableClassDescriptorLite classObject = descriptor.getClassObjectDescriptor();
if (classObject != null) {
classObject.addSupertype(descriptor.getDefaultType());
descriptor.createTypeConstructor();
if (classOrObject instanceof JetEnumEntry ||
classOrObject instanceof JetObjectDeclaration && classOrObject.getNameIdentifier() != null) {
MutableClassDescriptorLite classObject = descriptor.getClassObjectDescriptor();
assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText();
// 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.addSupertype(descriptor.getDefaultType());
}
}
}
@@ -490,11 +494,10 @@ public class TypeHierarchyResolver {
@Override
public void visitEnumEntry(@NotNull JetEnumEntry enumEntry) {
// TODO: Bad casting
MutableClassDescriptorLite ownerClassDescriptor = (MutableClassDescriptorLite) owner.getOwnerForChildren();
MutableClassDescriptorLite classObjectDescriptor = ownerClassDescriptor.getClassObjectDescriptor();
assert classObjectDescriptor != null : enumEntry.getParent().getText();
createClassDescriptorForEnumEntry(enumEntry, classObjectDescriptor);
MutableClassDescriptorLite enumClass = (MutableClassDescriptorLite) owner.getOwnerForChildren();
MutableClassDescriptorLite enumClassObject = enumClass.getClassObjectDescriptor();
assert enumClassObject != null : enumEntry.getParent().getText();
createClassDescriptorForEnumEntry(enumEntry, enumClassObject);
}
@Override
@@ -572,11 +575,22 @@ public class TypeHierarchyResolver {
@NotNull
private MutableClassDescriptor createClassDescriptorForObject(
@NotNull JetObjectDeclaration declaration,
@NotNull JetClassOrObject declaration,
@NotNull Name name,
@NotNull ClassKind kind
) {
MutableClassDescriptor descriptor = new MutableClassDescriptor(owner.getOwnerForChildren(), outerScope, kind, false, name);
return createClassDescriptorForSingleton(owner.getOwnerForChildren(), outerScope, declaration, name, kind);
}
@NotNull
private MutableClassDescriptor createClassDescriptorForSingleton(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetScope scope,
@NotNull JetClassOrObject declaration,
@NotNull Name name,
@NotNull ClassKind kind
) {
MutableClassDescriptor descriptor = new MutableClassDescriptor(containingDeclaration, scope, kind, false, name);
prepareForDeferredCall(descriptor.getScopeForMemberResolution(), descriptor, declaration);
@@ -585,30 +599,29 @@ public class TypeHierarchyResolver {
return descriptor;
}
@NotNull
private MutableClassDescriptor createClassDescriptorForEnumEntry(
@NotNull JetEnumEntry declaration,
@NotNull MutableClassDescriptorLite classObjectDescriptor
@NotNull MutableClassDescriptorLite enumClassObject
) {
NamespaceLikeBuilder owner = classObjectDescriptor.getBuilder();
MutableClassDescriptor mutableClassObjectDescriptor = (MutableClassDescriptor) classObjectDescriptor;
JetScope scope = ((MutableClassDescriptor) enumClassObject).getScopeForMemberResolution();
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), mutableClassObjectDescriptor.getScopeForMemberResolution(), ClassKind.ENUM_ENTRY,
false, JetPsiUtil.safeName(declaration.getName()));
context.getClasses().put(declaration, mutableClassDescriptor);
MutableClassDescriptor descriptor =
createClassDescriptorForSingleton(enumClassObject, scope, declaration, JetPsiUtil.safeName(declaration.getName()),
ClassKind.ENUM_ENTRY);
prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
context.getClasses().put(declaration, descriptor);
enumClassObject.getBuilder().addClassifierDescriptor(descriptor);
// ??? - is enum entry object?
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
owner.addObjectDescriptor(mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
return descriptor;
}
@NotNull
private ConstructorDescriptorImpl createPrimaryConstructorForObject(
@Nullable PsiElement object,
MutableClassDescriptor mutableClassDescriptor
@NotNull MutableClassDescriptor mutableClassDescriptor
) {
ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
.createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
@@ -7,14 +7,19 @@ internal final enum class In : jet.Enum<test.In> {
public class object <class-object-for-In> {
/*primary*/ private constructor <class-object-for-In>()
public final val A: test.In
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.In
public final /*synthesized*/ fun values(): jet.Array<test.In>
private enum entry A : test.In {
public enum entry A : test.In {
/*primary*/ private constructor A()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-A> : test.In.A {
/*primary*/ private constructor <class-object-for-A>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -26,14 +31,19 @@ private final enum class Pr : jet.Enum<test.Pr> {
public class object <class-object-for-Pr> {
/*primary*/ private constructor <class-object-for-Pr>()
public final val A: test.Pr
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.Pr
public final /*synthesized*/ fun values(): jet.Array<test.Pr>
private enum entry A : test.Pr {
public enum entry A : test.Pr {
/*primary*/ private constructor A()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-A> : test.Pr.A {
/*primary*/ private constructor <class-object-for-A>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -45,14 +55,19 @@ public final enum class Pu : jet.Enum<test.Pu> {
public class object <class-object-for-Pu> {
/*primary*/ private constructor <class-object-for-Pu>()
public final val A: test.Pu
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.Pu
public final /*synthesized*/ fun values(): jet.Array<test.Pu>
private enum entry A : test.Pu {
public enum entry A : test.Pu {
/*primary*/ private constructor A()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-A> : test.Pu.A {
/*primary*/ private constructor <class-object-for-A>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -14,14 +14,19 @@ internal final class A {
public class object <class-object-for-E> {
/*primary*/ private constructor <class-object-for-E>()
public final val ENTRY: test.A.E
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.A.E
public final /*synthesized*/ fun values(): jet.Array<test.A.E>
private enum entry ENTRY : test.A.E {
public enum entry ENTRY : test.A.E {
/*primary*/ private constructor ENTRY()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-ENTRY> : test.A.E.ENTRY {
/*primary*/ private constructor <class-object-for-ENTRY>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -10,14 +10,19 @@ internal final class A {
public class object <class-object-for-E> {
/*primary*/ private constructor <class-object-for-E>()
public final val ENTRY: test.A.E
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.A.E
public final /*synthesized*/ fun values(): jet.Array<test.A.E>
private enum entry ENTRY : test.A.E {
public enum entry ENTRY : test.A.E {
/*primary*/ private constructor ENTRY()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-ENTRY> : test.A.E.ENTRY {
/*primary*/ private constructor <class-object-for-ENTRY>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -7,14 +7,19 @@ internal final enum class MyEnum : jet.Enum<test.MyEnum> {
public class object <class-object-for-MyEnum> {
/*primary*/ private constructor <class-object-for-MyEnum>()
public final val ENTRY: test.MyEnum
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.MyEnum
public final /*synthesized*/ fun values(): jet.Array<test.MyEnum>
private enum entry ENTRY : test.MyEnum {
public enum entry ENTRY : test.MyEnum {
/*primary*/ private constructor ENTRY()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public class object <class-object-for-ENTRY> : test.MyEnum.ENTRY {
/*primary*/ private constructor <class-object-for-ENTRY>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -31,6 +31,8 @@ import org.jetbrains.jet.storage.StorageManager;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClass;
public abstract class AbstractClassDescriptor implements ClassDescriptor {
private final Name name;
protected final NotNullLazyValue<JetType> defaultType;
@@ -81,6 +83,12 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
return getDefaultType();
}
if (getKind() == ClassKind.ENUM_ENTRY) {
DeclarationDescriptor enumClass = getContainingDeclaration();
assert isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + this;
return ((ClassDescriptor) enumClass).getDefaultType();
}
ClassDescriptor classObject = getClassObjectDescriptor();
return classObject == null ? null : classObject.getDefaultType();
}