Flags supported for classes and their members

This commit is contained in:
Andrey Breslav
2013-05-15 19:01:12 +04:00
committed by Alexander Udalov
parent babb1a14d5
commit c610695612
7 changed files with 387 additions and 42 deletions
@@ -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
*/
@@ -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.<AnnotationDescriptor>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<TypeParameterDescriptor> typeParameters(@NotNull List<TypeParameter> protos) {
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>(protos.size());
@@ -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) {
@@ -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 <E extends Enum<E>> 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> 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);
}
}
@@ -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<Kind>
public static com.google.protobuf.Internal.EnumLiteMap<MemberKind>
internalGetValueMap() {
return internalValueMap;
}
private static com.google.protobuf.Internal.EnumLiteMap<Kind>
private static com.google.protobuf.Internal.EnumLiteMap<MemberKind>
internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<Kind>() {
public Kind findValueByNumber(int number) {
return Kind.valueOf(number);
new com.google.protobuf.Internal.EnumLiteMap<MemberKind>() {
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<CallableKind>
internalGetValueMap() {
return internalValueMap;
}
private static com.google.protobuf.Internal.EnumLiteMap<CallableKind>
internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<CallableKind>() {
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
@@ -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
@@ -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<FunctionDescriptor> computeFunctions(@NotNull Name name) {
List<ProtoBuf.Callable> functionProtos = membersProtos.get(name);
private <D extends CallableMemberDescriptor> List<D> computeMembersByName(Name name, ProtoBuf.Callable.CallableKind callableKind) {
List<ProtoBuf.Callable> memberProtos = membersProtos.get(name);
List<FunctionDescriptor> functions = new ArrayList<FunctionDescriptor>(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<D> descriptors = new ArrayList<D>(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<FunctionDescriptor> computeFunctions(@NotNull Name name) {
List<FunctionDescriptor> descriptors = computeMembersByName(name, ProtoBuf.Callable.CallableKind.FUN);
computeNonDeclaredFunctions(name, descriptors);
return descriptors;
}
protected void computeNonDeclaredFunctions(@NotNull Name name, @NotNull List<FunctionDescriptor> functions) {