diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java index c83e753c7dc..a90d9f05481 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java @@ -121,9 +121,9 @@ public class DescriptorSerializer { Collection 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())) { diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java index cf6e40e8905..cb293c79131 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java @@ -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 classObjectDescriptor; private final NestedClassDescriptors nestedClasses; - private final NestedClassDescriptors nestedObjects; private final NotNullLazyValue 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 names(@NotNull List nameIndices, @NotNull NameResolver nameResolver) { - Set result = new HashSet(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.emptyList(), - Visibilities.PUBLIC, name, this); - property.setType(getDefaultType(), Collections.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 computeAllObjectDescriptors() { - return classDescriptor.nestedObjects.getAllDescriptors(); + return Collections.emptySet(); } } private class NestedClassDescriptors { - private final Set declaredNames; + private final Set nestedClassNames; private final MemoizedFunctionToNullable findClass; + private final Set enumEntryNames; + + public NestedClassDescriptors() { + this.nestedClassNames = nestedClassNames(); + this.enumEntryNames = enumEntryNames(); + + final NotNullLazyValue> enumMemberNames = storageManager.createLazyValue(new Function0>() { + @Override + public Collection invoke() { + return computeEnumMemberNames(); + } + }); - public NestedClassDescriptors(@NotNull StorageManager storageManager, @NotNull Set declaredNames) { - this.declaredNames = declaredNames; this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1() { @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 nestedClassNames() { + Set result = new HashSet(); + NameResolver nameResolver = deserializer.getNameResolver(); + for (Integer index : classProto.getNestedClassNameList()) { + result.add(nameResolver.getName(index)); + } + return result; + } + + @NotNull + private Set enumEntryNames() { + if (getKind() != ClassKind.ENUM_CLASS) { + return Collections.emptySet(); + } + + Set result = new HashSet(); + NameResolver nameResolver = deserializer.getNameResolver(); + for (Integer index : classProto.getEnumEntryList()) { + result.add(nameResolver.getName(index)); + } + return result; + } + + @NotNull + private Collection computeEnumMemberNames() { + Collection result = new HashSet(); + + 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() { + @Override + public Name invoke(@NotNull ProtoBuf.Callable callable) { + return nameResolver.getName(callable.getName()); } }); } @NotNull public Collection getAllDescriptors() { - Collection result = new ArrayList(declaredNames.size()); - for (Name name : declaredNames) { + Collection result = new ArrayList(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); diff --git a/compiler/testData/compileKotlinAgainstKotlin/Enum.A.kt b/compiler/testData/compileKotlinAgainstKotlin/Enum.A.kt new file mode 100644 index 00000000000..ae66e55943c --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/Enum.A.kt @@ -0,0 +1,6 @@ +package aaa + +enum class E { + TRIVIAL_ENTRY + SUBCLASS { } +} diff --git a/compiler/testData/compileKotlinAgainstKotlin/Enum.B.kt b/compiler/testData/compileKotlinAgainstKotlin/Enum.B.kt new file mode 100644 index 00000000000..bb578560f1a --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/Enum.B.kt @@ -0,0 +1,5 @@ +import aaa.E + +fun main(args: Array) { + if (E.TRIVIAL_ENTRY == E.SUBCLASS) throw AssertionError() +} diff --git a/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.A.kt b/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.A.kt new file mode 100644 index 00000000000..2b14156f637 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.A.kt @@ -0,0 +1,10 @@ +package aaa + +enum class E { + TRIVIAL_ENTRY + SUBCLASS { } + + class Nested { + fun fortyTwo() = 42 + } +} diff --git a/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.B.kt b/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.B.kt new file mode 100644 index 00000000000..f753c27d056 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/StarImportEnum.B.kt @@ -0,0 +1,6 @@ +import aaa.E.* + +fun main(args: Array) { + if (TRIVIAL_ENTRY == SUBCLASS) throw AssertionError() + if (Nested().fortyTwo() != 42) throw AssertionError() +} diff --git a/compiler/testData/loadKotlinCustom/enum/enumVisibilityBinary.txt b/compiler/testData/loadKotlinCustom/enum/enumVisibilityBinary.txt index f1b320c34ce..bfe63919ce8 100644 --- a/compiler/testData/loadKotlinCustom/enum/enumVisibilityBinary.txt +++ b/compiler/testData/loadKotlinCustom/enum/enumVisibilityBinary.txt @@ -7,10 +7,21 @@ internal final enum class In : jet.Enum { public class object { private constructor () - public final val A: test.In public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.In public final /*synthesized*/ fun values(): jet.Array } + + 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 : test.In.A { + private constructor () + 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 { @@ -20,10 +31,21 @@ private final enum class Pr : jet.Enum { public class object { private constructor () - public final val A: test.Pr public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.Pr public final /*synthesized*/ fun values(): jet.Array } + + 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 : test.Pr.A { + private constructor () + 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 { @@ -33,8 +55,19 @@ public final enum class Pu : jet.Enum { public class object { private constructor () - public final val A: test.Pu public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.Pu public final /*synthesized*/ fun values(): jet.Array } + + 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 : test.Pu.A { + private constructor () + public final override /*1*/ /*fake_override*/ fun name(): jet.String + public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int + } + } } diff --git a/compiler/testData/loadKotlinCustom/enum/innerEnumBinary.txt b/compiler/testData/loadKotlinCustom/enum/innerEnumBinary.txt index 87a2ee27cb5..38a5c86bb71 100644 --- a/compiler/testData/loadKotlinCustom/enum/innerEnumBinary.txt +++ b/compiler/testData/loadKotlinCustom/enum/innerEnumBinary.txt @@ -10,9 +10,20 @@ internal final class A { public class object { private constructor () - 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 } + + 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 : test.A.E.ENTRY { + private constructor () + public final override /*1*/ /*fake_override*/ fun name(): jet.String + public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int + } + } } } diff --git a/compiler/testData/loadKotlinCustom/enum/innerEnumExistingClassObjectBinary.txt b/compiler/testData/loadKotlinCustom/enum/innerEnumExistingClassObjectBinary.txt index 609e08678cc..15db28b8d59 100644 --- a/compiler/testData/loadKotlinCustom/enum/innerEnumExistingClassObjectBinary.txt +++ b/compiler/testData/loadKotlinCustom/enum/innerEnumExistingClassObjectBinary.txt @@ -14,9 +14,20 @@ internal final class A { public class object { private constructor () - 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 } + + 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 : test.A.E.ENTRY { + private constructor () + public final override /*1*/ /*fake_override*/ fun name(): jet.String + public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int + } + } } } diff --git a/compiler/testData/loadKotlinCustom/enum/simpleEnumBinary.txt b/compiler/testData/loadKotlinCustom/enum/simpleEnumBinary.txt index 1e905be393d..5cc1be8a647 100644 --- a/compiler/testData/loadKotlinCustom/enum/simpleEnumBinary.txt +++ b/compiler/testData/loadKotlinCustom/enum/simpleEnumBinary.txt @@ -7,8 +7,19 @@ internal final enum class MyEnum : jet.Enum { public class object { private constructor () - public final val ENTRY: test.MyEnum public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.MyEnum public final /*synthesized*/ fun values(): jet.Array } + + 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 : test.MyEnum.ENTRY { + private constructor () + public final override /*1*/ /*fake_override*/ fun name(): jet.String + public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int + } + } } diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java index cf33cf9668b..51b486fd447 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java @@ -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"); + } + }