Resolve enum entries similar to objects in TypeHierarchyResolver
This commit is contained in:
+2
-2
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user