kotlin.reflect.jvm.internal.impl.serialization.Flags Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-reflect Show documentation
Show all versions of kotlin-reflect Show documentation
Kotlin Full Reflection Library
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.reflect.jvm.internal.impl.serialization;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import kotlin.reflect.jvm.internal.impl.descriptors.*;
import kotlin.reflect.jvm.internal.impl.protobuf.Internal;
public class Flags {
private Flags() {}
// Types
public static final BooleanFlagField SUSPEND_TYPE = FlagField.booleanFirst();
// Common for declarations
public static final BooleanFlagField HAS_ANNOTATIONS = FlagField.booleanFirst();
public static final FlagField VISIBILITY = FlagField.after(HAS_ANNOTATIONS, ProtoBuf.Visibility.values());
public static final FlagField MODALITY = FlagField.after(VISIBILITY, ProtoBuf.Modality.values());
// Class
public static final FlagField CLASS_KIND = FlagField.after(MODALITY, ProtoBuf.Class.Kind.values());
public static final BooleanFlagField IS_INNER = FlagField.booleanAfter(CLASS_KIND);
public static final BooleanFlagField IS_DATA = FlagField.booleanAfter(IS_INNER);
public static final BooleanFlagField IS_EXTERNAL_CLASS = FlagField.booleanAfter(IS_DATA);
public static final BooleanFlagField IS_HEADER_CLASS = FlagField.booleanAfter(IS_EXTERNAL_CLASS);
// Constructors
public static final BooleanFlagField IS_SECONDARY = FlagField.booleanAfter(VISIBILITY);
// Callables
public static final FlagField MEMBER_KIND = FlagField.after(MODALITY, ProtoBuf.MemberKind.values());
// Functions
public static final BooleanFlagField IS_OPERATOR = FlagField.booleanAfter(MEMBER_KIND);
public static final BooleanFlagField IS_INFIX = FlagField.booleanAfter(IS_OPERATOR);
public static final BooleanFlagField IS_INLINE = FlagField.booleanAfter(IS_INFIX);
public static final BooleanFlagField IS_TAILREC = FlagField.booleanAfter(IS_INLINE);
public static final BooleanFlagField IS_EXTERNAL_FUNCTION = FlagField.booleanAfter(IS_TAILREC);
public static final BooleanFlagField IS_SUSPEND = FlagField.booleanAfter(IS_EXTERNAL_FUNCTION);
public static final BooleanFlagField IS_HEADER_FUNCTION = FlagField.booleanAfter(IS_SUSPEND);
// Properties
public static final BooleanFlagField IS_VAR = FlagField.booleanAfter(MEMBER_KIND);
public static final BooleanFlagField HAS_GETTER = FlagField.booleanAfter(IS_VAR);
public static final BooleanFlagField HAS_SETTER = FlagField.booleanAfter(HAS_GETTER);
public static final BooleanFlagField IS_CONST = FlagField.booleanAfter(HAS_SETTER);
public static final BooleanFlagField IS_LATEINIT = FlagField.booleanAfter(IS_CONST);
public static final BooleanFlagField HAS_CONSTANT = FlagField.booleanAfter(IS_LATEINIT);
public static final BooleanFlagField IS_EXTERNAL_PROPERTY = FlagField.booleanAfter(HAS_CONSTANT);
public static final BooleanFlagField IS_DELEGATED = FlagField.booleanAfter(IS_EXTERNAL_PROPERTY);
public static final BooleanFlagField IS_HEADER_PROPERTY = FlagField.booleanAfter(IS_DELEGATED);
// Parameters
public static final BooleanFlagField DECLARES_DEFAULT_VALUE = FlagField.booleanAfter(HAS_ANNOTATIONS);
public static final BooleanFlagField IS_CROSSINLINE = FlagField.booleanAfter(DECLARES_DEFAULT_VALUE);
public static final BooleanFlagField IS_NOINLINE = FlagField.booleanAfter(IS_CROSSINLINE);
// Accessors
public static final BooleanFlagField IS_NOT_DEFAULT = FlagField.booleanAfter(MODALITY);
public static final BooleanFlagField IS_EXTERNAL_ACCESSOR = FlagField.booleanAfter(IS_NOT_DEFAULT);
public static final BooleanFlagField IS_INLINE_ACCESSOR = FlagField.booleanAfter(IS_EXTERNAL_ACCESSOR);
// ---
public static int getTypeFlags(boolean isSuspend) {
return SUSPEND_TYPE.toFlags(isSuspend);
}
public static int getClassFlags(
boolean hasAnnotations,
Visibility visibility,
Modality modality,
ClassKind kind,
boolean inner,
boolean isCompanionObject,
boolean isData,
boolean isExternal,
boolean isHeader
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| MODALITY.toFlags(modality(modality))
| VISIBILITY.toFlags(visibility(visibility))
| CLASS_KIND.toFlags(classKind(kind, isCompanionObject))
| IS_INNER.toFlags(inner)
| IS_DATA.toFlags(isData)
| IS_EXTERNAL_CLASS.toFlags(isExternal)
| IS_HEADER_CLASS.toFlags(isHeader)
;
}
private static ProtoBuf.Class.Kind classKind(ClassKind kind, boolean isCompanionObject) {
if (isCompanionObject) return ProtoBuf.Class.Kind.COMPANION_OBJECT;
switch (kind) {
case CLASS:
return ProtoBuf.Class.Kind.CLASS;
case INTERFACE:
return ProtoBuf.Class.Kind.INTERFACE;
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;
}
throw new IllegalArgumentException("Unknown class kind: " + kind);
}
public static int getConstructorFlags(
boolean hasAnnotations,
@NotNull Visibility visibility,
boolean isSecondary
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| VISIBILITY.toFlags(visibility(visibility))
| IS_SECONDARY.toFlags(isSecondary)
;
}
public static int getFunctionFlags(
boolean hasAnnotations,
@NotNull Visibility visibility,
@NotNull Modality modality,
@NotNull CallableMemberDescriptor.Kind memberKind,
boolean isOperator,
boolean isInfix,
boolean isInline,
boolean isTailrec,
boolean isExternal,
boolean isSuspend,
boolean isHeader
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| VISIBILITY.toFlags(visibility(visibility))
| MODALITY.toFlags(modality(modality))
| MEMBER_KIND.toFlags(memberKind(memberKind))
| IS_OPERATOR.toFlags(isOperator)
| IS_INFIX.toFlags(isInfix)
| IS_INLINE.toFlags(isInline)
| IS_TAILREC.toFlags(isTailrec)
| IS_EXTERNAL_FUNCTION.toFlags(isExternal)
| IS_SUSPEND.toFlags(isSuspend)
| IS_HEADER_FUNCTION.toFlags(isHeader)
;
}
public static int getPropertyFlags(
boolean hasAnnotations,
@NotNull Visibility visibility,
@NotNull Modality modality,
@NotNull CallableMemberDescriptor.Kind memberKind,
boolean isVar,
boolean hasGetter,
boolean hasSetter,
boolean hasConstant,
boolean isConst,
boolean lateInit,
boolean isExternal,
boolean isDelegated,
boolean isHeader
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| VISIBILITY.toFlags(visibility(visibility))
| MODALITY.toFlags(modality(modality))
| MEMBER_KIND.toFlags(memberKind(memberKind))
| IS_VAR.toFlags(isVar)
| HAS_GETTER.toFlags(hasGetter)
| HAS_SETTER.toFlags(hasSetter)
| IS_CONST.toFlags(isConst)
| IS_LATEINIT.toFlags(lateInit)
| HAS_CONSTANT.toFlags(hasConstant)
| IS_EXTERNAL_PROPERTY.toFlags(isExternal)
| IS_DELEGATED.toFlags(isDelegated)
| IS_HEADER_PROPERTY.toFlags(isHeader)
;
}
public static int getAccessorFlags(
boolean hasAnnotations,
@NotNull Visibility visibility,
@NotNull Modality modality,
boolean isNotDefault,
boolean isExternal,
boolean isInlineAccessor
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| MODALITY.toFlags(modality(modality))
| VISIBILITY.toFlags(visibility(visibility))
| IS_NOT_DEFAULT.toFlags(isNotDefault)
| IS_EXTERNAL_ACCESSOR.toFlags(isExternal)
| IS_INLINE_ACCESSOR.toFlags(isInlineAccessor)
;
}
@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.PRIVATE_TO_THIS) {
return ProtoBuf.Visibility.PRIVATE_TO_THIS;
}
else if (visibility == Visibilities.PROTECTED) {
return ProtoBuf.Visibility.PROTECTED;
}
else if (visibility == Visibilities.LOCAL) {
return ProtoBuf.Visibility.LOCAL;
}
throw new IllegalArgumentException("Unknown visibility: " + visibility);
}
@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;
case SEALED:
return ProtoBuf.Modality.SEALED;
}
throw new IllegalArgumentException("Unknown modality: " + modality);
}
@NotNull
private static ProtoBuf.MemberKind memberKind(@NotNull CallableMemberDescriptor.Kind kind) {
switch (kind) {
case DECLARATION:
return ProtoBuf.MemberKind.DECLARATION;
case FAKE_OVERRIDE:
return ProtoBuf.MemberKind.FAKE_OVERRIDE;
case DELEGATION:
return ProtoBuf.MemberKind.DELEGATION;
case SYNTHESIZED:
return ProtoBuf.MemberKind.SYNTHESIZED;
}
throw new IllegalArgumentException("Unknown member kind: " + kind);
}
public static int getValueParameterFlags(
boolean hasAnnotations,
boolean declaresDefaultValue,
boolean isCrossinline,
boolean isNoinline
) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| DECLARES_DEFAULT_VALUE.toFlags(declaresDefaultValue)
| IS_CROSSINLINE.toFlags(isCrossinline)
| IS_NOINLINE.toFlags(isNoinline)
;
}
public static int getTypeAliasFlags(boolean hasAnnotations, Visibility visibility) {
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
| VISIBILITY.toFlags(visibility(visibility))
;
}
// Infrastructure
public static abstract class FlagField {
public static FlagField after(FlagField> previousField, E[] values) {
int offset = previousField.offset + previousField.bitWidth;
return new EnumLiteFlagField(offset, values);
}
public static FlagField first(E[] values) {
return new EnumLiteFlagField(0, values);
}
public static BooleanFlagField booleanFirst() {
return new BooleanFlagField(0);
}
public static BooleanFlagField booleanAfter(FlagField> previousField) {
int offset = previousField.offset + previousField.bitWidth;
return new BooleanFlagField(offset);
}
protected final int offset;
protected final int bitWidth;
private FlagField(int offset, int bitWidth) {
this.offset = offset;
this.bitWidth = bitWidth;
}
public abstract E get(int flags);
public abstract int toFlags(E value);
}
@SuppressWarnings("WeakerAccess")
public static class BooleanFlagField extends FlagField {
public BooleanFlagField(int offset) {
super(offset, 1);
}
@Override
@NotNull
public Boolean get(int flags) {
return (flags & (1 << offset)) != 0;
}
@Override
public int toFlags(Boolean value) {
return value ? 1 << offset : 0;
}
}
private static class EnumLiteFlagField extends FlagField {
private final E[] values;
public EnumLiteFlagField(int offset, E[] values) {
super(offset, bitWidth(values));
this.values = values;
}
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());
}
@Override
@Nullable
public E get(int flags) {
int maskUnshifted = (1 << bitWidth) - 1;
int mask = maskUnshifted << offset;
int value = (flags & mask) >> offset;
for (E e : values) {
if (e.getNumber() == value) {
return e;
}
}
return null;
}
@Override
public int toFlags(E value) {
return value.getNumber() << offset;
}
}
}