Create classes when deserializing enum entries
This commit is contained in:
+3
-3
@@ -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())) {
|
||||
|
||||
+83
-44
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user