From c610695612999e991217b42dedca2a350636b5c0 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 15 May 2013 19:01:12 +0400 Subject: [PATCH] Flags supported for classes and their members --- .../serialization/src/descriptors.proto | 17 +- .../serialization/DescriptorDeserializer.java | 96 ++++++++- .../serialization/DescriptorSerializer.java | 29 ++- .../jet/descriptors/serialization/Flags.java | 186 ++++++++++++++++++ .../descriptors/serialization/ProtoBuf.java | 65 +++++- .../DeserializedClassDescriptor.java | 9 +- .../descriptors/DeserializedMemberScope.java | 27 ++- 7 files changed, 387 insertions(+), 42 deletions(-) create mode 100644 compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/Flags.java diff --git a/compiler/frontend/serialization/src/descriptors.proto b/compiler/frontend/serialization/src/descriptors.proto index b195c9b7dc7..5c2e09e682d 100644 --- a/compiler/frontend/serialization/src/descriptors.proto +++ b/compiler/frontend/serialization/src/descriptors.proto @@ -99,8 +99,8 @@ message Class { } /* - Modality Visibility + Modality ClassKind is_inner */ @@ -128,7 +128,7 @@ message Class { } message Callable { - enum Kind { + enum MemberKind { // 2 bits DECLARATION = 0; FAKE_OVERRIDE = 1; @@ -136,11 +136,20 @@ message Callable { SYNTHESIZED = 3; } + enum CallableKind { + // 2 bits + FUN = 0; + VAL = 1; + VAR = 2; + CONSTRUCTOR = 3; + } + /* + Visibility + Modality fun/val/var/constructor Kind - Modality - Visibility + inline setter::Modality setter::Visibility */ diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java index fb8d149f4a6..047e44d64e4 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorDeserializer.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.descriptors.Visibility; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; @@ -80,16 +81,29 @@ public class DescriptorDeserializer { } @NotNull - public FunctionDescriptor loadFunction(@NotNull Callable proto) { - // TODO: assert function flag + public CallableMemberDescriptor loadCallable(@NotNull Callable proto) { + Callable.CallableKind callableKind = Flags.getCallableKind(proto.getFlags()); + switch (callableKind) { + case FUN: + return loadFunction(proto); + case VAL: + case VAR: + break; + case CONSTRUCTOR: + break; + } + throw new IllegalArgumentException("Unsupported callable kind: " + callableKind); + } + @NotNull + private CallableMemberDescriptor loadFunction(@NotNull Callable proto) { + int flags = proto.getFlags(); SimpleFunctionDescriptorImpl function = new SimpleFunctionDescriptorImpl( containingDeclaration, // TODO: annotations Collections.emptyList(), nameResolver.getName(proto.getName()), - // TODO: kind - CallableMemberDescriptor.Kind.DECLARATION + memberKind(Flags.getMemberKind(flags)) ); DescriptorDeserializer local = new DescriptorDeserializer(this, function, nameResolver); function.initialize( @@ -99,17 +113,79 @@ public class DescriptorDeserializer { local.typeParameters(proto.getTypeParametersList()), local.valueParameters(proto.getValueParametersList()), local.typeDeserializer.type(proto.getReturnType()), - // TODO: modality - Modality.OPEN, - // TODO: visibility - Visibilities.PUBLIC, - // TODO: inline - false + modality(Flags.getModality(flags)), + visibility(Flags.getVisibility(flags)), + Flags.isInline(flags) ); return function; } + private static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) { + switch (memberKind) { + case DECLARATION: + return CallableMemberDescriptor.Kind.DECLARATION; + case FAKE_OVERRIDE: + return CallableMemberDescriptor.Kind.FAKE_OVERRIDE; + case DELEGATION: + return CallableMemberDescriptor.Kind.DELEGATION; + case SYNTHESIZED: + return CallableMemberDescriptor.Kind.SYNTHESIZED; + } + throw new IllegalArgumentException("Unknown member kind: " + memberKind); + } + + @NotNull + public static Modality modality(@NotNull ProtoBuf.Modality modality) { + switch (modality) { + case FINAL: + return Modality.FINAL; + case OPEN: + return Modality.OPEN; + case ABSTRACT: + return Modality.ABSTRACT; + } + throw new IllegalArgumentException("Unknown modality: " + modality); + } + + @NotNull + public static Visibility visibility(@NotNull ProtoBuf.Visibility visibility) { + switch (visibility) { + case INTERNAL: + return Visibilities.INTERNAL; + case PRIVATE: + return Visibilities.PRIVATE; + case PROTECTED: + return Visibilities.PROTECTED; + case PUBLIC: + return Visibilities.PUBLIC; + case EXTRA: + throw new UnsupportedOperationException("Extra visibilities are not supported yet"); // TODO + } + throw new IllegalArgumentException("Unknown visibility: " + visibility); + } + + @NotNull + public static ClassKind classKind(@NotNull ProtoBuf.Class.Kind kind) { + switch (kind) { + case CLASS: + return ClassKind.CLASS; + case TRAIT: + return ClassKind.TRAIT; + case ENUM_CLASS: + return ClassKind.ENUM_CLASS; + case ENUM_ENTRY: + return ClassKind.ENUM_ENTRY; + case ANNOTATION_CLASS: + return ClassKind.ANNOTATION_CLASS; + case OBJECT: + return ClassKind.OBJECT; + case CLASS_OBJECT: + return ClassKind.CLASS_OBJECT; + } + throw new IllegalArgumentException("Unknown class kind: " + kind); + } + @NotNull public List typeParameters(@NotNull List protos) { List result = new ArrayList(protos.size()); 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 2f9f8f69f95..add2d9d2c14 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 @@ -53,7 +53,13 @@ public class DescriptorSerializer { ProtoBuf.Class.Builder builder = ProtoBuf.Class.newBuilder(); // TODO annotations - // TODO flags + extraVisibility + + int flags = Flags.getClassFlags(classDescriptor.getVisibility(), classDescriptor.getModality(), classDescriptor.getKind(), + classDescriptor.isInner()); + builder.setFlags(flags); + + // TODO extra visibility + builder.setName(nameTable.getSimpleNameIndex(classDescriptor.getName())); DescriptorSerializer local = createChildSerializer(); @@ -86,7 +92,13 @@ public class DescriptorSerializer { public ProtoBuf.Callable.Builder functionProto(@NotNull FunctionDescriptor function) { ProtoBuf.Callable.Builder builder = ProtoBuf.Callable.newBuilder(); - builder.setFlags(flags(function)); + // TODO setter flags + builder.setFlags(Flags.getCallableFlags(function.getVisibility(), + function.getModality(), + function.getKind(), + callableKind(function), + function instanceof SimpleFunctionDescriptor && ((SimpleFunctionDescriptor) function).isInline()) + ); //TODO builder.setExtraVisibility() //TODO builder.addAnnotations() @@ -113,9 +125,16 @@ public class DescriptorSerializer { return builder; } - private int flags(FunctionDescriptor function) { - // TODO - return 0; + private static ProtoBuf.Callable.CallableKind callableKind(CallableMemberDescriptor descriptor) { + if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + return propertyDescriptor.isVar() ? ProtoBuf.Callable.CallableKind.VAR : ProtoBuf.Callable.CallableKind.VAL; + } + if (descriptor instanceof ConstructorDescriptor) { + return ProtoBuf.Callable.CallableKind.CONSTRUCTOR; + } + assert descriptor instanceof FunctionDescriptor : "Unknown descriptor class: " + descriptor.getClass(); + return ProtoBuf.Callable.CallableKind.FUN; } private ProtoBuf.Callable.ValueParameter.Builder valueParameter(ValueParameterDescriptor descriptor) { diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/Flags.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/Flags.java new file mode 100644 index 00000000000..983cc423d0e --- /dev/null +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/Flags.java @@ -0,0 +1,186 @@ +package org.jetbrains.jet.descriptors.serialization; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.*; + +public class Flags { + private Flags() {} + + // Common + + public static final int VISIBILITY_BIT_COUNT = bitWidth(ProtoBuf.Visibility.values()); + public static final int VISIBILITY_OFFSET = 0; + + public static final int MODALITY_BIT_COUNT = bitWidth(ProtoBuf.Modality.values()); + public static final int MODALITY_OFFSET = VISIBILITY_OFFSET + VISIBILITY_BIT_COUNT; + + // Class + + public static final int CLASS_KIND_BIT_COUNT = bitWidth(ProtoBuf.Class.Kind.values()); + public static final int CLASS_KIND_OFFSET = MODALITY_OFFSET + MODALITY_BIT_COUNT; + + public static final int INNER_BIT_COUNT = 1; + public static final int INNER_OFFSET = CLASS_KIND_OFFSET + CLASS_KIND_BIT_COUNT; + + // Callables + + public static final int CALLABLE_KIND_BIT_COUNT = bitWidth(ProtoBuf.Callable.CallableKind.values()); + public static final int CALLABLE_KIND_OFFSET = MODALITY_OFFSET + MODALITY_BIT_COUNT; + + public static final int MEMBER_KIND_BIT_COUNT = bitWidth(ProtoBuf.Callable.MemberKind.values()); + public static final int MEMBER_KIND_OFFSET = CALLABLE_KIND_OFFSET + CALLABLE_KIND_BIT_COUNT; + + public static final int INLINE_BIT_COUNT = 1; + public static final int INLINE_OFFSET = MEMBER_KIND_OFFSET + MEMBER_KIND_BIT_COUNT; + + // --- + + private static final Boolean[] BOOLEANS = { false, true }; + + private static > int bitWidth(@NotNull E[] enumEntries) { + int length = enumEntries.length - 1; + if (length == 0) return 1; + for (int i = 31; i >= 0; i--) { + if ((length & (1 << i)) != 0) return i + 1; + } + throw new IllegalStateException("Empty enum: " + enumEntries.getClass()); + } + + @NotNull + private static E getValue(int flags, @NotNull E[] values, int count, int offset) { + int maskUnshifted = (1 << count) - 1; + int mask = maskUnshifted << offset; + int value = (flags & mask) >> offset; + return values[value]; + } + + @NotNull + public static ProtoBuf.Visibility getVisibility(int flags) { + return getValue(flags, ProtoBuf.Visibility.values(), VISIBILITY_BIT_COUNT, VISIBILITY_OFFSET); + } + + @NotNull + public static ProtoBuf.Modality getModality(int flags) { + return getValue(flags, ProtoBuf.Modality.values(), MODALITY_BIT_COUNT, MODALITY_OFFSET); + } + + @NotNull + public static ProtoBuf.Class.Kind getClassKind(int flags) { + return getValue(flags, ProtoBuf.Class.Kind.values(), CLASS_KIND_BIT_COUNT, CLASS_KIND_OFFSET); + } + + public static boolean isInner(int flags) { + return getValue(flags, BOOLEANS, INNER_BIT_COUNT, INNER_OFFSET); + } + + @NotNull + public static ProtoBuf.Callable.CallableKind getCallableKind(int flags) { + return getValue(flags, ProtoBuf.Callable.CallableKind.values(), CALLABLE_KIND_BIT_COUNT, CALLABLE_KIND_OFFSET); + } + + @NotNull + public static ProtoBuf.Callable.MemberKind getMemberKind(int flags) { + return getValue(flags, ProtoBuf.Callable.MemberKind.values(), MEMBER_KIND_BIT_COUNT, MEMBER_KIND_OFFSET); + } + + public static boolean isInline(int flags) { + return getValue(flags, BOOLEANS, INLINE_BIT_COUNT, INLINE_OFFSET); + } + + public static int getClassFlags(Visibility visibility, Modality modality, ClassKind kind, boolean inner) { + int visibilityInt = visibility(visibility).getNumber(); + int modalityInt = modality(modality).getNumber(); + int classKindInt = classKind(kind).getNumber(); + int innerInt = inner ? 1 : 0; + return visibilityInt << VISIBILITY_OFFSET + | modalityInt << MODALITY_OFFSET + | classKindInt << CLASS_KIND_OFFSET + | innerInt << INNER_OFFSET + ; + } + + private static ProtoBuf.Class.Kind classKind(ClassKind kind) { + switch (kind) { + case CLASS: + return ProtoBuf.Class.Kind.CLASS; + case TRAIT: + return ProtoBuf.Class.Kind.TRAIT; + case ENUM_CLASS: + return ProtoBuf.Class.Kind.ENUM_CLASS; + case ENUM_ENTRY: + return ProtoBuf.Class.Kind.ENUM_ENTRY; + case ANNOTATION_CLASS: + return ProtoBuf.Class.Kind.ANNOTATION_CLASS; + case OBJECT: + return ProtoBuf.Class.Kind.OBJECT; + case CLASS_OBJECT: + return ProtoBuf.Class.Kind.CLASS_OBJECT; + } + throw new IllegalArgumentException("Unknown class kind: " + kind); + } + + public static int getCallableFlags( + @NotNull Visibility visibility, + @NotNull Modality modality, + @NotNull CallableMemberDescriptor.Kind memberKind, + @NotNull ProtoBuf.Callable.CallableKind callableKind, + boolean inline + ) { + int visibilityInt = visibility(visibility).getNumber(); + int modalityInt = modality(modality).getNumber(); + int memberKindInt = memberKind(memberKind).getNumber(); + int callableKindInt = callableKind.getNumber(); + int inlineInt = inline ? 1 : 0; + return visibilityInt << VISIBILITY_OFFSET + | modalityInt << MODALITY_OFFSET + | memberKindInt << MEMBER_KIND_OFFSET + | callableKindInt << CALLABLE_KIND_OFFSET + | inlineInt << INLINE_OFFSET + ; + } + + @NotNull + private static ProtoBuf.Visibility visibility(@NotNull Visibility visibility) { + if (visibility == Visibilities.INTERNAL) { + return ProtoBuf.Visibility.INTERNAL; + } + else if (visibility == Visibilities.PUBLIC) { + return ProtoBuf.Visibility.PUBLIC; + } + else if (visibility == Visibilities.PRIVATE) { + return ProtoBuf.Visibility.PRIVATE; + } + else if (visibility == Visibilities.PROTECTED) { + return ProtoBuf.Visibility.PROTECTED; + } + return ProtoBuf.Visibility.EXTRA; + } + + @NotNull + private static ProtoBuf.Modality modality(@NotNull Modality modality) { + switch (modality) { + case FINAL: + return ProtoBuf.Modality.FINAL; + case OPEN: + return ProtoBuf.Modality.OPEN; + case ABSTRACT: + return ProtoBuf.Modality.ABSTRACT; + } + throw new IllegalArgumentException("Unknown modality: " + modality); + } + + @NotNull + private static ProtoBuf.Callable.MemberKind memberKind(@NotNull CallableMemberDescriptor.Kind kind) { + switch (kind) { + case DECLARATION: + return ProtoBuf.Callable.MemberKind.DECLARATION; + case FAKE_OVERRIDE: + return ProtoBuf.Callable.MemberKind.FAKE_OVERRIDE; + case DELEGATION: + return ProtoBuf.Callable.MemberKind.DELEGATION; + case SYNTHESIZED: + return ProtoBuf.Callable.MemberKind.SYNTHESIZED; + } + throw new IllegalArgumentException("Unknown member kind: " + kind); + } +} diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java index ec568814ee4..d2bbbfcf542 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/ProtoBuf.java @@ -4870,7 +4870,7 @@ public final class ProtoBuf { return defaultInstance; } - public enum Kind + public enum MemberKind implements com.google.protobuf.Internal.EnumLite { DECLARATION(0, 0), FAKE_OVERRIDE(1, 1), @@ -4886,7 +4886,7 @@ public final class ProtoBuf { public final int getNumber() { return value; } - public static Kind valueOf(int value) { + public static MemberKind valueOf(int value) { switch (value) { case 0: return DECLARATION; case 1: return FAKE_OVERRIDE; @@ -4896,25 +4896,72 @@ public final class ProtoBuf { } } - public static com.google.protobuf.Internal.EnumLiteMap + public static com.google.protobuf.Internal.EnumLiteMap internalGetValueMap() { return internalValueMap; } - private static com.google.protobuf.Internal.EnumLiteMap + private static com.google.protobuf.Internal.EnumLiteMap internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public Kind findValueByNumber(int number) { - return Kind.valueOf(number); + new com.google.protobuf.Internal.EnumLiteMap() { + public MemberKind findValueByNumber(int number) { + return MemberKind.valueOf(number); } }; private final int value; - private Kind(int index, int value) { + private MemberKind(int index, int value) { this.value = value; } - // @@protoc_insertion_point(enum_scope:org.jetbrains.jet.descriptors.serialization.Callable.Kind) + // @@protoc_insertion_point(enum_scope:org.jetbrains.jet.descriptors.serialization.Callable.MemberKind) + } + + public enum CallableKind + implements com.google.protobuf.Internal.EnumLite { + FUN(0, 0), + VAL(1, 1), + VAR(2, 2), + CONSTRUCTOR(3, 3), + ; + + public static final int FUN_VALUE = 0; + public static final int VAL_VALUE = 1; + public static final int VAR_VALUE = 2; + public static final int CONSTRUCTOR_VALUE = 3; + + + public final int getNumber() { return value; } + + public static CallableKind valueOf(int value) { + switch (value) { + case 0: return FUN; + case 1: return VAL; + case 2: return VAR; + case 3: return CONSTRUCTOR; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static com.google.protobuf.Internal.EnumLiteMap + internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public CallableKind findValueByNumber(int number) { + return CallableKind.valueOf(number); + } + }; + + private final int value; + + private CallableKind(int index, int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:org.jetbrains.jet.descriptors.serialization.Callable.CallableKind) } public interface ValueParameterOrBuilder 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 15d0a1bfc78..0064aa7ca8b 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 @@ -69,10 +69,11 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements this.thisAsReceiverParameter = new ReceiverParameterDescriptorImpl(this, getDefaultType(), new ClassReceiver(this)); this.name = nameResolver.getName(classProto.getName()); - this.modality = Modality.OPEN; // TODO - this.visibility = Visibilities.INTERNAL; // TODO - this.kind = ClassKind.CLASS; // TODO - this.isInner = false; // TODO + int flags = classProto.getFlags(); + this.modality = DescriptorDeserializer.modality(Flags.getModality(flags)); + this.visibility = DescriptorDeserializer.visibility(Flags.getVisibility(flags)); + this.kind = DescriptorDeserializer.classKind(Flags.getClassKind(flags)); + this.isInner = Flags.isInner(flags); } @NotNull diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.java index 4db00d82369..e63efdc6b25 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedMemberScope.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.descriptors.serialization.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.descriptors.serialization.DescriptorDeserializer; +import org.jetbrains.jet.descriptors.serialization.Flags; import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull; @@ -89,20 +90,26 @@ public abstract class DeserializedMemberScope implements JetScope { } @NotNull - private Collection computeFunctions(@NotNull Name name) { - List functionProtos = membersProtos.get(name); + private List computeMembersByName(Name name, ProtoBuf.Callable.CallableKind callableKind) { + List memberProtos = membersProtos.get(name); - List functions = new ArrayList(functionProtos != null ? functionProtos.size() : 0); - if (functionProtos != null) { - for (ProtoBuf.Callable memberProto : functionProtos) { - // TODO: check that the proto is a function, and not a property - functions.add(deserializer.loadFunction(memberProto)); + List descriptors = new ArrayList(memberProtos != null ? memberProtos.size() : 0); + if (memberProtos != null) { + for (ProtoBuf.Callable memberProto : memberProtos) { + if (Flags.getCallableKind(memberProto.getFlags()) == callableKind) { + //noinspection unchecked + descriptors.add((D) deserializer.loadCallable(memberProto)); + } } } + return descriptors; + } - computeNonDeclaredFunctions(name, functions); - - return functions; + @NotNull + private Collection computeFunctions(@NotNull Name name) { + List descriptors = computeMembersByName(name, ProtoBuf.Callable.CallableKind.FUN); + computeNonDeclaredFunctions(name, descriptors); + return descriptors; } protected void computeNonDeclaredFunctions(@NotNull Name name, @NotNull List functions) {