Less verbose, type-safe implementation of Flags

This commit is contained in:
Andrey Breslav
2013-05-31 18:34:49 +04:00
committed by Alexander Udalov
parent 4f12a3d86e
commit 76e01fa552
4 changed files with 118 additions and 117 deletions
@@ -83,7 +83,7 @@ public class DescriptorDeserializer {
@NotNull
public CallableMemberDescriptor loadCallable(@NotNull Callable proto) {
Callable.CallableKind callableKind = Flags.getCallableKind(proto.getFlags());
Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(proto.getFlags());
switch (callableKind) {
case FUN:
return loadFunction(proto);
@@ -102,11 +102,11 @@ public class DescriptorDeserializer {
PropertyDescriptorImpl property = new PropertyDescriptorImpl(
containingDeclaration,
getAnnotations(proto),
modality(Flags.getModality(flags)),
visibility(Flags.getVisibility(flags)),
Flags.getCallableKind(flags) == Callable.CallableKind.VAR,
modality(Flags.MODALITY.get(flags)),
visibility(Flags.VISIBILITY.get(flags)),
Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
nameResolver.getName(proto.getName()),
memberKind(Flags.getMemberKind(flags))
memberKind(Flags.MEMBER_KIND.get(flags))
);
DescriptorDeserializer local = createChildDeserializer(property);
List<TypeParameterDescriptor> typeParameters = local.typeParameters(proto.getTypeParametersList());
@@ -127,7 +127,7 @@ public class DescriptorDeserializer {
containingDeclaration,
getAnnotations(proto),
nameResolver.getName(proto.getName()),
memberKind(Flags.getMemberKind(flags))
memberKind(Flags.MEMBER_KIND.get(flags))
);
DescriptorDeserializer local = createChildDeserializer(function);
List<TypeParameterDescriptor> typeParameters = local.typeParameters(proto.getTypeParametersList());
@@ -138,9 +138,9 @@ public class DescriptorDeserializer {
typeParameters,
local.valueParameters(proto.getValueParametersList()),
local.typeDeserializer.type(proto.getReturnType()),
modality(Flags.getModality(flags)),
visibility(Flags.getVisibility(flags)),
Flags.isInline(flags)
modality(Flags.MODALITY.get(flags)),
visibility(Flags.VISIBILITY.get(flags)),
Flags.INLINE.get(flags)
);
return function;
@@ -158,14 +158,14 @@ public class DescriptorDeserializer {
descriptor.initialize(
classDescriptor.getTypeConstructor().getParameters(),
local.valueParameters(proto.getValueParametersList()),
visibility(Flags.getVisibility(proto.getFlags())),
visibility(Flags.VISIBILITY.get(proto.getFlags())),
!classDescriptor.isInner()
);
return descriptor;
}
private List<AnnotationDescriptor> getAnnotations(Callable proto) {
return Flags.hasAnnotations(proto.getFlags())
return Flags.HAS_ANNOTATIONS.get(proto.getFlags())
? annotationDeserializer.loadCallableAnnotations(proto)
: Collections.<AnnotationDescriptor>emptyList();
}
@@ -304,12 +304,12 @@ public class DescriptorDeserializer {
getAnnotations(proto),
nameResolver.getName(proto.getName()),
typeDeserializer.type(proto.getType()),
Flags.declaresDefaultValue(proto.getFlags()),
Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null));
}
private List<AnnotationDescriptor> getAnnotations(Callable.ValueParameter proto) {
return Flags.hasAnnotations(proto.getFlags())
return Flags.HAS_ANNOTATIONS.get(proto.getFlags())
? annotationDeserializer.loadValueParameterAnnotations(proto)
: Collections.<AnnotationDescriptor>emptyList();
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.descriptors.serialization;
import com.google.protobuf.Internal;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
@@ -8,44 +9,34 @@ public class Flags {
// Common
public static final int HAS_ANNOTATIONS_BIT_COUNT = 1;
public static final int HAS_ANNOTATIONS_OFFSET = 0;
public static final FlagField<Boolean> HAS_ANNOTATIONS = FlagField.booleanFirst();
public static final int VISIBILITY_BIT_COUNT = bitWidth(ProtoBuf.Visibility.values());
public static final int VISIBILITY_OFFSET = HAS_ANNOTATIONS_OFFSET + HAS_ANNOTATIONS_BIT_COUNT;
public static final FlagField<ProtoBuf.Visibility> VISIBILITY = FlagField.after(HAS_ANNOTATIONS, ProtoBuf.Visibility.values());
public static final int MODALITY_BIT_COUNT = bitWidth(ProtoBuf.Modality.values());
public static final int MODALITY_OFFSET = VISIBILITY_OFFSET + VISIBILITY_BIT_COUNT;
public static final FlagField<ProtoBuf.Modality> MODALITY = FlagField.after(VISIBILITY, ProtoBuf.Modality.values());
// 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 FlagField<ProtoBuf.Class.Kind> CLASS_KIND = FlagField.after(MODALITY, ProtoBuf.Class.Kind.values());
public static final int INNER_BIT_COUNT = 1;
public static final int INNER_OFFSET = CLASS_KIND_OFFSET + CLASS_KIND_BIT_COUNT;
public static final FlagField<Boolean> INNER = FlagField.booleanAfter(CLASS_KIND);
// 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 FlagField<ProtoBuf.Callable.CallableKind> CALLABLE_KIND = FlagField.after(MODALITY,
ProtoBuf.Callable.CallableKind.values());
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;
public static final FlagField<ProtoBuf.Callable.MemberKind> MEMBER_KIND = FlagField.after(CALLABLE_KIND,
ProtoBuf.Callable.MemberKind.values());
public static final FlagField<Boolean> INLINE = FlagField.booleanAfter(MEMBER_KIND);
// Parameters
public static final int DECLARES_DEFAULT_VALUE_BIT_COUNT = 1;
public static final int DECLARES_DEFAULT_VALUE_OFFSET = HAS_ANNOTATIONS_OFFSET + HAS_ANNOTATIONS_BIT_COUNT;
public static final FlagField<Boolean> DECLARES_DEFAULT_VALUE = FlagField.booleanAfter(HAS_ANNOTATIONS);
// ---
private static final Boolean[] BOOLEANS = { false, true };
private static <E extends Enum<E>> int bitWidth(@NotNull E[] enumEntries) {
private static <E> int bitWidth(@NotNull E[] enumEntries) {
int length = enumEntries.length - 1;
if (length == 0) return 1;
for (int i = 31; i >= 0; i--) {
@@ -54,55 +45,6 @@ public class Flags {
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 boolean declaresDefaultValue(int flags) {
return getValue(flags, BOOLEANS, DECLARES_DEFAULT_VALUE_BIT_COUNT, DECLARES_DEFAULT_VALUE_OFFSET);
}
public static boolean hasAnnotations(int flags) {
return getValue(flags, BOOLEANS, HAS_ANNOTATIONS_BIT_COUNT, HAS_ANNOTATIONS_OFFSET);
}
public static int getClassFlags(
boolean hasAnnotations,
Visibility visibility,
@@ -110,16 +52,11 @@ public class Flags {
ClassKind kind,
boolean inner
) {
int hasAnnotationsInt = hasAnnotations ? 1 : 0;
int visibilityInt = visibility(visibility).getNumber();
int modalityInt = modality(modality).getNumber();
int classKindInt = classKind(kind).getNumber();
int innerInt = inner ? 1 : 0;
return hasAnnotationsInt << HAS_ANNOTATIONS_OFFSET
| modalityInt << MODALITY_OFFSET
| visibilityInt << VISIBILITY_OFFSET
| classKindInt << CLASS_KIND_OFFSET
| innerInt << INNER_OFFSET
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| MODALITY.toFlags(modality(modality))
| VISIBILITY.toFlags(visibility(visibility))
| CLASS_KIND.toFlags(classKind(kind))
| INNER.toFlags(inner)
;
}
@@ -144,24 +81,19 @@ public class Flags {
}
public static int getCallableFlags(
boolean hasAnnotations, @NotNull Visibility visibility,
boolean hasAnnotations,
@NotNull Visibility visibility,
@NotNull Modality modality,
@NotNull CallableMemberDescriptor.Kind memberKind,
@NotNull ProtoBuf.Callable.CallableKind callableKind,
boolean inline
) {
int hasAnnotationsInt = hasAnnotations ? 1 : 0;
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 hasAnnotationsInt << HAS_ANNOTATIONS_OFFSET
| modalityInt << MODALITY_OFFSET
| visibilityInt << VISIBILITY_OFFSET
| memberKindInt << MEMBER_KIND_OFFSET
| callableKindInt << CALLABLE_KIND_OFFSET
| inlineInt << INLINE_OFFSET
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| MODALITY.toFlags(modality(modality))
| VISIBILITY.toFlags(visibility(visibility))
| MEMBER_KIND.toFlags(memberKind(memberKind))
| CALLABLE_KIND.toFlags(callableKind)
| INLINE.toFlags(inline)
;
}
@@ -211,10 +143,79 @@ public class Flags {
}
public static int getValueParameterFlags(boolean hasAnnotations, boolean declaresDefaultValue) {
int hasAnnotationsInt = hasAnnotations ? 1 : 0;
int declaresDefaultValueInt = declaresDefaultValue ? 1 : 0;
return hasAnnotationsInt << HAS_ANNOTATIONS_OFFSET
| declaresDefaultValueInt << DECLARES_DEFAULT_VALUE_OFFSET
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| DECLARES_DEFAULT_VALUE.toFlags(declaresDefaultValue)
;
}
// Infrastructure
public static abstract class FlagField<E> {
public static <E extends Internal.EnumLite> FlagField<E> after(FlagField<?> previousField, E[] values) {
int offset = previousField.offset + previousField.bitWidth;
return new EnumLiteFlagField<E>(offset, values);
}
public static <E extends Internal.EnumLite> FlagField<E> first(E[] values) {
return new EnumLiteFlagField<E>(0, values);
}
public static FlagField<Boolean> booleanFirst() {
return new BooleanFlagField(0);
}
public static FlagField<Boolean> booleanAfter(FlagField<?> previousField) {
int offset = previousField.offset + previousField.bitWidth;
return new BooleanFlagField(offset);
}
private final int offset;
private final int bitWidth;
private final E[] values;
private FlagField(int offset, E[] values) {
this.offset = offset;
this.bitWidth = bitWidth(values);
this.values = values;
}
public E get(int flags) {
int maskUnshifted = (1 << bitWidth) - 1;
int mask = maskUnshifted << offset;
int value = (flags & mask) >> offset;
return values[value];
}
public int toFlags(E value) {
return getIntValue(value) << offset;
}
protected abstract int getIntValue(E value);
}
private static class BooleanFlagField extends FlagField<Boolean> {
private static final Boolean[] BOOLEAN = { false, true };
public BooleanFlagField(int offset) {
super(offset, BOOLEAN);
}
@Override
protected int getIntValue(Boolean value) {
return value ? 1 : 0;
}
}
private static class EnumLiteFlagField<E extends Internal.EnumLite> extends FlagField<E> {
public EnumLiteFlagField(int offset, E[] values) {
super(offset, values);
}
@Override
protected int getIntValue(E value) {
return value.getNumber();
}
}
}
@@ -81,10 +81,10 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
this.name = nameResolver.getName(classProto.getName());
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);
this.modality = DescriptorDeserializer.modality(Flags.MODALITY.get(flags));
this.visibility = DescriptorDeserializer.visibility(Flags.VISIBILITY.get(flags));
this.kind = DescriptorDeserializer.classKind(Flags.CLASS_KIND.get(flags));
this.isInner = Flags.INNER.get(flags);
this.annotationDeserializer = annotationResolver;
this.annotations = new NotNullLazyValueImpl<List<AnnotationDescriptor>>() {
@@ -181,7 +181,7 @@ public class DeserializedClassDescriptor extends ClassDescriptorBase implements
}
private List<AnnotationDescriptor> computeAnnotations() {
if (!Flags.hasAnnotations(classProto.getFlags())) {
if (!Flags.HAS_ANNOTATIONS.get(classProto.getFlags())) {
return Collections.emptyList();
}
return annotationDeserializer.loadClassAnnotations(classProto);
@@ -117,7 +117,7 @@ public abstract class DeserializedMemberScope implements JetScope {
Collection<D> descriptors = new LinkedHashSet<D>(memberProtos != null ? memberProtos.size() : 0);
if (memberProtos != null) {
for (ProtoBuf.Callable memberProto : memberProtos) {
if (callableKind.accept(Flags.getCallableKind(memberProto.getFlags()))) {
if (callableKind.accept(Flags.CALLABLE_KIND.get(memberProto.getFlags()))) {
//noinspection unchecked
descriptors.add((D) deserializer.loadCallable(memberProto));
}