Put enum entries into enum class in JDR

This commit is contained in:
Alexander Udalov
2013-11-13 21:26:31 +04:00
parent 60e7722a82
commit 5a4cc1e2fe
15 changed files with 139 additions and 163 deletions
@@ -1642,10 +1642,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
if (descriptor instanceof VariableDescriptorForObject) {
return genObjectClassInstance((VariableDescriptorForObject) descriptor);
}
int index = lookupLocalIndex(descriptor);
if (index >= 0) {
return stackValueForLocal(descriptor, index);
@@ -1731,20 +1727,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
@NotNull
private StackValue genObjectClassInstance(@NotNull VariableDescriptorForObject variableDescriptor) {
boolean isEnumEntry = DescriptorUtils.isEnumClassObject(variableDescriptor.getContainingDeclaration());
if (isEnumEntry) {
ClassDescriptor containing = (ClassDescriptor) variableDescriptor.getContainingDeclaration().getContainingDeclaration();
assert containing != null;
Type type = typeMapper.mapType(containing);
return StackValue.field(type, type, variableDescriptor.getName().asString(), true);
}
else {
return StackValue.singleton(variableDescriptor.getObjectClass(), typeMapper);
}
}
private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
if (descriptor instanceof VariableDescriptor) {
Type sharedVarType = typeMapper.getSharedVarType(descriptor);
@@ -279,7 +279,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (inner == null || isTopLevelDeclaration(inner)) {
break;
}
if (inner instanceof ClassDescriptor && !isEnumClassObject(inner)) {
if (inner instanceof ClassDescriptor) {
writeInnerClass((ClassDescriptor) inner);
}
inner = inner.getContainingDeclaration();
@@ -303,9 +303,6 @@ public class AnnotationResolver {
CallableDescriptor callableDescriptor = resolvedCall.getResultingDescriptor();
if (callableDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) callableDescriptor;
if (isEnumProperty(propertyDescriptor)) {
return new EnumValue(((VariableDescriptorForObject) propertyDescriptor).getObjectClass());
}
if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) {
return trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, propertyDescriptor);
}
@@ -366,14 +363,6 @@ public class AnnotationResolver {
return expression.accept(visitor, null);
}
private static boolean isEnumProperty(@NotNull PropertyDescriptor descriptor) {
// TODO: this is true only for enum entries loaded from Java, refactor JDR to use classes with class objects instead
ClassifierDescriptor classifier = descriptor.getType().getConstructor().getDeclarationDescriptor();
return classifier != null &&
DescriptorUtils.isEnumClass(classifier) &&
DescriptorUtils.isEnumClassObject(descriptor.getContainingDeclaration());
}
@SuppressWarnings("MethodMayBeStatic")
@NotNull
public List<AnnotationDescriptor> getResolvedAnnotations(@NotNull List<JetAnnotationEntry> annotations, @NotNull BindingTrace trace) {
@@ -11,37 +11,37 @@ public final enum class EnumMembers : jet.Enum<test.EnumMembers> {
private constructor <class-object-for-EnumMembers>()
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.EnumMembers
public final /*synthesized*/ fun values(): jet.Array<test.EnumMembers>
}
public enum entry FIRST : test.EnumMembers {
private constructor FIRST()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry FIRST : test.EnumMembers {
private constructor FIRST()
public class object <class-object-for-FIRST> : test.EnumMembers.FIRST {
private constructor <class-object-for-FIRST>()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
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-FIRST> : test.EnumMembers.FIRST {
private constructor <class-object-for-FIRST>()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
public enum entry SECOND : test.EnumMembers {
private constructor SECOND()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry SECOND : test.EnumMembers {
private constructor SECOND()
public class object <class-object-for-SECOND> : test.EnumMembers.SECOND {
private constructor <class-object-for-SECOND>()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
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-SECOND> : test.EnumMembers.SECOND {
private constructor <class-object-for-SECOND>()
public final override /*1*/ /*fake_override*/ val isFirst: jet.Boolean
public open override /*1*/ /*fake_override*/ fun first(): jet.Boolean
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -9,29 +9,29 @@ public final enum class JavaEnum : jet.Enum<test.JavaEnum> {
private constructor <class-object-for-JavaEnum>()
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.JavaEnum
public final /*synthesized*/ fun values(): jet.Array<test.JavaEnum>
}
public enum entry ANOTHER : test.JavaEnum {
private constructor ANOTHER()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry ANOTHER : test.JavaEnum {
private constructor ANOTHER()
public class object <class-object-for-ANOTHER> : test.JavaEnum.ANOTHER {
private constructor <class-object-for-ANOTHER>()
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-ANOTHER> : test.JavaEnum.ANOTHER {
private constructor <class-object-for-ANOTHER>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
public enum entry ENTRY : test.JavaEnum {
private constructor ENTRY()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry ENTRY : test.JavaEnum {
private constructor ENTRY()
public class object <class-object-for-ENTRY> : test.JavaEnum.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
public class object <class-object-for-ENTRY> : test.JavaEnum.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
}
}
}
}
@@ -16,17 +16,17 @@ public trait CustomAnnotation : java.lang.Object {
private constructor <class-object-for-MyEnum>()
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.CustomAnnotation.MyEnum
public final /*synthesized*/ fun values(): jet.Array<test.CustomAnnotation.MyEnum>
}
public enum entry ONE : test.CustomAnnotation.MyEnum {
private constructor ONE()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry ONE : test.CustomAnnotation.MyEnum {
private constructor ONE()
public class object <class-object-for-ONE> : test.CustomAnnotation.MyEnum.ONE {
private constructor <class-object-for-ONE>()
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-ONE> : test.CustomAnnotation.MyEnum.ONE {
private constructor <class-object-for-ONE>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
}
@@ -9,41 +9,41 @@ public final enum class Enum : jet.Enum<test.Enum> {
private constructor <class-object-for-Enum>()
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.Enum
public final /*synthesized*/ fun values(): jet.Array<test.Enum>
}
public enum entry A : test.Enum {
private constructor A()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry A : test.Enum {
private constructor A()
public class object <class-object-for-A> : test.Enum.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 class object <class-object-for-A> : test.Enum.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 enum entry B : test.Enum {
private constructor B()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry B : test.Enum {
private constructor B()
public class object <class-object-for-B> : test.Enum.B {
private constructor <class-object-for-B>()
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-B> : test.Enum.B {
private constructor <class-object-for-B>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
public enum entry C : test.Enum {
private constructor C()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry C : test.Enum {
private constructor C()
public class object <class-object-for-C> : test.Enum.C {
private constructor <class-object-for-C>()
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-C> : test.Enum.C {
private constructor <class-object-for-C>()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
}
}
}
@@ -9,17 +9,17 @@ public final enum class StaticMembersInEnum : jet.Enum<test.StaticMembersInEnum>
private constructor <class-object-for-StaticMembersInEnum>()
public final /*synthesized*/ fun valueOf(/*0*/ value: jet.String): test.StaticMembersInEnum
public final /*synthesized*/ fun values(): jet.Array<test.StaticMembersInEnum>
}
public enum entry ENTRY : test.StaticMembersInEnum {
private constructor ENTRY()
public final override /*1*/ /*fake_override*/ fun name(): jet.String
public final override /*1*/ /*fake_override*/ fun ordinal(): jet.Int
public enum entry ENTRY : test.StaticMembersInEnum {
private constructor ENTRY()
public class object <class-object-for-ENTRY> : test.StaticMembersInEnum.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
public class object <class-object-for-ENTRY> : test.StaticMembersInEnum.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
}
}
}
}
@@ -115,23 +115,20 @@ public final class DescriptorResolverUtils {
}
/**
* @return true if {@code member} is a static member of enum class, which is to be put into its class object (and not into the
* corresponding package). This applies to enum entries, values() and valueOf(String) methods
* @return true if {@code method} is a static method of enum class, which is to be put into its class object (and not into the
* corresponding package). This applies to values() and valueOf(String) methods
*/
public static boolean shouldBeInEnumClassObject(@NotNull JavaMember member) {
if (!member.getContainingClass().isEnum()) return false;
public static boolean shouldBeInEnumClassObject(@NotNull JavaMethod method) {
if (!method.getContainingClass().isEnum()) return false;
if (member instanceof JavaField && ((JavaField) member).isEnumEntry()) return true;
if (!(member instanceof JavaMethod)) return false;
String signature = JavaSignatureFormatter.getInstance().formatMethod((JavaMethod) member);
String signature = JavaSignatureFormatter.getInstance().formatMethod(method);
return "values()".equals(signature) ||
"valueOf(java.lang.String)".equals(signature);
}
public static boolean isCorrectOwnerForEnumMember(@NotNull ClassOrNamespaceDescriptor ownerDescriptor, @NotNull JavaMember member) {
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
public static boolean isCorrectOwnerForEnumMethod(@NotNull ClassOrNamespaceDescriptor ownerDescriptor, @NotNull JavaMethod method) {
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(method);
}
public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
@@ -101,7 +101,7 @@ public final class JavaFunctionResolver {
@NotNull ClassOrNamespaceDescriptor ownerDescriptor,
boolean record
) {
if (!DescriptorResolverUtils.isCorrectOwnerForEnumMember(ownerDescriptor, method)) {
if (!DescriptorResolverUtils.isCorrectOwnerForEnumMethod(ownerDescriptor, method)) {
return null;
}
@@ -228,7 +228,7 @@ public final class JavaNamespaceResolver {
}
for (JavaField field : javaClass.getFields()) {
if (field.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(field)) {
if (field.isStatic() && !field.isEnumEntry()) {
return true;
}
}
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.types.TypeUtils;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClass;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClassObject;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.resolveOverrides;
@@ -79,7 +80,7 @@ public final class JavaPropertyResolver {
assert fields.size() <= 1;
if (fields.size() == 1) {
JavaField field = fields.iterator().next();
if (DescriptorResolverUtils.isCorrectOwnerForEnumMember(owner, field)) {
if (!field.isEnumEntry()) {
propertiesFromCurrent.add(resolveProperty(owner, propertyName, field));
}
}
@@ -16,17 +16,26 @@
package org.jetbrains.jet.lang.resolve.java.scope;
import jet.Function0;
import jet.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.NotNullLazyValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClass;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
public final class JavaClassNonStaticMembersScope extends JavaClassMembersScope {
@@ -58,6 +67,43 @@ public final class JavaClassNonStaticMembersScope extends JavaClassMembersScope
for (JavaClass innerClass : innerClasses) {
result.add(resolveInnerClass(innerClass));
}
if (isEnumClass(descriptor)) {
result.addAll(computeEnumEntries());
}
return result;
}
private Collection<ClassDescriptor> computeEnumEntries() {
List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
final Collection<NamedMembers> enumNonStaticMembers = MembersProvider.forClass(javaClass, true).allMembers();
NotNullLazyValue<Collection<Name>> enumMemberNames =
LockBasedStorageManager.NO_LOCKS.createLazyValue(new Function0<Collection<Name>>() {
@Override
public Collection<Name> invoke() {
return KotlinPackage.map(enumNonStaticMembers, new Function1<NamedMembers, Name>() {
@Override
public Name invoke(@NotNull NamedMembers members) {
return members.getName();
}
});
}
});
for (NamedMembers members : enumNonStaticMembers) {
for (JavaField field : members.getFields()) {
if (field.isEnumEntry()) {
EnumEntrySyntheticClassDescriptor enumEntry = EnumEntrySyntheticClassDescriptor
.create(LockBasedStorageManager.NO_LOCKS, descriptor, members.getName(), enumMemberNames);
result.add(enumEntry);
break;
}
}
}
return result;
}
@@ -16,24 +16,14 @@
package org.jetbrains.jet.lang.resolve.java.scope;
import jet.Function0;
import jet.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.storage.LockBasedStorageManager;
import org.jetbrains.jet.storage.NotNullLazyValue;
import org.jetbrains.jet.storage.StorageManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Collections;
public class JavaEnumClassObjectScope extends JavaClassMembersScope {
public JavaEnumClassObjectScope(
@@ -47,34 +37,6 @@ public class JavaEnumClassObjectScope extends JavaClassMembersScope {
@NotNull
@Override
protected Collection<ClassDescriptor> computeInnerClasses() {
List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
final Collection<NamedMembers> enumNonStaticMembers = membersProvider.allMembers();
NotNullLazyValue<Collection<Name>> enumMemberNames =
LockBasedStorageManager.NO_LOCKS.createLazyValue(new Function0<Collection<Name>>() {
@Override
public Collection<Name> invoke() {
return KotlinPackage.map(enumNonStaticMembers, new Function1<NamedMembers, Name>() {
@Override
public Name invoke(@NotNull NamedMembers members) {
return members.getName();
}
});
}
});
for (NamedMembers members : enumNonStaticMembers) {
for (JavaField field : members.getFields()) {
if (field.isEnumEntry()) {
EnumEntrySyntheticClassDescriptor enumEntry = EnumEntrySyntheticClassDescriptor
.create(LockBasedStorageManager.NO_LOCKS, (ClassDescriptor) descriptor, members.getName(), enumMemberNames);
result.add(enumEntry);
break;
}
}
}
return result;
return Collections.emptySet();
}
}
@@ -53,14 +53,13 @@ public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
@NotNull
public static EnumEntrySyntheticClassDescriptor create(
@NotNull StorageManager storageManager,
@NotNull ClassDescriptor enumClassObject,
@NotNull ClassDescriptor enumClass,
@NotNull Name name,
@NotNull NotNullLazyValue<Collection<Name>> enumMemberNames
) {
JetType enumType = ((ClassDescriptor) enumClassObject.getContainingDeclaration()).getDefaultType();
JetType enumType = enumClass.getDefaultType();
return new EnumEntrySyntheticClassDescriptor(storageManager, enumClassObject, enumType, name, ClassKind.ENUM_ENTRY,
enumMemberNames);
return new EnumEntrySyntheticClassDescriptor(storageManager, enumClass, enumType, name, ClassKind.ENUM_ENTRY, enumMemberNames);
}
private EnumEntrySyntheticClassDescriptor(