From 1a1cbcb32100c11e61d05e531765cbc24b9aea86 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Fri, 24 Mar 2023 20:50:57 +0100 Subject: [PATCH] Rework flags in kotlinx.metadata: Introduce extensions for KmNodes to work with various modifiers instead of old Flags.SOMETHING.invoke(flags). Provide Visibility, Modality, and Kind enums. Introduce KmPropertyAccessorAttributes to replace KmProperty.getterFlags and KmProperty.setterFlags. Deprecate nodes constructors which take flags but not flags itself (yet). Adapt KotlinP to changes. #KT-59440 Fixed --- .../interop/gen/StubIrMetadataEmitter.kt | 34 +- .../jvm/api/kotlinx-metadata-jvm.api | 183 +++++++++ .../src/kotlinx/metadata/jvm/JvmAttributes.kt | 40 ++ .../jvm/src/kotlinx/metadata/jvm/JvmFlag.kt | 2 +- .../jvm/internal/JvmExtensionNodes.kt | 6 +- .../metadata/test/FlagDelegatesTest.kt | 162 ++++++++ .../metadata/test/MetadataSmokeTest.kt | 13 +- .../src/kotlinx/metadata/Attributes.kt | 379 ++++++++++++++++++ .../src/kotlinx/metadata/Flag.kt | 41 +- .../src/kotlinx/metadata/Modifiers.kt | 185 +++++++++ .../src/kotlinx/metadata/Nodes.kt | 133 +++++- .../metadata/internal/FlagDelegatesImpl.kt | 74 ++++ .../src/kotlinx/metadata/internal/Readers.kt | 2 +- .../org/jetbrains/kotlin/kotlinp/printers.kt | 237 +++++------ .../commonizer/metadata/CirDeserializers.kt | 3 + .../commonizer/metadata/CirSerializers.kt | 31 +- .../kotlin/commonizer/metadata/flags.kt | 26 +- 17 files changed, 1344 insertions(+), 207 deletions(-) create mode 100644 libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt create mode 100644 libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt create mode 100644 libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt create mode 100644 libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt create mode 100644 libraries/kotlinx-metadata/src/kotlinx/metadata/internal/FlagDelegatesImpl.kt diff --git a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt index 6112a9105dd..fbd8057033e 100644 --- a/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt +++ b/kotlin-native/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -140,7 +140,8 @@ internal class ModuleMetadataEmitter( override fun visitTypealias(element: TypealiasStub, data: VisitingContext): KmTypeAlias = data.withMappingExtensions { - KmTypeAlias(element.flags, element.alias.topLevelName).also { km -> + KmTypeAlias(element.alias.topLevelName).also { km -> + km.flags = element.flags km.underlyingType = element.aliasee.map(shouldExpandTypeAliases = false) km.expandedType = element.aliasee.map() } @@ -156,7 +157,8 @@ internal class ModuleMetadataEmitter( annotations = listOf(AnnotationStub.Deprecated.unableToImport) ) } - KmFunction(function.flags, function.name).also { km -> + KmFunction(function.name).also { km -> + km.flags = function.flags km.receiverParameterType = function.receiver?.type?.map() function.typeParameters.mapTo(km.typeParameters) { it.map() } function.parameters.mapTo(km.valueParameters) { it.map() } @@ -176,7 +178,10 @@ internal class ModuleMetadataEmitter( else -> element.copy(kind = bridgeSupportedKind) } val name = getPropertyNameInScope(property, data.container) - KmProperty(property.flags, name, property.getterFlags, property.setterFlags).also { km -> + KmProperty(name).also { km -> + km.flags = property.flags + km.getterFlags = property.getterFlags + km.setterFlags = property.setterFlags property.annotations.mapTo(km.annotations) { it.map() } km.receiverParameterType = property.receiverType?.map() km.returnType = property.type.map() @@ -199,7 +204,8 @@ internal class ModuleMetadataEmitter( override fun visitConstructor(constructorStub: ConstructorStub, data: VisitingContext) = data.withMappingExtensions { - KmConstructor(constructorStub.flags).apply { + KmConstructor().apply { + flags = constructorStub.flags constructorStub.parameters.mapTo(valueParameters, { it.map() }) constructorStub.annotations.mapTo(annotations, { it.map() }) } @@ -483,12 +489,14 @@ private class MappingExtensions( is AbbreviatedType -> { val typeAliasClassifier = KmClassifier.TypeAlias(abbreviatedClassifier.fqNameSerialized) val typeArguments = typeArguments.map { it.map(shouldExpandTypeAliases) } - val abbreviatedType = KmType(flags).also { km -> + val abbreviatedType = KmType().also { km -> + km.flags = flags km.classifier = typeAliasClassifier km.arguments += typeArguments } if (shouldExpandTypeAliases) { - KmType(expandedTypeFlags).also { km -> + KmType().also { km -> + km.flags = expandedTypeFlags km.abbreviatedType = abbreviatedType val kmUnderlyingType = underlyingType.map(true) km.arguments += kmUnderlyingType.arguments @@ -498,21 +506,25 @@ private class MappingExtensions( abbreviatedType } } - is ClassifierStubType -> KmType(flags).also { km -> + is ClassifierStubType -> KmType().also { km -> + km.flags = flags typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } km.classifier = KmClassifier.Class(classifier.fqNameSerialized) } - is FunctionalType -> KmType(flags).also { km -> + is FunctionalType -> KmType().also { km -> + km.flags = flags typeArguments.mapTo(km.arguments) { it.map(shouldExpandTypeAliases) } km.classifier = KmClassifier.Class(classifier.fqNameSerialized) } - is TypeParameterType -> KmType(flags).also { km -> + is TypeParameterType -> KmType().also { km -> + km.flags = flags km.classifier = KmClassifier.TypeParameter(id) } } fun FunctionParameterStub.map(): KmValueParameter = - KmValueParameter(flags, name).also { km -> + KmValueParameter(name).also { km -> + km.flags = flags val kmType = type.map() if (isVararg) { km.varargElementType = kmType @@ -527,7 +539,7 @@ private class MappingExtensions( } fun TypeParameterStub.map(): KmTypeParameter = - KmTypeParameter(flagsOf(), name, id, KmVariance.INVARIANT).also { km -> + KmTypeParameter(name, id, KmVariance.INVARIANT).also { km -> km.upperBounds.addIfNotNull(upperBound?.map()) } diff --git a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api index 63b17ad3577..c9334c339d7 100644 --- a/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api +++ b/libraries/kotlinx-metadata/jvm/api/kotlinx-metadata-jvm.api @@ -1,3 +1,131 @@ +public final class kotlinx/metadata/Attributes { + public static final fun getDeclaresDefaultValue (Lkotlinx/metadata/KmValueParameter;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmClass;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmConstructor;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmFunction;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmProperty;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmTypeAlias;)Z + public static final fun getHasAnnotations (Lkotlinx/metadata/KmValueParameter;)Z + public static final fun getHasConstant (Lkotlinx/metadata/KmProperty;)Z + public static final fun getHasEnumEntries (Lkotlinx/metadata/KmClass;)Z + public static final fun getHasGetter (Lkotlinx/metadata/KmProperty;)Z + public static final fun getHasNonStableParameterNames (Lkotlinx/metadata/KmConstructor;)Z + public static final fun getHasNonStableParameterNames (Lkotlinx/metadata/KmFunction;)Z + public static final fun getHasSetter (Lkotlinx/metadata/KmProperty;)Z + public static final fun getKind (Lkotlinx/metadata/KmClass;)Lkotlinx/metadata/ClassKind; + public static final fun getKind (Lkotlinx/metadata/KmFunction;)Lkotlinx/metadata/MemberKind; + public static final fun getKind (Lkotlinx/metadata/KmProperty;)Lkotlinx/metadata/MemberKind; + public static final fun getModality (Lkotlinx/metadata/KmClass;)Lkotlinx/metadata/Modality; + public static final fun getModality (Lkotlinx/metadata/KmFunction;)Lkotlinx/metadata/Modality; + public static final fun getModality (Lkotlinx/metadata/KmProperty;)Lkotlinx/metadata/Modality; + public static final fun getModality (Lkotlinx/metadata/KmPropertyAccessorAttributes;)Lkotlinx/metadata/Modality; + public static final fun getVisibility (Lkotlinx/metadata/KmClass;)Lkotlinx/metadata/Visibility; + public static final fun getVisibility (Lkotlinx/metadata/KmConstructor;)Lkotlinx/metadata/Visibility; + public static final fun getVisibility (Lkotlinx/metadata/KmFunction;)Lkotlinx/metadata/Visibility; + public static final fun getVisibility (Lkotlinx/metadata/KmProperty;)Lkotlinx/metadata/Visibility; + public static final fun getVisibility (Lkotlinx/metadata/KmPropertyAccessorAttributes;)Lkotlinx/metadata/Visibility; + public static final fun getVisibility (Lkotlinx/metadata/KmTypeAlias;)Lkotlinx/metadata/Visibility; + public static final fun isConst (Lkotlinx/metadata/KmProperty;)Z + public static final fun isCrossinline (Lkotlinx/metadata/KmValueParameter;)Z + public static final fun isData (Lkotlinx/metadata/KmClass;)Z + public static final fun isDefinitelyNonNull (Lkotlinx/metadata/KmType;)Z + public static final fun isDelegated (Lkotlinx/metadata/KmProperty;)Z + public static final fun isExpect (Lkotlinx/metadata/KmClass;)Z + public static final fun isExpect (Lkotlinx/metadata/KmFunction;)Z + public static final fun isExpect (Lkotlinx/metadata/KmProperty;)Z + public static final fun isExternal (Lkotlinx/metadata/KmClass;)Z + public static final fun isExternal (Lkotlinx/metadata/KmFunction;)Z + public static final fun isExternal (Lkotlinx/metadata/KmProperty;)Z + public static final fun isExternal (Lkotlinx/metadata/KmPropertyAccessorAttributes;)Z + public static final fun isFunInterface (Lkotlinx/metadata/KmClass;)Z + public static final fun isInfix (Lkotlinx/metadata/KmFunction;)Z + public static final fun isInline (Lkotlinx/metadata/KmFunction;)Z + public static final fun isInline (Lkotlinx/metadata/KmPropertyAccessorAttributes;)Z + public static final fun isInner (Lkotlinx/metadata/KmClass;)Z + public static final fun isLateinit (Lkotlinx/metadata/KmProperty;)Z + public static final fun isNegated (Lkotlinx/metadata/KmEffectExpression;)Z + public static final fun isNoinline (Lkotlinx/metadata/KmValueParameter;)Z + public static final fun isNotDefault (Lkotlinx/metadata/KmPropertyAccessorAttributes;)Z + public static final fun isNullCheckPredicate (Lkotlinx/metadata/KmEffectExpression;)Z + public static final fun isNullable (Lkotlinx/metadata/KmType;)Z + public static final fun isOperator (Lkotlinx/metadata/KmFunction;)Z + public static final fun isReified (Lkotlinx/metadata/KmTypeParameter;)Z + public static final fun isSecondary (Lkotlinx/metadata/KmConstructor;)Z + public static final fun isSuspend (Lkotlinx/metadata/KmFunction;)Z + public static final fun isSuspend (Lkotlinx/metadata/KmType;)Z + public static final fun isTailrec (Lkotlinx/metadata/KmFunction;)Z + public static final fun isValue (Lkotlinx/metadata/KmClass;)Z + public static final fun isVar (Lkotlinx/metadata/KmProperty;)Z + public static final fun setConst (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setCrossinline (Lkotlinx/metadata/KmValueParameter;Z)V + public static final fun setData (Lkotlinx/metadata/KmClass;Z)V + public static final fun setDeclaresDefaultValue (Lkotlinx/metadata/KmValueParameter;Z)V + public static final fun setDefinitelyNonNull (Lkotlinx/metadata/KmType;Z)V + public static final fun setDelegated (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setExpect (Lkotlinx/metadata/KmClass;Z)V + public static final fun setExpect (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setExpect (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setExternal (Lkotlinx/metadata/KmClass;Z)V + public static final fun setExternal (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setExternal (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setFunInterface (Lkotlinx/metadata/KmClass;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmClass;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmConstructor;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmTypeAlias;Z)V + public static final fun setHasAnnotations (Lkotlinx/metadata/KmValueParameter;Z)V + public static final fun setHasConstant (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setHasEnumEntries (Lkotlinx/metadata/KmClass;Z)V + public static final fun setHasGetter (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setHasNonStableParameterNames (Lkotlinx/metadata/KmConstructor;Z)V + public static final fun setHasNonStableParameterNames (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setHasSetter (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setInfix (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setInline (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setInner (Lkotlinx/metadata/KmClass;Z)V + public static final fun setKind (Lkotlinx/metadata/KmClass;Lkotlinx/metadata/ClassKind;)V + public static final fun setKind (Lkotlinx/metadata/KmFunction;Lkotlinx/metadata/MemberKind;)V + public static final fun setKind (Lkotlinx/metadata/KmProperty;Lkotlinx/metadata/MemberKind;)V + public static final fun setLateinit (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setModality (Lkotlinx/metadata/KmClass;Lkotlinx/metadata/Modality;)V + public static final fun setModality (Lkotlinx/metadata/KmFunction;Lkotlinx/metadata/Modality;)V + public static final fun setModality (Lkotlinx/metadata/KmProperty;Lkotlinx/metadata/Modality;)V + public static final fun setModality (Lkotlinx/metadata/KmPropertyAccessorAttributes;Lkotlinx/metadata/Modality;)V + public static final fun setNegated (Lkotlinx/metadata/KmEffectExpression;Z)V + public static final fun setNoinline (Lkotlinx/metadata/KmValueParameter;Z)V + public static final fun setNotDefault (Lkotlinx/metadata/KmPropertyAccessorAttributes;Z)V + public static final fun setNullCheckPredicate (Lkotlinx/metadata/KmEffectExpression;Z)V + public static final fun setNullable (Lkotlinx/metadata/KmType;Z)V + public static final fun setOperator (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setReified (Lkotlinx/metadata/KmTypeParameter;Z)V + public static final fun setSecondary (Lkotlinx/metadata/KmConstructor;Z)V + public static final fun setSuspend (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setSuspend (Lkotlinx/metadata/KmType;Z)V + public static final fun setTailrec (Lkotlinx/metadata/KmFunction;Z)V + public static final fun setValue (Lkotlinx/metadata/KmClass;Z)V + public static final fun setVar (Lkotlinx/metadata/KmProperty;Z)V + public static final fun setVisibility (Lkotlinx/metadata/KmClass;Lkotlinx/metadata/Visibility;)V + public static final fun setVisibility (Lkotlinx/metadata/KmConstructor;Lkotlinx/metadata/Visibility;)V + public static final fun setVisibility (Lkotlinx/metadata/KmFunction;Lkotlinx/metadata/Visibility;)V + public static final fun setVisibility (Lkotlinx/metadata/KmProperty;Lkotlinx/metadata/Visibility;)V + public static final fun setVisibility (Lkotlinx/metadata/KmPropertyAccessorAttributes;Lkotlinx/metadata/Visibility;)V + public static final fun setVisibility (Lkotlinx/metadata/KmTypeAlias;Lkotlinx/metadata/Visibility;)V +} + +public final class kotlinx/metadata/ClassKind : java/lang/Enum { + public static final field ANNOTATION_CLASS Lkotlinx/metadata/ClassKind; + public static final field CLASS Lkotlinx/metadata/ClassKind; + public static final field COMPANION_OBJECT Lkotlinx/metadata/ClassKind; + public static final field ENUM_CLASS Lkotlinx/metadata/ClassKind; + public static final field ENUM_ENTRY Lkotlinx/metadata/ClassKind; + public static final field INTERFACE Lkotlinx/metadata/ClassKind; + public static final field OBJECT Lkotlinx/metadata/ClassKind; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lkotlinx/metadata/ClassKind; + public static fun values ()[Lkotlinx/metadata/ClassKind; +} + public final class kotlinx/metadata/ClassNameKt { public static final fun isLocal (Ljava/lang/String;)Z public static final fun isLocalClassName (Ljava/lang/String;)Z @@ -462,6 +590,7 @@ public final class kotlinx/metadata/KmConstantValue { } public final class kotlinx/metadata/KmConstructor : kotlinx/metadata/KmConstructorVisitor { + public fun ()V public fun (I)V public final fun accept (Lkotlinx/metadata/KmConstructorVisitor;)V public final fun getFlags ()I @@ -623,6 +752,7 @@ public final class kotlinx/metadata/KmFlexibleTypeUpperBound { public final class kotlinx/metadata/KmFunction : kotlinx/metadata/KmFunctionVisitor { public field returnType Lkotlinx/metadata/KmType; public fun (ILjava/lang/String;)V + public fun (Ljava/lang/String;)V public final fun accept (Lkotlinx/metadata/KmFunctionVisitor;)V public final fun getContextReceiverTypes ()Ljava/util/List; public final fun getContract ()Lkotlinx/metadata/KmContract; @@ -713,13 +843,16 @@ public abstract class kotlinx/metadata/KmPackageVisitor : kotlinx/metadata/KmDec public final class kotlinx/metadata/KmProperty : kotlinx/metadata/KmPropertyVisitor { public field returnType Lkotlinx/metadata/KmType; public fun (ILjava/lang/String;II)V + public fun (Ljava/lang/String;)V public final fun accept (Lkotlinx/metadata/KmPropertyVisitor;)V public final fun getContextReceiverTypes ()Ljava/util/List; public final fun getFlags ()I + public final fun getGetter ()Lkotlinx/metadata/KmPropertyAccessorAttributes; public final fun getGetterFlags ()I public final fun getName ()Ljava/lang/String; public final fun getReceiverParameterType ()Lkotlinx/metadata/KmType; public final fun getReturnType ()Lkotlinx/metadata/KmType; + public final fun getSetter ()Lkotlinx/metadata/KmPropertyAccessorAttributes; public final fun getSetterFlags ()I public final fun getSetterParameter ()Lkotlinx/metadata/KmValueParameter; public final fun getTypeParameters ()Ljava/util/List; @@ -729,6 +862,7 @@ public final class kotlinx/metadata/KmProperty : kotlinx/metadata/KmPropertyVisi public final fun setName (Ljava/lang/String;)V public final fun setReceiverParameterType (Lkotlinx/metadata/KmType;)V public final fun setReturnType (Lkotlinx/metadata/KmType;)V + public final fun setSetter (Lkotlinx/metadata/KmPropertyAccessorAttributes;)V public final fun setSetterFlags (I)V public final fun setSetterParameter (Lkotlinx/metadata/KmValueParameter;)V public fun visitContextReceiverType (I)Lkotlinx/metadata/KmTypeVisitor; @@ -740,6 +874,10 @@ public final class kotlinx/metadata/KmProperty : kotlinx/metadata/KmPropertyVisi public fun visitVersionRequirement ()Lkotlinx/metadata/KmVersionRequirementVisitor; } +public final class kotlinx/metadata/KmPropertyAccessorAttributes { + public fun ()V +} + public abstract interface class kotlinx/metadata/KmPropertyExtensionVisitor : kotlinx/metadata/KmExtensionVisitor { } @@ -759,6 +897,7 @@ public abstract class kotlinx/metadata/KmPropertyVisitor { public final class kotlinx/metadata/KmType : kotlinx/metadata/KmTypeVisitor { public field classifier Lkotlinx/metadata/KmClassifier; + public fun ()V public fun (I)V public final fun accept (Lkotlinx/metadata/KmTypeVisitor;)V public final fun getAbbreviatedType ()Lkotlinx/metadata/KmType; @@ -787,6 +926,7 @@ public final class kotlinx/metadata/KmTypeAlias : kotlinx/metadata/KmTypeAliasVi public field expandedType Lkotlinx/metadata/KmType; public field underlyingType Lkotlinx/metadata/KmType; public fun (ILjava/lang/String;)V + public fun (Ljava/lang/String;)V public final fun accept (Lkotlinx/metadata/KmTypeAliasVisitor;)V public final fun getAnnotations ()Ljava/util/List; public final fun getExpandedType ()Lkotlinx/metadata/KmType; @@ -828,6 +968,7 @@ public abstract interface class kotlinx/metadata/KmTypeExtensionVisitor : kotlin public final class kotlinx/metadata/KmTypeParameter : kotlinx/metadata/KmTypeParameterVisitor { public fun (ILjava/lang/String;ILkotlinx/metadata/KmVariance;)V + public fun (Ljava/lang/String;ILkotlinx/metadata/KmVariance;)V public final fun accept (Lkotlinx/metadata/KmTypeParameterVisitor;)V public final fun getFlags ()I public final fun getId ()I @@ -893,6 +1034,7 @@ public abstract class kotlinx/metadata/KmTypeVisitor { public final class kotlinx/metadata/KmValueParameter : kotlinx/metadata/KmValueParameterVisitor { public field type Lkotlinx/metadata/KmType; public fun (ILjava/lang/String;)V + public fun (Ljava/lang/String;)V public final fun accept (Lkotlinx/metadata/KmValueParameterVisitor;)V public final fun getFlags ()I public final fun getName ()Ljava/lang/String; @@ -991,6 +1133,47 @@ public abstract class kotlinx/metadata/KmVersionRequirementVisitor { public fun visitVersion (III)V } +public final class kotlinx/metadata/MemberKind : java/lang/Enum { + public static final field DECLARATION Lkotlinx/metadata/MemberKind; + public static final field DELEGATION Lkotlinx/metadata/MemberKind; + public static final field FAKE_OVERRIDE Lkotlinx/metadata/MemberKind; + public static final field SYNTHESIZED Lkotlinx/metadata/MemberKind; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lkotlinx/metadata/MemberKind; + public static fun values ()[Lkotlinx/metadata/MemberKind; +} + +public final class kotlinx/metadata/Modality : java/lang/Enum { + public static final field ABSTRACT Lkotlinx/metadata/Modality; + public static final field FINAL Lkotlinx/metadata/Modality; + public static final field OPEN Lkotlinx/metadata/Modality; + public static final field SEALED Lkotlinx/metadata/Modality; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lkotlinx/metadata/Modality; + public static fun values ()[Lkotlinx/metadata/Modality; +} + +public final class kotlinx/metadata/Visibility : java/lang/Enum { + public static final field INTERNAL Lkotlinx/metadata/Visibility; + public static final field LOCAL Lkotlinx/metadata/Visibility; + public static final field PRIVATE Lkotlinx/metadata/Visibility; + public static final field PRIVATE_TO_THIS Lkotlinx/metadata/Visibility; + public static final field PROTECTED Lkotlinx/metadata/Visibility; + public static final field PUBLIC Lkotlinx/metadata/Visibility; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lkotlinx/metadata/Visibility; + public static fun values ()[Lkotlinx/metadata/Visibility; +} + +public final class kotlinx/metadata/jvm/JvmAttributes { + public static final fun getHasMethodBodiesInInterface (Lkotlinx/metadata/KmClass;)Z + public static final fun isCompiledInCompatibilityMode (Lkotlinx/metadata/KmClass;)Z + public static final fun isMovedFromInterfaceCompanion (Lkotlinx/metadata/KmProperty;)Z + public static final fun setCompiledInCompatibilityMode (Lkotlinx/metadata/KmClass;Z)V + public static final fun setHasMethodBodiesInInterface (Lkotlinx/metadata/KmClass;Z)V + public static final fun setMovedFromInterfaceCompanion (Lkotlinx/metadata/KmProperty;Z)V +} + public class kotlinx/metadata/jvm/JvmClassExtensionVisitor : kotlinx/metadata/jvm/JvmDeclarationContainerExtensionVisitor, kotlinx/metadata/KmClassExtensionVisitor { public static final field Companion Lkotlinx/metadata/jvm/JvmClassExtensionVisitor$Companion; public static final field TYPE Lkotlinx/metadata/KmExtensionType; diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt new file mode 100644 index 00000000000..24dfd37c18a --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:JvmName("JvmAttributes") + +package kotlinx.metadata.jvm + +import kotlinx.metadata.KmClass +import kotlinx.metadata.KmProperty +import kotlinx.metadata.internal.BooleanFlagDelegate +import kotlinx.metadata.jvm.JvmFlag.booleanFlag +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmFlags as JF + +/** + * Applied to a property declared in an interface's companion object, signifies that its backing field is declared as a static + * field in the interface. In Kotlin code, this usually happens if the property is annotated with [JvmField]. + * + * Has no effect if the property is not declared in a companion object of some interface. + */ +var KmProperty.isMovedFromInterfaceCompanion by BooleanFlagDelegate(KmProperty::jvmFlags, booleanFlag(JF.IS_MOVED_FROM_INTERFACE_COMPANION)) + +/** + * Applied to an interface compiled with -Xjvm-default=all or all-compatibility. + * + * Without this flag or a `@JvmDefault` annotation on individual interface methods + * the Kotlin compiler moves all interface method bodies into a nested `DefaultImpls` + * class. + */ +var KmClass.hasMethodBodiesInInterface by BooleanFlagDelegate(KmClass::jvmFlags, booleanFlag(JF.IS_COMPILED_IN_JVM_DEFAULT_MODE)) + +/** + * Applied to an interface compiled with -Xjvm-default=all-compatibility. + * + * In compatibility mode we generate method bodies directly in the interface, + * but we also generate bridges in a nested `DefaultImpls` class for use by + * clients compiled without all-compatibility. + */ +var KmClass.isCompiledInCompatibilityMode by BooleanFlagDelegate(KmClass::jvmFlags, booleanFlag(JF.IS_COMPILED_IN_COMPATIBILITY_MODE)) diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt index e560df79bd9..fd3561a097c 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt @@ -56,6 +56,6 @@ object JvmFlag { val IS_COMPILED_IN_COMPATIBILITY_MODE = booleanFlag(JF.IS_COMPILED_IN_COMPATIBILITY_MODE) } - private fun booleanFlag(f: F.BooleanFlagField): Flag = + internal fun booleanFlag(f: F.BooleanFlagField): Flag = Flag(f.offset, f.bitWidth, 1) } diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmExtensionNodes.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmExtensionNodes.kt index 1aa52d7ab5c..095146c2edf 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmExtensionNodes.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/internal/JvmExtensionNodes.kt @@ -56,7 +56,8 @@ internal class JvmClassExtension : JvmClassExtensionVisitor(), KmClassExtension override fun accept(visitor: KmClassExtensionVisitor) { require(visitor is JvmClassExtensionVisitor) localDelegatedProperties.forEach { - visitor.visitLocalDelegatedProperty(it.flags, it.name, it.getterFlags, it.setterFlags)?.let(it::accept) + @Suppress("INVISIBLE_MEMBER") // getter.flags + visitor.visitLocalDelegatedProperty(it.flags, it.name, it.getter.flags, it.setterFlags)?.let(it::accept) } moduleName?.let(visitor::visitModuleName) anonymousObjectOriginName?.let(visitor::visitAnonymousObjectOriginName) @@ -79,7 +80,8 @@ internal class JvmPackageExtension : JvmPackageExtensionVisitor(), KmPackageExte override fun accept(visitor: KmPackageExtensionVisitor) { require(visitor is JvmPackageExtensionVisitor) localDelegatedProperties.forEach { - visitor.visitLocalDelegatedProperty(it.flags, it.name, it.getterFlags, it.setterFlags)?.let(it::accept) + @Suppress("INVISIBLE_MEMBER") // getter.flags + visitor.visitLocalDelegatedProperty(it.flags, it.name, it.getter.flags, it.setterFlags)?.let(it::accept) } moduleName?.let(visitor::visitModuleName) visitor.visitEnd() diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt new file mode 100644 index 00000000000..8fb33cc0dd0 --- /dev/null +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlinx.metadata.test + +import kotlinx.metadata.* +import org.junit.Test +import kotlin.reflect.KMutableProperty0 +import kotlin.test.* + +class FlagDelegatesTest { + private class Private + + public class Public { + public fun f(): String = "" + } + + @Test + fun testVisibilityFlags() { + val p1 = Private::class.java.readMetadataAsKmClass() + val p2 = Public::class.java.readMetadataAsKmClass() + + assertEquals(Visibility.PRIVATE, p1.visibility) + assertEquals(Visibility.PUBLIC, p2.visibility) + + assertTrue(Flag.IS_PRIVATE(p1.flags)) + assertTrue(Flag.IS_PUBLIC(p2.flags)) + + p1.visibility = Visibility.PUBLIC + p2.visibility = Visibility.INTERNAL + + assertFalse(Flag.IS_PRIVATE(p1.flags)) + assertFalse(Flag.IS_PUBLIC(p2.flags)) + + assertTrue(Flag.IS_PUBLIC(p1.flags)) + assertTrue(Flag.IS_INTERNAL(p2.flags)) + + val f = assertNotNull(p2.functions.find { it.name == "f" }) + assertEquals(Visibility.PUBLIC, f.visibility) + f.visibility = Visibility.PRIVATE + assertFalse(Flag.IS_PUBLIC(f.flags)) + assertTrue(Flag.IS_PRIVATE(f.flags)) + } + + @Test + fun testBooleanFlags() { + val klass = Public::class.java.readMetadataAsKmClass() + fun doTest(prop: KMutableProperty0, flags: () -> Flags, rawFlag: Flag) { + assertFalse(prop.get()) + assertFalse(rawFlag(flags())) + + prop.set(true) + + assertTrue(prop.get()) + assertTrue(rawFlag(flags())) + } + + + doTest(klass::isData, klass::flags, Flag.Class.IS_DATA) + val f = klass.functions.single { it.name == "f" } + doTest(f::isOperator, f::flags, Flag.Function.IS_OPERATOR) + val rt = f.returnType + doTest(rt::isNullable, rt::flags, Flag.Type.IS_NULLABLE) + } + + @Suppress("UNUSED_PARAMETER") + class PropertiesContainer { + val defaultVal: String = "" + + var defaultVar: String = "" + + val getterVal: String get() = "foo" + + var getterSetterFieldVar: String = "" + get() = field + "a" + set(param) { + field = param + "b" + } + + var getterSetterNoFieldVar: String + get() = "" + set(param) { + // no + } + + var getterSetterNoFieldNoParamVar: String + get() = "" + set(_) { + // no + } + + var defaultSetterVar: String = "" + get() = "foo" + + var defaultGetterVar: String = "" + set(param) { + field = param.takeLast(0) + } + + var noinlineModifierVar: String = "" + set(noinline param) { + field = param.takeLast(0) + } + + } + + @Test + fun testPropertyAccessors() { + val klass = PropertiesContainer::class.java.readMetadataAsKmClass() + val propMap = klass.properties.associateBy { it.name } + + fun assertProperty( + name: String, + isVarProp: Boolean, + getterNotDefault: Boolean, + setterNotDefault: Boolean?, + setterParamCheck: (KmValueParameter?) -> Unit = { assertNull(it, "Should not be a setter parameter for $name") }, + ) { + with(propMap.getValue(name)) { + assertEquals(listOf(isVarProp, true, isVarProp), listOf(isVar, hasGetter, hasSetter), "for $name") + assertEquals(visibility, getter.visibility, "for $name") + assertEquals(getterNotDefault, getter.isNotDefault, "for $name") + + assertEquals(isVarProp, setter != null, "for $name") + assertEquals(setterNotDefault, setter?.isNotDefault, "for $name") + assertEquals(if (isVarProp) visibility else null, setter?.visibility, "for $name") + + setterParamCheck(setterParameter) + } + } + + assertProperty("defaultVal", false, false, null) + assertProperty("defaultVar", true, false, false) + assertProperty("getterVal", false, true, null) + + assertProperty("getterSetterFieldVar", true, true, true) { + assertEquals("param", it?.name) + } + + // Same as with field + assertProperty("getterSetterNoFieldVar", true, true, true) { + assertEquals("param", it?.name) + } + + assertProperty("getterSetterNoFieldNoParamVar", true, true, true) { + assertEquals(true, it?.name?.contains("anonymous parameter")) + } + + assertProperty("defaultSetterVar", true, true, false) + assertProperty("defaultGetterVar", true, false, true) { + assertEquals("param", it?.name) + } + + assertProperty("noinlineModifierVar", true, false, true) { + assertEquals("param", it?.name) + assertEquals(true, it?.isNoinline) + } + + } +} diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt index 6e5c0737b8b..56a938679dd 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/MetadataSmokeTest.kt @@ -49,10 +49,13 @@ class MetadataSmokeTest { val klass = KmClass().apply { name = "Hello" flags = flagsOf(Flag.IS_PUBLIC) - constructors += KmConstructor(flagsOf(Flag.IS_PUBLIC)).apply { + constructors += KmConstructor().apply { + visibility = Visibility.PUBLIC signature = JvmMethodSignature("", "()V") } - functions += KmFunction(flagsOf(Flag.IS_PUBLIC, Flag.Function.IS_DECLARATION), "hello").apply { + functions += KmFunction("hello").apply { + visibility = Visibility.PUBLIC + kind = MemberKind.DECLARATION returnType = KmType(flagsOf()).apply { classifier = KmClassifier.Class("kotlin/String") } @@ -166,6 +169,9 @@ class MetadataSmokeTest { classWithStableParameterNames.constructors.forEach { assertFalse(Flag.Constructor.HAS_NON_STABLE_PARAMETER_NAMES(it.flags)) } classWithStableParameterNames.functions.forEach { assertFalse(Flag.Function.HAS_NON_STABLE_PARAMETER_NAMES(it.flags)) } + classWithStableParameterNames.constructors.forEach { assertFalse(it.hasNonStableParameterNames) } + classWithStableParameterNames.functions.forEach { assertFalse(it.hasNonStableParameterNames) } + val newMetadata = KotlinClassMetadata.writeClass( KmClass().apply { classWithStableParameterNames.accept( @@ -184,6 +190,9 @@ class MetadataSmokeTest { classWithUnstableParameterNames.constructors.forEach { assertTrue(Flag.Constructor.HAS_NON_STABLE_PARAMETER_NAMES(it.flags)) } classWithUnstableParameterNames.functions.forEach { assertTrue(Flag.Function.HAS_NON_STABLE_PARAMETER_NAMES(it.flags)) } + + classWithUnstableParameterNames.constructors.forEach { assertTrue(it.hasNonStableParameterNames) } + classWithUnstableParameterNames.functions.forEach { assertTrue(it.hasNonStableParameterNames) } } @Test diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt new file mode 100644 index 00000000000..57d2edda853 --- /dev/null +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt @@ -0,0 +1,379 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:OptIn(ExperimentalStdlibApi::class) +@file:JvmName("Attributes") + +package kotlinx.metadata + +import kotlinx.metadata.internal.* +import kotlinx.metadata.internal.BooleanFlagDelegate +import kotlinx.metadata.internal.EnumFlagDelegate +import kotlinx.metadata.internal.classBooleanFlag +import kotlinx.metadata.internal.constructorBooleanFlag +import kotlin.contracts.ExperimentalContracts +import org.jetbrains.kotlin.metadata.deserialization.Flags as ProtoFlags + +// --- ANNOTATIONS --- + +/** + * Signifies that the corresponding class has at least one annotation. + * + * This flag is useful for reading Kotlin metadata on JVM efficiently. On JVM, most of the annotations are written not to the Kotlin + * metadata, but directly on the corresponding declarations in the class file. This flag can be used as an optimization to avoid + * reading annotations from the class file (which can be slow) in case when a class has no annotations. + */ +var KmClass.hasAnnotations by annotationsOn(KmClass::flags) + +/** + * Signifies that the corresponding constructor has at least one annotation. + * + * This flag is useful for reading Kotlin metadata on JVM efficiently. On JVM, most of the annotations are written not to the Kotlin + * metadata, but directly on the corresponding declarations in the class file. This flag can be used as an optimization to avoid + * reading annotations from the class file (which can be slow) in case when a constructor has no annotations. + */ +var KmConstructor.hasAnnotations by annotationsOn(KmConstructor::flags) + +/** + * Signifies that the corresponding function has at least one annotation. + * + * This flag is useful for reading Kotlin metadata on JVM efficiently. On JVM, most of the annotations are written not to the Kotlin + * metadata, but directly on the corresponding declarations in the class file. This flag can be used as an optimization to avoid + * reading annotations from the class file (which can be slow) in case when a function has no annotations. + */ +var KmFunction.hasAnnotations by annotationsOn(KmFunction::flags) + +/** + * Signifies that the corresponding property has at least one annotation. + * + * This flag is useful for reading Kotlin metadata on JVM efficiently. On JVM, most of the annotations are written not to the Kotlin + * metadata, but directly on the corresponding declarations in the class file. This flag can be used as an optimization to avoid + * reading annotations from the class file (which can be slow) in case when a property has no annotations. + */ +var KmProperty.hasAnnotations by annotationsOn(KmProperty::flags) + +/** + * Signifies that the corresponding value parameter has at least one annotation. + * + * This flag is useful for reading Kotlin metadata on JVM efficiently. On JVM, most of the annotations are written not to the Kotlin + * metadata, but directly on the corresponding declarations in the class file. This flag can be used as an optimization to avoid + * reading annotations from the class file (which can be slow) in case when a value parameter has no annotations. + */ +var KmValueParameter.hasAnnotations by annotationsOn(KmValueParameter::flags) + +/** + * Signifies that the corresponding type alias has at least one annotation. + * + * Type aliases store their annotation in metadata directly (accessible via [KmTypeAlias.annotations]) and + * in the class file at the same time. + * As a result, Kotlin compiler still writes this flag for them, and this extension is left for completeness. + */ +var KmTypeAlias.hasAnnotations by annotationsOn(KmTypeAlias::flags) + +// KmType and KmTypeParameter have annotations in it, and this flag for them is not written + +// --- CLASS --- + +/** + * Represents modality of a corresponding class + */ +var KmClass.modality: Modality by modalityDelegate(KmClass::flags) + +/** + * Represents visibility of a corresponding class + */ +var KmClass.visibility: Visibility by visibilityDelegate(KmClass::flags) + +/** + * Represents kind of a corresponding class + */ +var KmClass.kind: ClassKind by EnumFlagDelegate( + KmClass::flags, + ProtoFlags.CLASS_KIND, + ClassKind.entries, + ClassKind.entries.map { it.flag }, +) + +/** + * Signifies that the corresponding class is `inner`. + */ +var KmClass.isInner: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_INNER)) + +/** + * Signifies that the corresponding class is `data`. + */ +var KmClass.isData: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_DATA)) + +/** + * Signifies that the corresponding class is `external`. + */ +var KmClass.isExternal: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_CLASS)) + +/** + * Signifies that the corresponding class is `expect`. + */ +var KmClass.isExpect: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_EXPECT_CLASS)) + +/** + * Signifies that the corresponding class is either a pre-Kotlin-1.5 `inline` class, or a 1.5+ `value` class. + * + * Note that it doesn't imply that the class has [JvmInline] annotation and will be inlined. + * Currently, it is impossible to declare a value class without this annotation, but this can be changed in the future. + */ +var KmClass.isValue: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_VALUE_CLASS)) + +/** + * Signifies that the corresponding class is a functional interface, i.e. marked with the keyword `fun`. + */ +var KmClass.isFunInterface: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_FUN_INTERFACE)) + +/** + * Signifies that the corresponding enum class has synthetic ".entries" property in bytecode. + * Always `false` for not enum classes. + */ +var KmClass.hasEnumEntries: Boolean by classBooleanFlag(Flag(ProtoFlags.HAS_ENUM_ENTRIES)) + +// --- CONSTRUCTOR --- + +/** + * Represents visibility of a corresponding constructor. + */ +var KmConstructor.visibility: Visibility by visibilityDelegate(KmConstructor::flags) + +/** + * Signifies that the corresponding constructor is secondary, i.e. declared not in the class header, but in the class body. + */ +var KmConstructor.isSecondary: Boolean by constructorBooleanFlag(Flag(ProtoFlags.IS_SECONDARY)) + +/** + * Signifies that the corresponding constructor has non-stable parameter names, i.e. cannot be called with named arguments. + */ +var KmConstructor.hasNonStableParameterNames: Boolean by constructorBooleanFlag(Flag(ProtoFlags.IS_CONSTRUCTOR_WITH_NON_STABLE_PARAMETER_NAMES)) + +// --- FUNCTION --- + +/** + * Represents kind of a corresponding function + */ +var KmFunction.kind: MemberKind by memberKindDelegate(KmFunction::flags) + +/** + * Represents visibility of a corresponding function + */ +var KmFunction.visibility: Visibility by visibilityDelegate(KmFunction::flags) + +/** + * Represents modality of a corresponding function. + */ +var KmFunction.modality: Modality by modalityDelegate(KmFunction::flags) + +/** + * Signifies that the corresponding function is `operator`. + */ +var KmFunction.isOperator: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_OPERATOR)) + +/** + * Signifies that the corresponding function is `infix`. + */ +var KmFunction.isInfix: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_INFIX)) + +/** + * Signifies that the corresponding function is `inline`. + */ +var KmFunction.isInline: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_INLINE)) + +/** + * Signifies that the corresponding function is `tailrec`. + */ +var KmFunction.isTailrec: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_TAILREC)) + +/** + * Signifies that the corresponding function is `external`. + */ +var KmFunction.isExternal: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_FUNCTION)) + +/** + * Signifies that the corresponding function is `suspend`. + */ +var KmFunction.isSuspend: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_SUSPEND)) + +/** + * Signifies that the corresponding function is `expect`. + */ +var KmFunction.isExpect: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_EXPECT_FUNCTION)) + +/** + * Signifies that the corresponding function has non-stable parameter names, i.e. cannot be called with named arguments. + */ +var KmFunction.hasNonStableParameterNames: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_FUNCTION_WITH_NON_STABLE_PARAMETER_NAMES)) + +// --- PROPERTY --- + +/** + * Represents visibility of a corresponding property + */ +var KmProperty.visibility: Visibility by visibilityDelegate(KmProperty::flags) + +/** + * Represents modality of a corresponding property. + */ +var KmProperty.modality: Modality by modalityDelegate(KmProperty::flags) + +/** + * Represents kind of a corresponding property + */ +var KmProperty.kind: MemberKind by memberKindDelegate(KmProperty::flags) + +/** + * Signifies that the corresponding property is `var`. + */ +var KmProperty.isVar: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_VAR)) + +/** + * Signifies that the corresponding property has a getter. + */ +var KmProperty.hasGetter: Boolean by propertyBooleanFlag(Flag(ProtoFlags.HAS_GETTER)) + +/** + * Signifies that the corresponding property has a setter. + */ +var KmProperty.hasSetter: Boolean by propertyBooleanFlag(Flag(ProtoFlags.HAS_SETTER)) + +/** + * Signifies that the corresponding property is `const`. + */ +var KmProperty.isConst: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_CONST)) + +/** + * Signifies that the corresponding property is `lateinit`. + */ +var KmProperty.isLateinit: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_LATEINIT)) + +/** + * Signifies that the corresponding property has a constant value. On JVM, this flag allows an optimization similarly to + * [KmProperty.hasAnnotations]: constant values of properties are written to the bytecode directly, and this flag can be used to avoid + * reading the value from the bytecode in case there isn't one. + */ +var KmProperty.hasConstant: Boolean by propertyBooleanFlag(Flag(ProtoFlags.HAS_CONSTANT)) + +/** + * Signifies that the corresponding property is `external`. + */ +var KmProperty.isExternal: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_PROPERTY)) + +/** + * Signifies that the corresponding property is a delegated property. + */ +var KmProperty.isDelegated: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_DELEGATED)) + +/** + * Signifies that the corresponding property is `expect`. + */ +var KmProperty.isExpect: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_EXPECT_PROPERTY)) + +// --- PROPERTY ACCESSOR --- + +/** + * Represents visibility of a corresponding property accessor. + */ +var KmPropertyAccessorAttributes.visibility: Visibility by visibilityDelegate(KmPropertyAccessorAttributes::flags) + +/** + * Represents modality of a corresponding property accessor. + */ +var KmPropertyAccessorAttributes.modality: Modality by modalityDelegate(KmPropertyAccessorAttributes::flags) + +/** + * Signifies that the corresponding property accessor is not default, i.e. it has a body and/or annotations in the source code. + */ +var KmPropertyAccessorAttributes.isNotDefault: Boolean by propertyAccessorBooleanFlag(Flag(ProtoFlags.IS_NOT_DEFAULT)) + +/** + * Signifies that the corresponding property accessor is `external`. + */ +val KmPropertyAccessorAttributes.isExternal: Boolean by propertyAccessorBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_ACCESSOR)) + +/** + * Signifies that the corresponding property accessor is `inline`. + */ +val KmPropertyAccessorAttributes.isInline: Boolean by propertyAccessorBooleanFlag(Flag(ProtoFlags.IS_INLINE_ACCESSOR)) + +// --- TYPE & TYPE_PARAM + +/** + * Signifies that the corresponding type is marked as nullable, i.e. has a question mark at the end of its notation. + */ +var KmType.isNullable: Boolean by typeBooleanFlag(Flag(0, 1, 1)) + +/** + * Signifies that the corresponding type is `suspend`. + */ +var KmType.isSuspend: Boolean by typeBooleanFlag(Flag(ProtoFlags.SUSPEND_TYPE.offset + 1, ProtoFlags.SUSPEND_TYPE.bitWidth, 1)) + +/** + * Signifies that the corresponding type is [definitely non-null](https://kotlinlang.org/docs/whatsnew17.html#stable-definitely-non-nullable-types). + */ +var KmType.isDefinitelyNonNull: Boolean by typeBooleanFlag( + Flag( + ProtoFlags.DEFINITELY_NOT_NULL_TYPE.offset + 1, + ProtoFlags.DEFINITELY_NOT_NULL_TYPE.bitWidth, + 1 + ) +) + + +/** + * Signifies that the corresponding type parameter is `reified`. + */ +var KmTypeParameter.isReified: Boolean by BooleanFlagDelegate(KmTypeParameter::flags, Flag(0, 1, 1)) + +// --- TYPE ALIAS --- + +/** + * Represents visibility of a corresponding type alias. + */ +var KmTypeAlias.visibility: Visibility by visibilityDelegate(KmTypeAlias::flags) + + +// --- VALUE PARAMETER --- + + +/** + * Signifies that the corresponding value parameter declares a default value. Note that the default value itself can be a complex + * expression and is not available via metadata. Also note that in case of an override of a parameter with default value, the + * parameter in the derived method does _not_ declare the default value, but the parameter is + * still optional at the call site because the default value from the base method is used. + */ +var KmValueParameter.declaresDefaultValue: Boolean by valueParameterBooleanFlag(Flag(ProtoFlags.DECLARES_DEFAULT_VALUE)) + +/** + * Signifies that the corresponding value parameter is `crossinline`. + */ +var KmValueParameter.isCrossinline: Boolean by valueParameterBooleanFlag(Flag(ProtoFlags.IS_CROSSINLINE)) + +/** + * Signifies that the corresponding value parameter is `noinline`. + */ +var KmValueParameter.isNoinline: Boolean by valueParameterBooleanFlag(Flag(ProtoFlags.IS_NOINLINE)) + +// --- EFFECT EXPRESSION --- + +/** + * Signifies that the corresponding effect expression should be negated to compute the proposition or the conclusion of an effect. + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + */ +@ExperimentalContracts +var KmEffectExpression.isNegated: Boolean by BooleanFlagDelegate(KmEffectExpression::flags, Flag(ProtoFlags.IS_NEGATED)) + +/** + * Signifies that the corresponding effect expression checks whether a value of some variable is `null`. + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + */ +@ExperimentalContracts +var KmEffectExpression.isNullCheckPredicate: Boolean by BooleanFlagDelegate(KmEffectExpression::flags, Flag(ProtoFlags.IS_NULL_CHECK_PREDICATE)) diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt index 194618950ef..f2204de8e40 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt @@ -9,6 +9,9 @@ import kotlinx.metadata.internal.IgnoreInApiDump import org.jetbrains.kotlin.metadata.ProtoBuf.* import org.jetbrains.kotlin.metadata.ProtoBuf.Class.Kind as ClassKind import org.jetbrains.kotlin.metadata.deserialization.Flags as F +import org.jetbrains.kotlin.metadata.ProtoBuf.Modality as ProtoModality +import org.jetbrains.kotlin.metadata.ProtoBuf.Visibility as ProtoVisibility +import org.jetbrains.kotlin.metadata.ProtoBuf.MemberKind as ProtoMemberKind /** * Represents a boolean flag that is either present or not in a Kotlin declaration. A "flag" is a boolean trait that is either present @@ -38,7 +41,7 @@ import org.jetbrains.kotlin.metadata.deserialization.Flags as F * @see Flags * @see flagsOf */ -class Flag(private val offset: Int, private val bitWidth: Int, private val value: Int) { +class Flag(internal val offset: Int, internal val bitWidth: Int, internal val value: Int) { @IgnoreInApiDump internal constructor(field: F.FlagField<*>, value: Int) : this(field.offset, field.bitWidth, value) @@ -71,64 +74,64 @@ class Flag(private val offset: Int, private val bitWidth: Int, private val value * A visibility flag, signifying that the corresponding declaration is `internal`. */ @JvmField - val IS_INTERNAL = Flag(F.VISIBILITY, Visibility.INTERNAL_VALUE) + val IS_INTERNAL = Flag(F.VISIBILITY, ProtoVisibility.INTERNAL_VALUE) /** * A visibility flag, signifying that the corresponding declaration is `private`. */ @JvmField - val IS_PRIVATE = Flag(F.VISIBILITY, Visibility.PRIVATE_VALUE) + val IS_PRIVATE = Flag(F.VISIBILITY, ProtoVisibility.PRIVATE_VALUE) /** * A visibility flag, signifying that the corresponding declaration is `protected`. */ @JvmField - val IS_PROTECTED = Flag(F.VISIBILITY, Visibility.PROTECTED_VALUE) + val IS_PROTECTED = Flag(F.VISIBILITY, ProtoVisibility.PROTECTED_VALUE) /** * A visibility flag, signifying that the corresponding declaration is `public`. */ @JvmField - val IS_PUBLIC = Flag(F.VISIBILITY, Visibility.PUBLIC_VALUE) + val IS_PUBLIC = Flag(F.VISIBILITY, ProtoVisibility.PUBLIC_VALUE) /** * A visibility flag, signifying that the corresponding declaration is "private-to-this", which is a non-denotable visibility of * private members in Kotlin which are callable only on the same instance of the declaring class. */ @JvmField - val IS_PRIVATE_TO_THIS = Flag(F.VISIBILITY, Visibility.PRIVATE_TO_THIS_VALUE) + val IS_PRIVATE_TO_THIS = Flag(F.VISIBILITY, ProtoVisibility.PRIVATE_TO_THIS_VALUE) /** * A visibility flag, signifying that the corresponding declaration is local, i.e. declared inside a code block * and not visible from the outside. */ @JvmField - val IS_LOCAL = Flag(F.VISIBILITY, Visibility.LOCAL_VALUE) + val IS_LOCAL = Flag(F.VISIBILITY, ProtoVisibility.LOCAL_VALUE) /** * A modality flag, signifying that the corresponding declaration is `final`. */ @JvmField - val IS_FINAL = Flag(F.MODALITY, Modality.FINAL_VALUE) + val IS_FINAL = Flag(F.MODALITY, ProtoModality.FINAL_VALUE) /** * A modality flag, signifying that the corresponding declaration is `open`. */ @JvmField - val IS_OPEN = Flag(F.MODALITY, Modality.OPEN_VALUE) + val IS_OPEN = Flag(F.MODALITY, ProtoModality.OPEN_VALUE) /** * A modality flag, signifying that the corresponding declaration is `abstract`. */ @JvmField - val IS_ABSTRACT = Flag(F.MODALITY, Modality.ABSTRACT_VALUE) + val IS_ABSTRACT = Flag(F.MODALITY, ProtoModality.ABSTRACT_VALUE) /** * A modality flag, signifying that the corresponding declaration is `sealed`. */ @JvmField - val IS_SEALED = Flag(F.MODALITY, Modality.SEALED_VALUE) + val IS_SEALED = Flag(F.MODALITY, ProtoModality.SEALED_VALUE) } /** @@ -267,28 +270,28 @@ class Flag(private val offset: Int, private val bitWidth: Int, private val value * A member kind flag, signifying that the corresponding function is explicitly declared in the containing class. */ @JvmField - val IS_DECLARATION = Flag(F.MEMBER_KIND, MemberKind.DECLARATION_VALUE) + val IS_DECLARATION = Flag(F.MEMBER_KIND, ProtoMemberKind.DECLARATION_VALUE) /** * A member kind flag, signifying that the corresponding function exists in the containing class because a function with a suitable * signature exists in a supertype. This flag is not written by the Kotlin compiler and its effects are unspecified. */ @JvmField - val IS_FAKE_OVERRIDE = Flag(F.MEMBER_KIND, MemberKind.FAKE_OVERRIDE_VALUE) + val IS_FAKE_OVERRIDE = Flag(F.MEMBER_KIND, ProtoMemberKind.FAKE_OVERRIDE_VALUE) /** * A member kind flag, signifying that the corresponding function exists in the containing class because it has been produced * by interface delegation (delegation "by"). */ @JvmField - val IS_DELEGATION = Flag(F.MEMBER_KIND, MemberKind.DELEGATION_VALUE) + val IS_DELEGATION = Flag(F.MEMBER_KIND, ProtoMemberKind.DELEGATION_VALUE) /** * A member kind flag, signifying that the corresponding function exists in the containing class because it has been synthesized * by the compiler and has no declaration in the source code. */ @JvmField - val IS_SYNTHESIZED = Flag(F.MEMBER_KIND, MemberKind.SYNTHESIZED_VALUE) + val IS_SYNTHESIZED = Flag(F.MEMBER_KIND, ProtoMemberKind.SYNTHESIZED_VALUE) /** @@ -351,28 +354,28 @@ class Flag(private val offset: Int, private val bitWidth: Int, private val value * A member kind flag, signifying that the corresponding property is explicitly declared in the containing class. */ @JvmField - val IS_DECLARATION = Flag(F.MEMBER_KIND, MemberKind.DECLARATION_VALUE) + val IS_DECLARATION = Flag(F.MEMBER_KIND, ProtoMemberKind.DECLARATION_VALUE) /** * A member kind flag, signifying that the corresponding property exists in the containing class because a property with a suitable * signature exists in a supertype. This flag is not written by the Kotlin compiler and its effects are unspecified. */ @JvmField - val IS_FAKE_OVERRIDE = Flag(F.MEMBER_KIND, MemberKind.FAKE_OVERRIDE_VALUE) + val IS_FAKE_OVERRIDE = Flag(F.MEMBER_KIND, ProtoMemberKind.FAKE_OVERRIDE_VALUE) /** * A member kind flag, signifying that the corresponding property exists in the containing class because it has been produced * by interface delegation (delegation "by"). */ @JvmField - val IS_DELEGATION = Flag(F.MEMBER_KIND, MemberKind.DELEGATION_VALUE) + val IS_DELEGATION = Flag(F.MEMBER_KIND, ProtoMemberKind.DELEGATION_VALUE) /** * A member kind flag, signifying that the corresponding property exists in the containing class because it has been synthesized * by the compiler and has no declaration in the source code. */ @JvmField - val IS_SYNTHESIZED = Flag(F.MEMBER_KIND, MemberKind.SYNTHESIZED_VALUE) + val IS_SYNTHESIZED = Flag(F.MEMBER_KIND, ProtoMemberKind.SYNTHESIZED_VALUE) /** diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt new file mode 100644 index 00000000000..892b8226837 --- /dev/null +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt @@ -0,0 +1,185 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlinx.metadata + +import org.jetbrains.kotlin.metadata.deserialization.Flags as ProtoFlags +import org.jetbrains.kotlin.metadata.ProtoBuf.Class.Kind as ProtoClassKind +import org.jetbrains.kotlin.metadata.ProtoBuf.Visibility as ProtoVisibility +import org.jetbrains.kotlin.metadata.ProtoBuf.Modality as ProtoModality +import org.jetbrains.kotlin.metadata.ProtoBuf.MemberKind as ProtoMemberKind + +// Do not reorder any enums in this file! + +/** + * Represents visibility level (also known as access level) of a corresponding declaration. + * Some of these visibilities may be non-denotable in Kotlin. + */ +enum class Visibility(kind: Int) { + /** + * Signifies that the corresponding declaration is `internal`. + */ + INTERNAL(ProtoVisibility.INTERNAL_VALUE), + + /** + * Signifies that the corresponding declaration is `private`. + */ + PRIVATE(ProtoVisibility.PRIVATE_VALUE), + + /** + * Signifies that the corresponding declaration is `protected`. + */ + PROTECTED(ProtoVisibility.PROTECTED_VALUE), + + /** + * Signifies that the corresponding declaration is `public`. + */ + PUBLIC(ProtoVisibility.PUBLIC_VALUE), + + /** + * Signifies that the corresponding declaration is "private-to-this", which is a non-denotable visibility of + * private members in Kotlin which are callable only on the same instance of the declaring class. + * Generally, this visibility is more restrictive than 'private', so for most use cases it can be treated the same. + * + * Example of 'PRIVATE_TO_THIS' declaration: + * ``` + * class A(t: T) { + * private val t: T = t // visibility for t is PRIVATE_TO_THIS + * + * fun test() { + * val x: T = t // correct + * val y: T = this.t // also correct + * } + * fun foo(a: A) { + * val x: String = a.t // incorrect, because a.t can be Any + * } + * } + * ``` + */ + PRIVATE_TO_THIS(ProtoVisibility.PRIVATE_TO_THIS_VALUE), + + /** + * Signifies that the corresponding declaration is local, i.e. declared inside a code block + * and not visible from the outside. + */ + LOCAL(ProtoVisibility.LOCAL_VALUE) + ; + + internal val flag = Flag(ProtoFlags.VISIBILITY, kind) +} + +/** + * Represents modality of a corresponding declaration. + */ +enum class Modality(kind: Int) { + /** + * Signifies that the corresponding declaration is `final`. + */ + FINAL(ProtoModality.FINAL_VALUE), + + /** + * Signifies that the corresponding declaration is `open`. + */ + OPEN(ProtoModality.OPEN_VALUE), + + /** + * Signifies that the corresponding declaration is `abstract`. + */ + ABSTRACT(ProtoModality.ABSTRACT_VALUE), + + /** + * Signifies that the corresponding declaration is `sealed`. + * + * Pay attention that this modality is not applicable to class' members. + * Setting it as a value for member modality leads to an undefined behaviour. + */ + SEALED(ProtoModality.SEALED_VALUE) + ; + + internal val flag = Flag(ProtoFlags.MODALITY, kind) +} + +/** + * Represents the nature of a corresponding class. + */ +enum class ClassKind(kind: Int) { + /** + * Signifies that the corresponding class is a usual `class`. + */ + CLASS(ProtoClassKind.CLASS_VALUE), + + /** + * Signifies that the corresponding class is an `interface`. + */ + INTERFACE(ProtoClassKind.INTERFACE_VALUE), + + /** + * Signifies that the corresponding class is an `enum class`. + */ + ENUM_CLASS(ProtoClassKind.ENUM_CLASS_VALUE), + + /** + * Signifies that the corresponding class is an enum entry. + */ + ENUM_ENTRY(ProtoClassKind.ENUM_ENTRY_VALUE), + + /** + * Signifies that the corresponding class is an `annotation class`. + */ + ANNOTATION_CLASS(ProtoClassKind.ANNOTATION_CLASS_VALUE), + + /** + * Signifies that the corresponding class is a non-companion `object`. + */ + OBJECT(ProtoClassKind.OBJECT_VALUE), + + /** + * Signifies that the corresponding class is a `companion object`. + */ + COMPANION_OBJECT(ProtoClassKind.COMPANION_OBJECT_VALUE) + ; + + internal val flag = Flag(ProtoFlags.CLASS_KIND, kind) +} + +/** + * Represents kind of a function or property. + * + * Kind indicates the origin of a declaration within a containing class. + * It provides information about whether a function or property was defined, generated, or something else. + */ +enum class MemberKind(kind: Int) { + /** + * Signifies that the corresponding function or property is explicitly declared in the containing class. + */ + DECLARATION(ProtoMemberKind.DECLARATION_VALUE), + + /** + * Signifies that the corresponding function or property exists in the containing class because a function with a suitable + * signature exists in a supertype. + * This flag is not written by the Kotlin compiler and normally cannot be encountered in binary metadata. + * Its effects are unspecified. + */ + FAKE_OVERRIDE(ProtoMemberKind.FAKE_OVERRIDE_VALUE), + + /** + * Signifies that the corresponding function or property exists in the containing class because it has been produced + * by interface delegation. + * + * Do not confuse with property delegation which is denoted by [KmProperty.isDelegated]. + */ + DELEGATION(ProtoMemberKind.DELEGATION_VALUE), + + /** + * Signifies that the corresponding function or property exists in the containing class because it has been synthesized + * by the compiler or compiler plugin and has no declaration in the source code. + * + * An example of such function can be component1() of a data class. + */ + SYNTHESIZED(ProtoMemberKind.SYNTHESIZED_VALUE) + ; + + internal val flag = Flag(ProtoFlags.MEMBER_KIND, kind) +} diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt index 531a07f5715..e12ae3fa4dc 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt @@ -8,6 +8,7 @@ package kotlinx.metadata import kotlinx.metadata.internal.extensions.* +import kotlinx.metadata.internal.getDefaultPropertyAccessorFlags import kotlin.contracts.ExperimentalContracts /** @@ -203,7 +204,7 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer { typeParameters.forEach { visitor.visitTypeParameter(it.flags, it.name, it.id, it.variance)?.let(it::accept) } supertypes.forEach { visitor.visitSupertype(it.flags)?.let(it::accept) } functions.forEach { visitor.visitFunction(it.flags, it.name)?.let(it::accept) } - properties.forEach { visitor.visitProperty(it.flags, it.name, it.getterFlags, it.setterFlags)?.let(it::accept) } + properties.forEach { visitor.visitProperty(it.flags, it.name, it.getter.flags, it.setterFlags)?.let(it::accept) } typeAliases.forEach { visitor.visitTypeAlias(it.flags, it.name)?.let(it::accept) } constructors.forEach { visitor.visitConstructor(it.flags)?.let(it::accept) } companionObject?.let(visitor::visitCompanionObject) @@ -268,7 +269,7 @@ class KmPackage : KmPackageVisitor(), KmDeclarationContainer { @Deprecated(VISITOR_API_MESSAGE) fun accept(visitor: KmPackageVisitor) { functions.forEach { visitor.visitFunction(it.flags, it.name)?.let(it::accept) } - properties.forEach { visitor.visitProperty(it.flags, it.name, it.getterFlags, it.setterFlags)?.let(it::accept) } + properties.forEach { visitor.visitProperty(it.flags, it.name, it.getter.flags, it.setterFlags)?.let(it::accept) } typeAliases.forEach { visitor.visitTypeAlias(it.flags, it.name)?.let(it::accept) } extensions.forEach { visitor.visitExtensions(it.type)?.let(it::accept) } visitor.visitEnd() @@ -307,7 +308,10 @@ class KmLambda : KmLambdaVisitor() { * @property flags constructor flags, consisting of [Flag.HAS_ANNOTATIONS], a visibility flag and [Flag.Constructor] flags */ @Suppress("DEPRECATION") -class KmConstructor(var flags: Flags) : KmConstructorVisitor() { +class KmConstructor @Deprecated(FLAGS_CTOR_DEPRECATED) constructor(var flags: Flags) : + KmConstructorVisitor() { + constructor() : this(0) + /** * Value parameters of the constructor. */ @@ -354,10 +358,13 @@ class KmConstructor(var flags: Flags) : KmConstructorVisitor() { * @property name the name of the function */ @Suppress("DEPRECATION") -class KmFunction( +class KmFunction @Deprecated(FLAGS_CTOR_DEPRECATED) constructor( var flags: Flags, - var name: String + var name: String, ) : KmFunctionVisitor() { + + constructor(name: String) : this(0, name) + /** * Type parameters of the function. */ @@ -452,23 +459,84 @@ class KmFunction( } } +/** + * Represents a Kotlin property accessor. + * Does not contain meaningful information except attributes, such as visibility and modality. + * Attributes can be read and written using extension functions, e.g. [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. + */ +public class KmPropertyAccessorAttributes internal constructor(internal var flags: Flags) { + public constructor() : this(0) +} + /** * Represents a Kotlin property declaration. * * @property flags property flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Property] flags * @property name the name of the property - * @property getterFlags property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag - * and [Flag.PropertyAccessor] flags - * @property setterFlags property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag - * and [Flag.PropertyAccessor] flags */ @Suppress("DEPRECATION") -class KmProperty( +class KmProperty @Deprecated(FLAGS_CTOR_DEPRECATED) constructor( var flags: Flags, var name: String, - var getterFlags: Flags, - var setterFlags: Flags + getterFlags: Flags, + setterFlags: Flags, ) : KmPropertyVisitor() { + + constructor(name: String) : this(0, name, 0, 0) + + /** + * Attributes of the getter of this property. + * Attributes can be retrieved with extension functions, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. + * + * Getter for property is always present, hence return type of this function is non-nullable. + */ + val getter: KmPropertyAccessorAttributes = KmPropertyAccessorAttributes(getterFlags) + + /** + * Attributes of the setter of this property. + * Attributes can be retrieved with extension functions, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. + * + * Returns null if setter is absent, i.e. [KmProperty.isVar] is false. + */ + var setter: KmPropertyAccessorAttributes? = if (this.hasSetter) KmPropertyAccessorAttributes(setterFlags) else null + set(new) { + this.hasSetter = new != null + field = new + } + + /** + * A legacy accessor for getter attributes. + * + * Property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag + * and [Flag.PropertyAccessor] flags. + */ + var getterFlags: Flags + get() = getter.flags + set(value) { + getter.flags = value + } + + /** + * A legacy accessor to setter attributes. + * + * Property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag + * and [Flag.PropertyAccessor] flags. + * + * Note that, for compatibility reasons, flags are present even the property is `val` and `setter` is null. + * In that case, flags for hasAnnotation, visibility and modality are copied from properties' flag, which may lead + * to incorrect results. For example, when property is annotated, [setterFlags] will also return true for [Flag.Common.HAS_ANNOTATIONS], + * even though there is no setter nor annotations on it. + * + * Setting this property when setter is absent changes the value, but does not create new [setter]. + * This behavior is for compatibility only and will be removed in future versions. + */ + var setterFlags: Flags = getDefaultPropertyAccessorFlags(flags) + get() = setter?.flags ?: field + set(value) { + setter?.flags = value + field = value + } + /** * Type parameters of the property. */ @@ -486,7 +554,15 @@ class KmProperty( val contextReceiverTypes: MutableList = ArrayList(0) /** - * Value parameter of the setter of this property, if this is a `var` property. + * Value parameter of the setter of this property, if this is a `var` property and parameter is present. + * Parameter is present if and only if the setter is not default: + * + * ```kotlin + * var foo: String = "" + * set(param) { + * field = param.removePrefix("bar") + * } + * ``` */ var setterParameter: KmValueParameter? = null @@ -558,10 +634,13 @@ class KmProperty( * @property name the name of the type alias */ @Suppress("DEPRECATION") -class KmTypeAlias( +class KmTypeAlias @Deprecated(FLAGS_CTOR_DEPRECATED) constructor( var flags: Flags, - var name: String + var name: String, ) : KmTypeAliasVisitor() { + + constructor(name: String) : this(0, name) + /** * Type parameters of the type alias. */ @@ -640,10 +719,13 @@ class KmTypeAlias( * @property name the name of the value parameter */ @Suppress("DEPRECATION") -class KmValueParameter( +class KmValueParameter @Deprecated(FLAGS_CTOR_DEPRECATED) constructor( var flags: Flags, - var name: String + var name: String, ) : KmValueParameterVisitor() { + + constructor(name: String) : this(0, name) + /** * Type of the value parameter. * If this is a `vararg` parameter of type `X`, returns the type `Array`. @@ -694,12 +776,15 @@ class KmValueParameter( * @property variance the declaration-site variance of the type parameter */ @Suppress("DEPRECATION") -class KmTypeParameter( +class KmTypeParameter @Deprecated(FLAGS_CTOR_DEPRECATED) constructor( var flags: Flags, var name: String, var id: Int, - var variance: KmVariance + var variance: KmVariance, ) : KmTypeParameterVisitor() { + + constructor(name: String, id: Int, variance: KmVariance) : this(0, name, id, variance) + /** * Upper bounds of the type parameter. */ @@ -735,7 +820,10 @@ class KmTypeParameter( * @property flags type flags, consisting of [Flag.Type] flags */ @Suppress("DEPRECATION") -class KmType(var flags: Flags) : KmTypeVisitor() { +class KmType @Deprecated(FLAGS_CTOR_DEPRECATED) constructor(var flags: Flags) : KmTypeVisitor() { + + constructor() : this(0) + /** * Classifier of the type. */ @@ -994,7 +1082,7 @@ class KmEffect( */ @ExperimentalContracts @Suppress("DEPRECATION") -class KmEffectExpression : KmEffectExpressionVisitor() { +class KmEffectExpression : KmEffectExpressionVisitor() { /** * Effect expression flags, consisting of [Flag.EffectExpression] flags. */ @@ -1155,3 +1243,6 @@ internal fun T.addTo(collection: MutableCollection): T { collection.add(this) return this } + +private const val FLAGS_CTOR_DEPRECATED = + "Constructor with flags is deprecated, use constructor without flags and assign them or corresponding extension properties directly." diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/FlagDelegatesImpl.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/FlagDelegatesImpl.kt new file mode 100644 index 00000000000..60794603810 --- /dev/null +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/FlagDelegatesImpl.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +@file:OptIn(ExperimentalStdlibApi::class) + +package kotlinx.metadata.internal + +import kotlinx.metadata.* +import kotlin.enums.EnumEntries +import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.KProperty +import org.jetbrains.kotlin.metadata.deserialization.Flags.FlagField as ProtoFlagSet +import org.jetbrains.kotlin.metadata.deserialization.Flags as ProtoFlags +import org.jetbrains.kotlin.protobuf.Internal.EnumLite as ProtoEnumLite + +internal class EnumFlagDelegate>( + val flags: KMutableProperty1, + private val protoSet: ProtoFlagSet, + private val entries: EnumEntries, + private val flagValues: List +) { + // Pre-built permutation ProtoEnum <> E to allow reordering of enum entries? + // Concern: if new enum values are added to metadata proto, everything (including existing flags) will break + operator fun getValue(thisRef: Node, property: KProperty<*>): E = entries[protoSet.get(flags.get(thisRef)).number] + + operator fun setValue(thisRef: Node, property: KProperty<*>, value: E) { + flags.set(thisRef, flagValues[value.ordinal] + flags.get(thisRef)) + } +} + +// Public in internal package - for reuse in JvmFlags +public class BooleanFlagDelegate(private val flags: KMutableProperty1, private val flag: Flag) { + private val mask: Int + + init { + require(flag.bitWidth == 1 && flag.value == 1) { "BooleanFlagDelegate can work only with boolean flags (bitWidth = 1 and value = 1), but $flag was passed" } + mask = 1 shl flag.offset + } + + operator fun getValue(thisRef: Node, property: KProperty<*>): Boolean = flag(flags.get(thisRef)) + + operator fun setValue(thisRef: Node, property: KProperty<*>, value: Boolean) { + val newValue = if (value) flags.get(thisRef) or mask else flags.get(thisRef) and mask.inv() + flags.set(thisRef, newValue) + } +} + + +internal fun visibilityDelegate(flags: KMutableProperty1) = + EnumFlagDelegate(flags, ProtoFlags.VISIBILITY, Visibility.entries, Visibility.entries.map { it.flag }) + +internal fun modalityDelegate(flags: KMutableProperty1) = + EnumFlagDelegate(flags, ProtoFlags.MODALITY, Modality.entries, Modality.entries.map { it.flag }) + +internal fun memberKindDelegate(flags: KMutableProperty1) = + EnumFlagDelegate(flags, ProtoFlags.MEMBER_KIND, MemberKind.entries, MemberKind.entries.map { it.flag }) + +internal fun classBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmClass::flags, flag) + +internal fun functionBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmFunction::flags, flag) + +internal fun constructorBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmConstructor::flags, flag) + +internal fun propertyBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmProperty::flags, flag) + +internal fun propertyAccessorBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmPropertyAccessorAttributes::flags, flag) + +internal fun typeBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmType::flags, flag) + +internal fun valueParameterBooleanFlag(flag: Flag) = BooleanFlagDelegate(KmValueParameter::flags, flag) + +internal fun annotationsOn(flags: KMutableProperty1) = BooleanFlagDelegate(flags, Flag(ProtoFlags.HAS_ANNOTATIONS)) + diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/Readers.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/Readers.kt index e283a87a930..c4278c0a9a6 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/Readers.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/internal/Readers.kt @@ -527,5 +527,5 @@ fun ProtoBuf.Property.getPropertyGetterFlags(): Flags = fun ProtoBuf.Property.getPropertySetterFlags(): Flags = if (hasSetterFlags()) setterFlags else getDefaultPropertyAccessorFlags(flags) -private fun getDefaultPropertyAccessorFlags(flags: Flags): Flags = +internal fun getDefaultPropertyAccessorFlags(flags: Flags): Flags = F.getAccessorFlags(F.HAS_ANNOTATIONS.get(flags), F.VISIBILITY.get(flags), F.MODALITY.get(flags), false, false, false) diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt index 5c34660b65b..490d50f7b6c 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt @@ -34,7 +34,7 @@ private fun visitFunction( sb.appendLine(function.contextReceiverTypes.joinToString(prefix = " context(", postfix = ")", transform = ::printType)) } sb.append(" ") - sb.appendFlags(function.flags, FUNCTION_FLAGS_MAP) + sb.appendFunctionModifiers(function) sb.append("fun ") if (function.typeParameters.isNotEmpty()) { function.typeParameters.joinTo(sb, prefix = "<", postfix = ">", transform = { printTypeParameter(it, settings) }) @@ -58,8 +58,6 @@ private fun visitProperty( settings: KotlinpSettings, sb: StringBuilder ) { - val flags: Flags = property.flags - sb.appendLine() property.versionRequirements.map(::printVersionRequirement).forEach { versionRequirement -> sb.appendLine(" // $versionRequirement") @@ -79,15 +77,15 @@ private fun visitProperty( if (property.syntheticMethodForDelegate != null) { sb.appendLine(" // synthetic method for delegate: ${property.syntheticMethodForDelegate}") } - if (JvmFlag.Property.IS_MOVED_FROM_INTERFACE_COMPANION(property.jvmFlags)) { + if (property.isMovedFromInterfaceCompanion) { sb.appendLine(" // is moved from interface companion") } if (property.contextReceiverTypes.isNotEmpty()) { sb.appendLine(property.contextReceiverTypes.joinToString(prefix = " context(", postfix = ")", transform = ::printType)) } sb.append(" ") - sb.appendFlags(flags, PROPERTY_FLAGS_MAP) - sb.append(if (Flag.Property.IS_VAR(flags)) "var " else "val ") + sb.appendPropertyModifiers(property) + sb.append(if (property.isVar) "var " else "val ") if (property.typeParameters.isNotEmpty()) { property.typeParameters.joinTo(sb, prefix = "<", postfix = ">", transform = { printTypeParameter(it, settings) }) sb.append(" ") @@ -97,18 +95,19 @@ private fun visitProperty( } sb.append(property.name) sb.append(": ").append(property.returnType.let(::printType)) - if (Flag.Property.HAS_CONSTANT(flags)) { + if (property.hasConstant) { sb.append(" /* = ... */") } sb.appendLine() - if (Flag.Property.HAS_GETTER(flags)) { + if (property.hasGetter) { sb.append(" ") - sb.appendFlags(property.getterFlags, PROPERTY_ACCESSOR_FLAGS_MAP) + sb.appendPropertyAccessorModifiers(property.getter) sb.appendLine("get") } - if (Flag.Property.HAS_SETTER(flags)) { + val setter = property.setter + if (setter != null) { sb.append(" ") - sb.appendFlags(property.setterFlags, PROPERTY_ACCESSOR_FLAGS_MAP) + sb.appendPropertyAccessorModifiers(setter) sb.append("set") property.setterParameter?.let { sb.append("(").append(printValueParameter(it)).append(")") @@ -127,7 +126,7 @@ private fun visitConstructor(constructor: KmConstructor, sb: StringBuilder) { sb.appendLine(" // signature: ${constructor.signature}") } sb.append(" ") - sb.appendFlags(constructor.flags, CONSTRUCTOR_FLAGS_MAP) + sb.appendConstructorModifiers(constructor) sb.append("constructor(") constructor.valueParameters.joinTo(sb, transform = ::printValueParameter) sb.appendLine(")") @@ -146,7 +145,7 @@ private fun visitTypeAlias( sb.append(" ").append("@").append(renderAnnotation(annotation)).appendLine() } sb.append(" ") - sb.appendFlags(typeAlias.flags, VISIBILITY_FLAGS_MAP) + sb.append(VISIBILITY_MAP[typeAlias.visibility]) sb.append("typealias ").append(typeAlias.name) if (typeAlias.typeParameters.isNotEmpty()) { typeAlias.typeParameters.joinTo(sb, prefix = "<", postfix = ">") { printTypeParameter(it, settings) } @@ -157,7 +156,6 @@ private fun visitTypeAlias( } private fun printType(type: KmType): String { - val flags: Flags = type.flags val classifier = when (val cls = type.classifier) { is KmClassifier.Class -> cls.name is KmClassifier.TypeParameter -> "T#${cls.id}" @@ -198,7 +196,7 @@ private fun printType(type: KmType): String { if (type.isRaw) { append("/* raw */ ") } - appendFlags(flags, TYPE_FLAGS_MAP) + appendFlags(type.isSuspend to "suspend") if (outerType != null) { append(outerType).append(".").append(classifier.substringAfterLast('.')) } else { @@ -207,10 +205,10 @@ private fun printType(type: KmType): String { if (arguments.isNotEmpty()) { arguments.joinTo(this, prefix = "<", postfix = ">") } - if (Flag.Type.IS_NULLABLE(flags)) { + if (type.isNullable) { append("?") } - if (Flag.Type.IS_DEFINITELY_NON_NULL(flags)) { + if (type.isDefinitelyNonNull) { append(" & Any") } if (abbreviatedType != null) { @@ -229,7 +227,7 @@ private fun printTypeParameter( typeParameter: KmTypeParameter, settings: KotlinpSettings ): String = buildString { - appendFlags(typeParameter.flags, TYPE_PARAMETER_FLAGS_MAP) + appendFlags(typeParameter.isReified to "reified") for (annotation in typeParameter.annotations) { append("@").append(renderAnnotation(annotation)).append(" ") } @@ -248,17 +246,16 @@ private fun printTypeParameter( private fun printValueParameter( valueParameter: KmValueParameter ): String { - val flags: Flags = valueParameter.flags val type = printType(valueParameter.type) val varargElementType = valueParameter.varargElementType?.let(::printType) return buildString { - appendFlags(flags, VALUE_PARAMETER_FLAGS_MAP) + appendValueParameterModifiers(valueParameter) if (varargElementType != null) { append("vararg ").append(valueParameter.name).append(": ").append(varargElementType).append(" /* ").append(type).append(" */") } else { append(valueParameter.name).append(": ").append(type) } - if (Flag.ValueParameter.DECLARES_DEFAULT_VALUE(flags)) { + if (valueParameter.declaresDefaultValue) { append(" /* = ... */") } } @@ -338,15 +335,6 @@ private fun printVersionRequirement(versionRequirement: KmVersionRequirement): S } } -private fun StringBuilder.appendFlags(flags: Flags, map: Map) { - for ((modifier, string) in map) { - if (modifier(flags)) { - append(string) - if (string.isNotEmpty()) append(" ") - } - } -} - private fun StringBuilder.appendDeclarationContainerExtensions( settings: KotlinpSettings, localDelegatedProperties: List, @@ -427,7 +415,6 @@ private fun printEffect( @ExperimentalContracts private fun printEffectExpression(effectExpression: KmEffectExpression): String { - val flags: Flags = effectExpression.flags val parameterIndex: Int? = effectExpression.parameterIndex val constantValue: List? = effectExpression.constantValue?.let { listOf(it.value) } val andArguments = effectExpression.andArguments.map(::printEffectExpression) @@ -447,11 +434,11 @@ private fun printEffectExpression(effectExpression: KmEffectExpression): String ) if (effectExpression.isInstanceType != null) { append(" ") - if (Flag.EffectExpression.IS_NEGATED(flags)) append("!") + if (effectExpression.isNegated) append("!") append("is ${effectExpression.isInstanceType?.let(::printType)}") } - if (Flag.EffectExpression.IS_NULL_CHECK_PREDICATE(flags)) { - append(if (Flag.EffectExpression.IS_NEGATED(flags)) " != " else " == ") + if (effectExpression.isNullCheckPredicate) { + append(if (effectExpression.isNegated) " != " else " == ") append("null") } @@ -478,7 +465,7 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter() private val supertypes = mutableListOf() @@ -496,7 +483,7 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter() val moduleName: String? = kclass.moduleName - val jvmFlags: Flags = kclass.jvmFlags anonymousObjectOriginName = kclass.anonymousObjectOriginName kclass.localDelegatedProperties.sortIfNeededBy(settings) { it.getterSignature?.toString() ?: it.name }.forEach { p -> @@ -557,11 +543,11 @@ class ClassPrinter(private val settings: KotlinpSettings) : AbstractPrinter) = modifiers.forEach { (condition, s) -> + if (condition) { + append(s) + if (s.isNotEmpty()) append(" ") + } +} - Flag.Function.IS_OPERATOR to "operator", - Flag.Function.IS_INFIX to "infix", - Flag.Function.IS_INLINE to "inline", - Flag.Function.IS_TAILREC to "tailrec", - Flag.Function.IS_EXTERNAL to "external", - Flag.Function.IS_SUSPEND to "suspend", - Flag.Function.IS_EXPECT to "expect", +private fun StringBuilder.appendClassModifiers(kmClass: KmClass) { + append(VISIBILITY_MAP[kmClass.visibility]) + append(MODALITY_MAP[kmClass.modality]) + appendFlags( + kmClass.isInner to "inner", + kmClass.isData to "data", + kmClass.isExternal to "external", + kmClass.isExpect to "expect", + kmClass.isValue to "value", + kmClass.isFunInterface to "fun", + ) + append(CLASS_KIND_MAP[kmClass.kind]) +} - Flag.Function.HAS_NON_STABLE_PARAMETER_NAMES to "/* non-stable parameter names */" -) - -private val PROPERTY_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf( - Flag.Property.IS_DECLARATION to "", - Flag.Property.IS_FAKE_OVERRIDE to "/* fake override */", - Flag.Property.IS_DELEGATION to "/* delegation */", - Flag.Property.IS_SYNTHESIZED to "/* synthesized */", - - Flag.Property.IS_CONST to "const", - Flag.Property.IS_LATEINIT to "lateinit", - Flag.Property.IS_EXTERNAL to "external", - Flag.Property.IS_DELEGATED to "/* delegated */", - Flag.Property.IS_EXPECT to "expect" -) - -private val PROPERTY_ACCESSOR_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf( - Flag.PropertyAccessor.IS_NOT_DEFAULT to "/* non-default */", - Flag.PropertyAccessor.IS_EXTERNAL to "external", - Flag.PropertyAccessor.IS_INLINE to "inline" -) - -private val VALUE_PARAMETER_FLAGS_MAP = mapOf( - Flag.ValueParameter.IS_CROSSINLINE to "crossinline", - Flag.ValueParameter.IS_NOINLINE to "noinline" -) - -private val TYPE_PARAMETER_FLAGS_MAP = mapOf( - Flag.TypeParameter.IS_REIFIED to "reified" -) - -private val TYPE_FLAGS_MAP = mapOf( - Flag.Type.IS_SUSPEND to "suspend" +private fun StringBuilder.appendConstructorModifiers(kmConstructor: KmConstructor) { + append(VISIBILITY_MAP[kmConstructor.visibility]) + appendFlags( + kmConstructor.isSecondary to "/* secondary */", + kmConstructor.hasNonStableParameterNames to "/* non-stable parameter names */" + ) +} + +private fun StringBuilder.appendFunctionModifiers(kmFunction: KmFunction) { + append(VISIBILITY_MAP[kmFunction.visibility]) + append(MODALITY_MAP[kmFunction.modality]) + append(MEMBER_KIND_MAP[kmFunction.kind]) + appendFlags( + kmFunction.isOperator to "operator", + kmFunction.isInfix to "infix", + kmFunction.isInline to "inline", + kmFunction.isTailrec to "tailrec", + kmFunction.isExternal to "external", + kmFunction.isSuspend to "suspend", + kmFunction.isExpect to "expect", + kmFunction.hasNonStableParameterNames to "/* non-stable parameter names */" + ) +} + +private fun StringBuilder.appendPropertyModifiers(kmProperty: KmProperty) { + append(VISIBILITY_MAP[kmProperty.visibility]) + append(MODALITY_MAP[kmProperty.modality]) + append(MEMBER_KIND_MAP[kmProperty.kind]) + appendFlags( + kmProperty.isConst to "const", + kmProperty.isLateinit to "lateinit", + kmProperty.isExternal to "external", + kmProperty.isDelegated to "/* delegated */", + kmProperty.isExpect to "expect" + ) +} + +private fun StringBuilder.appendPropertyAccessorModifiers(accessorAttributes: KmPropertyAccessorAttributes) { + append(VISIBILITY_MAP[accessorAttributes.visibility]) + append(MODALITY_MAP[accessorAttributes.modality]) + appendFlags( + accessorAttributes.isNotDefault to "/* non-default */", + accessorAttributes.isExternal to "external", + accessorAttributes.isInline to "inline" + ) +} + +private fun StringBuilder.appendValueParameterModifiers(valueParameter: KmValueParameter) = appendFlags( + valueParameter.isCrossinline to "crossinline", + valueParameter.isNoinline to "noinline" ) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirDeserializers.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirDeserializers.kt index b0d7d0015a7..4ee41877471 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirDeserializers.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirDeserializers.kt @@ -7,6 +7,9 @@ package org.jetbrains.kotlin.commonizer.metadata import gnu.trove.THashMap import kotlinx.metadata.* +import kotlinx.metadata.Modality as KmModality +import kotlinx.metadata.Visibility as KmVisibility +import kotlinx.metadata.ClassKind as KmClassKind import kotlinx.metadata.klib.annotations import kotlinx.metadata.klib.compileTimeValue import kotlinx.metadata.klib.getterAnnotations diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirSerializers.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirSerializers.kt index 640e8e9095c..516d4155825 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirSerializers.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/CirSerializers.kt @@ -126,9 +126,8 @@ internal fun linkSealedClassesWithSubclasses(packageName: CirPackageName, classC internal fun CirClassConstructor.serializeConstructor( context: CirTreeSerializationContext -): KmConstructor = KmConstructor( - flags = classConstructorFlags() -).also { constructor -> +): KmConstructor = KmConstructor().also { constructor -> + constructor.flags = classConstructorFlags() annotations.mapTo(constructor.annotations) { it.serializeAnnotation() } // TODO: nowhere to write constructor type parameters valueParameters.mapTo(constructor.valueParameters) { it.serializeValueParameter(context) } @@ -137,9 +136,9 @@ internal fun CirClassConstructor.serializeConstructor( internal fun CirTypeAlias.serializeTypeAlias( context: CirTreeSerializationContext ): KmTypeAlias = KmTypeAlias( - flags = typeAliasFlags(), name = name.name ).also { typeAlias -> + typeAlias.flags = typeAliasFlags() annotations.mapTo(typeAlias.annotations) { it.serializeAnnotation() } typeParameters.serializeTypeParameters(context, output = typeAlias.typeParameters) typeAlias.underlyingType = underlyingType.serializeType(context, expansion = ONLY_ABBREVIATIONS) @@ -148,12 +147,10 @@ internal fun CirTypeAlias.serializeTypeAlias( internal fun CirProperty.serializeProperty( context: CirTreeSerializationContext, -): KmProperty = KmProperty( - flags = propertyFlags(isExpect = context.isCommon && !isLiftedUp), - name = name.name, - getterFlags = getter?.propertyAccessorFlags(this, this) ?: NO_FLAGS, - setterFlags = setter?.let { setter -> setter.propertyAccessorFlags(setter, this) } ?: NO_FLAGS -).also { property -> +): KmProperty = KmProperty(name = name.name).also { property -> + property.flags = propertyFlags(isExpect = context.isCommon && !isLiftedUp) + property.getterFlags = getter?.propertyAccessorFlags(this, this) ?: NO_FLAGS + property.setterFlags = setter?.let { setter -> setter.propertyAccessorFlags(setter, this) } ?: NO_FLAGS annotations.mapTo(property.annotations) { it.serializeAnnotation() } getter?.annotations?.mapTo(property.getterAnnotations) { it.serializeAnnotation() } setter?.annotations?.mapTo(property.setterAnnotations) { it.serializeAnnotation() } @@ -181,9 +178,9 @@ internal fun CirProperty.serializeProperty( internal fun CirFunction.serializeFunction( context: CirTreeSerializationContext, ): KmFunction = KmFunction( - flags = functionFlags(isExpect = context.isCommon && kind != CallableMemberDescriptor.Kind.SYNTHESIZED), name = name.name ).also { function -> + function.flags = functionFlags(isExpect = context.isCommon && kind != CallableMemberDescriptor.Kind.SYNTHESIZED) annotations.mapTo(function.annotations) { it.serializeAnnotation() } typeParameters.serializeTypeParameters(context, output = function.typeParameters) valueParameters.mapTo(function.valueParameters) { it.serializeValueParameter(context) } @@ -242,9 +239,9 @@ private fun CirConstantValue.serializeConstantValue(): KmAnnotationArgument? = w private fun CirValueParameter.serializeValueParameter( context: CirTreeSerializationContext ): KmValueParameter = KmValueParameter( - flags = valueParameterFlags(), name = name.name ).also { parameter -> + parameter.flags = valueParameterFlags() annotations.mapTo(parameter.annotations) { it.serializeAnnotation() } parameter.type = returnType.serializeType(context) varargElementType?.let { varargElementType -> @@ -258,11 +255,11 @@ private fun List.serializeTypeParameters( ) { mapIndexedTo(output) { index, cirTypeParameter -> KmTypeParameter( - flags = cirTypeParameter.typeParameterFlags(), name = cirTypeParameter.name.name, id = context.typeParameterIndexOffset + index, variance = cirTypeParameter.variance.serializeVariance() ).also { parameter -> + parameter.flags = cirTypeParameter.typeParameterFlags() cirTypeParameter.upperBounds.mapTo(parameter.upperBounds) { it.serializeType(context) } cirTypeParameter.annotations.mapTo(parameter.annotations) { it.serializeAnnotation() } } @@ -287,14 +284,16 @@ private fun CirType.serializeType( } private fun CirTypeParameterType.serializeTypeParameterType(): KmType = - KmType(typeFlags()).also { type -> + KmType().also { type -> + applyTypeFlagsTo(type) type.classifier = KmClassifier.TypeParameter(index) } private fun CirClassType.serializeClassType( context: CirTreeSerializationContext, expansion: TypeAliasExpansion = FOR_TOP_LEVEL_TYPE -): KmType = KmType(typeFlags()).also { type -> +): KmType = KmType().also { type -> + applyTypeFlagsTo(type) type.classifier = KmClassifier.Class(classifierId.toString()) arguments.mapTo(type.arguments) { it.serializeArgument(context, expansion) } outerType?.let { type.outerType = it.serializeClassType(context, expansion) } @@ -318,7 +317,7 @@ private fun CirTypeAliasType.serializeAbbreviationType( context: CirTreeSerializationContext, expansion: TypeAliasExpansion ): KmType { - val abbreviationType = KmType(typeFlags()) + val abbreviationType = KmType().also { applyTypeFlagsTo(it) } abbreviationType.classifier = KmClassifier.TypeAlias(classifierId.toString()) arguments.mapTo(abbreviationType.arguments) { it.serializeArgument(context, expansion) } return abbreviationType diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/flags.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/flags.kt index 7e485ee7f24..6f289b8ceeb 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/flags.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/metadata/flags.kt @@ -5,9 +5,7 @@ package org.jetbrains.kotlin.commonizer.metadata -import kotlinx.metadata.Flag -import kotlinx.metadata.Flags -import kotlinx.metadata.flagsOf +import kotlinx.metadata.* import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassKind @@ -59,11 +57,13 @@ internal fun CirClassConstructor.classConstructorFlags(): Flags = Flag.Constructor.HAS_NON_STABLE_PARAMETER_NAMES.takeIf { !hasStableParameterNames } ) -internal fun CirType.typeFlags(): Flags = - flagsOfNotNull( - nullableFlag, - //Flag.Type.IS_SUSPEND.takeIf { false } - ) +internal fun CirType.applyTypeFlagsTo(type: KmType) { + type.isNullable = when (this) { + is CirSimpleType -> isMarkedNullable + is CirFlexibleType -> lowerBound.isMarkedNullable + } + //Flag.Type.IS_SUSPEND.takeIf { false } +} internal fun CirTypeParameter.typeParameterFlags(): Flags = flagsOfNotNull( @@ -172,14 +172,4 @@ private inline val CirProperty.modifiersFlags: Flags Flag.Property.IS_LATEINIT.takeIf { isLateInit }, ) -private inline val CirType.nullableFlag: Flag? - get() { - val isNullable = when (this) { - is CirSimpleType -> isMarkedNullable - is CirFlexibleType -> lowerBound.isMarkedNullable - } - - return if (isNullable) Flag.Type.IS_NULLABLE else null - } - private fun flagsOfNotNull(vararg flags: Flag?): Flags = flagsOf(*listOfNotNull(*flags).toTypedArray())