Create classes when deserializing enum entries

This commit is contained in:
Alexander Udalov
2013-11-13 23:38:27 +04:00
parent bd5eee5cc2
commit dd290bbeb9
11 changed files with 195 additions and 53 deletions
@@ -121,9 +121,9 @@ public class DescriptorSerializer {
Collection<DeclarationDescriptor> nestedClasses = classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors();
for (DeclarationDescriptor descriptor : sort(nestedClasses)) {
ClassDescriptor nestedClass = (ClassDescriptor) descriptor;
int nameIndex = nameTable.getSimpleNameIndex(nestedClass.getName());
builder.addNestedClassName(nameIndex);
if (!isEnumEntry(descriptor)) {
builder.addNestedClassName(nameTable.getSimpleNameIndex(descriptor.getName()));
}
}
for (ClassDescriptor descriptor : sort(classDescriptor.getUnsubstitutedInnerClassesScope().getObjectDescriptors())) {
@@ -18,12 +18,16 @@ package org.jetbrains.jet.descriptors.serialization.descriptors;
import jet.Function0;
import jet.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.*;
import org.jetbrains.jet.lang.descriptors.impl.AbstractClassDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorFactory;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
@@ -41,7 +45,6 @@ import org.jetbrains.jet.storage.StorageManager;
import java.util.*;
import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
public class DeserializedClassDescriptor extends AbstractClassDescriptor implements ClassDescriptor {
@@ -61,7 +64,6 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
private final NestedClassDescriptors nestedClasses;
private final NestedClassDescriptors nestedObjects;
private final NotNullLazyValue<DeclarationDescriptor> containingDeclaration;
private final DeserializedClassTypeConstructor typeConstructor;
@@ -129,17 +131,8 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
return computeClassObjectDescriptor();
}
});
this.nestedClasses = new NestedClassDescriptors(storageManager, names(classProto.getNestedClassNameList(), nameResolver));
this.nestedObjects = new NestedClassDescriptors(storageManager, names(classProto.getNestedObjectNameList(), nameResolver));
}
@NotNull
private static Set<Name> names(@NotNull List<Integer> nameIndices, @NotNull NameResolver nameResolver) {
Set<Name> result = new HashSet<Name>(nameIndices.size());
for (Integer index : nameIndices) {
result.add(nameResolver.getName(index));
}
return result;
this.nestedClasses = new NestedClassDescriptors();
}
@NotNull
@@ -243,13 +236,7 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
}
if (getKind() == ClassKind.ENUM_CLASS) {
MutableClassDescriptor classObject = createEnumClassObject();
for (int enumEntry : classProto.getEnumEntryList()) {
createEnumEntry(classObject, deserializer.getNameResolver().getName(enumEntry));
}
return classObject;
return createEnumClassObject();
}
if (getKind() == ClassKind.OBJECT) {
@@ -283,20 +270,6 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
return classObject;
}
private void createEnumEntry(@NotNull MutableClassDescriptor enumClassObject, @NotNull Name name) {
PropertyDescriptorImpl property = new PropertyDescriptorForObjectImpl(enumClassObject,
Collections.<AnnotationDescriptor>emptyList(),
Visibilities.PUBLIC, name, this);
property.setType(getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(),
enumClassObject.getThisAsReceiverParameter(), NO_RECEIVER_PARAMETER);
PropertyGetterDescriptorImpl getter = DescriptorFactory.createDefaultGetter(property);
getter.initialize(property.getReturnType());
property.initialize(getter, null);
enumClassObject.getBuilder().addPropertyDescriptor(property);
}
@Nullable
@Override
public ClassDescriptor getClassObjectDescriptor() {
@@ -463,36 +436,102 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme
@Nullable
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return classDescriptor.nestedObjects.findClass.invoke(name);
return null;
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeAllObjectDescriptors() {
return classDescriptor.nestedObjects.getAllDescriptors();
return Collections.emptySet();
}
}
private class NestedClassDescriptors {
private final Set<Name> declaredNames;
private final Set<Name> nestedClassNames;
private final MemoizedFunctionToNullable<Name, ClassDescriptor> findClass;
private final Set<Name> enumEntryNames;
public NestedClassDescriptors() {
this.nestedClassNames = nestedClassNames();
this.enumEntryNames = enumEntryNames();
final NotNullLazyValue<Collection<Name>> enumMemberNames = storageManager.createLazyValue(new Function0<Collection<Name>>() {
@Override
public Collection<Name> invoke() {
return computeEnumMemberNames();
}
});
public NestedClassDescriptors(@NotNull StorageManager storageManager, @NotNull Set<Name> declaredNames) {
this.declaredNames = declaredNames;
this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1<Name, ClassDescriptor>() {
@Override
public ClassDescriptor invoke(Name name) {
return NestedClassDescriptors.this.declaredNames.contains(name) ?
descriptorFinder.findClass(classId.createNestedClassId(name)) :
null;
if (enumEntryNames.contains(name)) {
return EnumEntrySyntheticClassDescriptor
.create(storageManager, DeserializedClassDescriptor.this, name, enumMemberNames);
}
if (nestedClassNames.contains(name)) {
return descriptorFinder.findClass(classId.createNestedClassId(name));
}
return null;
}
});
}
@NotNull
private Set<Name> nestedClassNames() {
Set<Name> result = new HashSet<Name>();
NameResolver nameResolver = deserializer.getNameResolver();
for (Integer index : classProto.getNestedClassNameList()) {
result.add(nameResolver.getName(index));
}
return result;
}
@NotNull
private Set<Name> enumEntryNames() {
if (getKind() != ClassKind.ENUM_CLASS) {
return Collections.emptySet();
}
Set<Name> result = new HashSet<Name>();
NameResolver nameResolver = deserializer.getNameResolver();
for (Integer index : classProto.getEnumEntryList()) {
result.add(nameResolver.getName(index));
}
return result;
}
@NotNull
private Collection<Name> computeEnumMemberNames() {
Collection<Name> result = new HashSet<Name>();
for (JetType supertype : getTypeConstructor().getSupertypes()) {
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof PropertyDescriptor) {
result.add(descriptor.getName());
}
}
}
final NameResolver nameResolver = deserializer.getNameResolver();
return KotlinPackage.mapTo(classProto.getMemberList(), result, new Function1<ProtoBuf.Callable, Name>() {
@Override
public Name invoke(@NotNull ProtoBuf.Callable callable) {
return nameResolver.getName(callable.getName());
}
});
}
@NotNull
public Collection<ClassDescriptor> getAllDescriptors() {
Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(declaredNames.size());
for (Name name : declaredNames) {
Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(nestedClassNames.size() + enumEntryNames.size());
for (Name name : nestedClassNames) {
ClassDescriptor descriptor = findClass.invoke(name);
if (descriptor != null) {
result.add(descriptor);
}
}
for (Name name : enumEntryNames) {
ClassDescriptor descriptor = findClass.invoke(name);
if (descriptor != null) {
result.add(descriptor);
@@ -0,0 +1,6 @@
package aaa
enum class E {
TRIVIAL_ENTRY
SUBCLASS { }
}
@@ -0,0 +1,5 @@
import aaa.E
fun main(args: Array<String>) {
if (E.TRIVIAL_ENTRY == E.SUBCLASS) throw AssertionError()
}
@@ -0,0 +1,10 @@
package aaa
enum class E {
TRIVIAL_ENTRY
SUBCLASS { }
class Nested {
fun fortyTwo() = 42
}
}
@@ -0,0 +1,6 @@
import aaa.E.*
fun main(args: Array<String>) {
if (TRIVIAL_ENTRY == SUBCLASS) throw AssertionError()
if (Nested().fortyTwo() != 42) throw AssertionError()
}
@@ -7,10 +7,21 @@ internal final enum class In : jet.Enum<test.In> {
public class object <class-object-for-In> {
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>
}
public enum entry A : test.In {
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 {
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
}
}
}
private final enum class Pr : jet.Enum<test.Pr> {
@@ -20,10 +31,21 @@ private final enum class Pr : jet.Enum<test.Pr> {
public class object <class-object-for-Pr> {
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>
}
public enum entry A : test.Pr {
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 {
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
}
}
}
public final enum class Pu : jet.Enum<test.Pu> {
@@ -33,8 +55,19 @@ public final enum class Pu : jet.Enum<test.Pu> {
public class object <class-object-for-Pu> {
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>
}
public enum entry A : test.Pu {
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 {
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
}
}
}
@@ -10,9 +10,20 @@ internal final class A {
public class object <class-object-for-E> {
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>
}
public enum entry ENTRY : test.A.E {
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 {
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
}
}
}
}
@@ -14,9 +14,20 @@ internal final class A {
public class object <class-object-for-E> {
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>
}
public enum entry ENTRY : test.A.E {
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 {
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,8 +7,19 @@ internal final enum class MyEnum : jet.Enum<test.MyEnum> {
public class object <class-object-for-MyEnum> {
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>
}
public enum entry ENTRY : test.MyEnum {
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 {
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
}
}
}
@@ -56,6 +56,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
doTest("compiler/testData/compileKotlinAgainstKotlin/DefaultConstructor.A.kt");
}
@TestMetadata("Enum.A.kt")
public void testEnum() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/Enum.A.kt");
}
@TestMetadata("ImportObject.A.kt")
public void testImportObject() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/ImportObject.A.kt");
@@ -91,4 +96,9 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
doTest("compiler/testData/compileKotlinAgainstKotlin/Simple.A.kt");
}
@TestMetadata("StarImportEnum.A.kt")
public void testStarImportEnum() throws Exception {
doTest("compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.A.kt");
}
}