From 0a573a803d8d8a4345ddcaffc322a0ab4698ba76 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Mon, 19 Jun 2023 12:13:55 +0200 Subject: [PATCH] Update and clarify documentation for kotlinx-metadata-jvm attributes: - Review fixes - Clarify KmClass.isData and enhance nodes documentaiton to mention extensions --- .../src/kotlinx/metadata/jvm/JvmAttributes.kt | 34 ++- .../jvm/src/kotlinx/metadata/jvm/JvmFlag.kt | 2 +- .../metadata/test/FlagDelegatesTest.kt | 55 +++++ .../src/kotlinx/metadata/Attributes.kt | 216 ++++++++++++------ .../src/kotlinx/metadata/Modifiers.kt | 23 +- .../src/kotlinx/metadata/Nodes.kt | 42 +++- 6 files changed, 276 insertions(+), 96 deletions(-) diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt index 2216b0a24af..300bfa4b33e 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmAttributes.kt @@ -16,28 +16,42 @@ import org.jetbrains.kotlin.metadata.deserialization.Flags 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 + * Applicable to a property declared in an interface's companion object. + * Indicates 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. + * Returns `false` 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` + * Applicable to an interface compiled with -Xjvm-default=all or all-compatibility. + * True if interface has method bodies in it, false if Kotlin compiler moved all interface method bodies into a nested `DefaultImpls` * class. + * + * Method bodies are also present in interface method if it has `@JvmDefault` annotation (now deprecated). + * + * Check [documentation](https://kotlinlang.org/docs/java-to-kotlin-interop.html#compatibility-modes-for-default-methods) for more details. + * + * @see JvmDefault + * @see JvmDefaultWithCompatibility + * @see JvmDefaultWithoutCompatibility */ 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. + * Indicates if an interface was 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. + * In compatibility mode Kotlin/JVM compiler generates method bodies directly in the interface, + * and also generates bridges in a nested `DefaultImpls` class. + * Bridges are intended for use by already existing clients, + * such as compiled Java code or Kotlin code compiled without all/all-compatibility setting. + * + * Also, can be a result of compiling interface with `@JvmDefaultWithCompatibility` annotation. + * Check [documentation](https://kotlinlang.org/docs/java-to-kotlin-interop.html#compatibility-modes-for-default-methods) for more details. + * + * @see JvmDefaultWithCompatibility + * @see JvmDefaultWithoutCompatibility */ 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 f1ba5973593..6556f4a53ab 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmFlag.kt @@ -62,7 +62,7 @@ object JvmFlag { * clients compiled without all-compatibility. */ @JvmField - @Deprecated("$prefix KmProperty.isCompiledInCompatibilityMode") + @Deprecated("$prefix KmClass.isCompiledInCompatibilityMode") val IS_COMPILED_IN_COMPATIBILITY_MODE = booleanFlag(JF.IS_COMPILED_IN_COMPATIBILITY_MODE) } diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt index a9029716a54..2cacccb37a2 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/FlagDelegatesTest.kt @@ -160,4 +160,59 @@ class FlagDelegatesTest { } } + + class X { + + val x2 = 2 + fun x22() = 2 + val x3 = x22() + + companion object Y { + val y2 = 2 + const val y3 = 3 + } + } + + @Test + fun testHasConstantExample() { + class X { + val a = 1 + val b = a + + fun x() = 2 + val c = x() + } + + val props = X::class.java.readMetadataAsKmClass().properties.associateBy { it.name } + props.values.forEach { assertFalse(it.isConst, it.name) } + assertTrue(props.getValue("a").hasConstant) + assertTrue(props.getValue("b").hasConstant) + assertFalse(props.getValue("c").hasConstant) + } + + interface I { + val x: Int + } + + class Foo(i: I) : I by i { + val props: Map = mapOf() + + val y: Int by props + } + + @Test + fun testDelegation() { + val foo = Foo::class.java.readMetadataAsKmClass() + val props = foo.properties.associateBy { it.name } + with(props["x"]!!) { + assertEquals(MemberKind.DELEGATION, kind) + assertFalse(isDelegated) + assertFalse(getter.isNotDefault) + } + with(props["y"]!!) { + assertEquals(MemberKind.DECLARATION, kind) + assertTrue(isDelegated) + assertTrue(getter.isNotDefault) + } + } } diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt index 9c3454ebd25..792208cc15f 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Attributes.kt @@ -19,65 +19,79 @@ import org.jetbrains.kotlin.metadata.deserialization.Flags as ProtoFlags // --- ANNOTATIONS --- /** - * Signifies that the corresponding class has at least one annotation. + * Indicates 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 + * metadata, but directly to 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmClass.hasAnnotations by annotationsOn(KmClass::flags) /** - * Signifies that the corresponding constructor has at least one annotation. + * Indicates 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 + * metadata, but directly to 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmConstructor.hasAnnotations by annotationsOn(KmConstructor::flags) /** - * Signifies that the corresponding function has at least one annotation. + * Indicates 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 + * metadata, but directly to 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmFunction.hasAnnotations by annotationsOn(KmFunction::flags) /** - * Signifies that the corresponding property has at least one annotation. + * Indicates 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 + * metadata, but directly to 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmProperty.hasAnnotations by annotationsOn(KmProperty::flags) /** - * Signifies that the corresponding property accessor has at least one annotation. + * Indicates that the corresponding property accessor 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 + * metadata, but directly to 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 accessor has no annotations. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmPropertyAccessorAttributes.hasAnnotations by annotationsOn(KmPropertyAccessorAttributes::flags) /** - * Signifies that the corresponding value parameter has at least one annotation. + * Indicates 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 + * metadata, but directly to 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files. */ var KmValueParameter.hasAnnotations by annotationsOn(KmValueParameter::flags) /** - * Signifies that the corresponding type alias has at least one annotation. + * Indicates 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. + * + * Only annotations with [AnnotationRetention.BINARY] and [AnnotationRetention.RUNTIME] are written to the class files and metadata. */ var KmTypeAlias.hasAnnotations by annotationsOn(KmTypeAlias::flags) @@ -86,17 +100,22 @@ var KmTypeAlias.hasAnnotations by annotationsOn(KmTypeAlias::flags) // --- CLASS --- /** - * Represents modality of a corresponding class + * Represents modality of the corresponding class. + * + * Modality determines when and where it is possible to extend/implement a class/interface. */ var KmClass.modality: Modality by modalityDelegate(KmClass::flags) /** - * Represents visibility of a corresponding class + * Represents visibility of the corresponding class. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ var KmClass.visibility: Visibility by visibilityDelegate(KmClass::flags) /** - * Represents kind of a corresponding class + * Represents kind of the corresponding class — whether it is a regular class or an interface, companion object, et cetera. */ var KmClass.kind: ClassKind by EnumFlagDelegate( KmClass::flags, @@ -106,223 +125,285 @@ var KmClass.kind: ClassKind by EnumFlagDelegate( ) /** - * Signifies that the corresponding class is `inner`. + * Indicates that the corresponding class is `inner`. */ var KmClass.isInner: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_INNER)) /** - * Signifies that the corresponding class is `data`. + * Indicates that the corresponding `class` or `object` is `data`. + * Always false for other kinds. */ var KmClass.isData: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_DATA)) /** - * Signifies that the corresponding class is `external`. + * Indicates that the corresponding class is `external`. */ var KmClass.isExternal: Boolean by classBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_CLASS)) /** - * Signifies that the corresponding class is `expect`. + * Indicates 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. + * Indicates 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. + * Note that it does not 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`. + * Indicates that the corresponding class is a functional interface, i.e., marked with the keyword `fun`. + * + * Always `false` if [KmClass.kind] is not an interface. */ 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. + * Indicates that the corresponding enum class has synthetic ".entries" property in bytecode. + * + * Always `false` if [KmClass.kind] is not an enum. + * Enum classes always have enum entries property starting from Kotlin 1.9.0. */ var KmClass.hasEnumEntries: Boolean by classBooleanFlag(Flag(ProtoFlags.HAS_ENUM_ENTRIES)) // --- CONSTRUCTOR --- /** - * Represents visibility of a corresponding constructor. + * Represents visibility of the corresponding constructor. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ 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. + * Indicates 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. + * Indicates that the corresponding constructor has non-stable parameter names, i.e., cannot be called with named arguments. + * + * Currently, this attribute is Kotlin/Native-specific and is never set by Kotlin/JVM compiler. + * This may be changed in the future. */ var KmConstructor.hasNonStableParameterNames: Boolean by constructorBooleanFlag(Flag(ProtoFlags.IS_CONSTRUCTOR_WITH_NON_STABLE_PARAMETER_NAMES)) // --- FUNCTION --- /** - * Represents kind of a corresponding function + * Represents kind of the corresponding function. + * + * Kind indicates the origin of a declaration within a containing class. For details, see [MemberKind]. */ var KmFunction.kind: MemberKind by memberKindDelegate(KmFunction::flags) /** - * Represents visibility of a corresponding function + * Represents visibility of the corresponding function. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ var KmFunction.visibility: Visibility by visibilityDelegate(KmFunction::flags) /** - * Represents modality of a corresponding function. + * Represents modality of the corresponding function. + * + * Modality determines when and where it is possible or mandatory to override a declaration. + * For additional details, see [Modality]. + * + * [Modality.SEALED] is not applicable for [KmFunction] and setting it as a value results in undefined behavior. */ var KmFunction.modality: Modality by modalityDelegate(KmFunction::flags) /** - * Signifies that the corresponding function is `operator`. + * Indicates that the corresponding function is `operator`. */ var KmFunction.isOperator: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_OPERATOR)) /** - * Signifies that the corresponding function is `infix`. + * Indicates that the corresponding function is `infix`. */ var KmFunction.isInfix: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_INFIX)) /** - * Signifies that the corresponding function is `inline`. + * Indicates that the corresponding function is `inline`. */ var KmFunction.isInline: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_INLINE)) /** - * Signifies that the corresponding function is `tailrec`. + * Indicates that the corresponding function is `tailrec`. */ var KmFunction.isTailrec: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_TAILREC)) /** - * Signifies that the corresponding function is `external`. + * Indicates that the corresponding function is `external`. */ var KmFunction.isExternal: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_FUNCTION)) /** - * Signifies that the corresponding function is `suspend`. + * Indicates that the corresponding function is `suspend`. */ var KmFunction.isSuspend: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_SUSPEND)) /** - * Signifies that the corresponding function is `expect`. + * Indicates 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. + * Indicates that the corresponding function has non-stable parameter names, i.e., cannot be called with named arguments. + * + * Currently, this attribute is Kotlin/Native-specific and is never set by Kotlin/JVM compiler. + * This may be changed in the future. */ var KmFunction.hasNonStableParameterNames: Boolean by functionBooleanFlag(Flag(ProtoFlags.IS_FUNCTION_WITH_NON_STABLE_PARAMETER_NAMES)) // --- PROPERTY --- /** - * Represents visibility of a corresponding property + * Represents visibility of the corresponding property. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ var KmProperty.visibility: Visibility by visibilityDelegate(KmProperty::flags) /** - * Represents modality of a corresponding property. + * Represents modality of the corresponding property. + * + * Modality determines when and where it is possible or mandatory to override a declaration. + * For additional details, see [Modality]. + * + * [Modality.SEALED] is not applicable for [KmProperty] and setting it as a value results in undefined behavior. */ var KmProperty.modality: Modality by modalityDelegate(KmProperty::flags) /** - * Represents kind of a corresponding property + * Represents kind of the corresponding property. + * + * Kind indicates the origin of a declaration within a containing class. For details, see [MemberKind]. */ var KmProperty.kind: MemberKind by memberKindDelegate(KmProperty::flags) /** - * Signifies that the corresponding property is `var`. + * Indicates that the corresponding property is `var`. */ var KmProperty.isVar: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_VAR)) /** - * Signifies that the corresponding property has a getter. + * Indicates 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. + * Indicates that the corresponding property has a setter. */ var KmProperty.hasSetter: Boolean by propertyBooleanFlag(Flag(ProtoFlags.HAS_SETTER)) /** - * Signifies that the corresponding property is `const`. + * Indicates that the corresponding property is `const`. */ var KmProperty.isConst: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_CONST)) /** - * Signifies that the corresponding property is `lateinit`. + * Indicates 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 + * Indicates 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. + * + * Not to be confused with [KmProperty.isConst], because `const` modifier is applicable only to properties on top-level and inside objects, + * while property in a regular class can also have constant value. + * Whether the property has a constant value is ultimately decided by the compiler and its optimizations. + * Generally, a property initializer that can be computed in compile time is likely to have a constant value written to the bytecode. + * In the following example, properties `a` and `b` have `hasConstant = true`, while `c` has `hasConstant = false`: + * + * ``` + * class X { + * val a = 1 + * val b = a + * + * fun x() = 2 + * val c = x() + * } + * ``` */ var KmProperty.hasConstant: Boolean by propertyBooleanFlag(Flag(ProtoFlags.HAS_CONSTANT)) /** - * Signifies that the corresponding property is `external`. + * Indicates 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. + * Indicates that the corresponding property is a delegated property. + * + * Not to be confused with interface delegation. + * If a property was produced by interface delegation, it would have the corresponding [KmProperty.kind]. */ var KmProperty.isDelegated: Boolean by propertyBooleanFlag(Flag(ProtoFlags.IS_DELEGATED)) /** - * Signifies that the corresponding property is `expect`. + * Indicates 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. + * Represents visibility of the corresponding property accessor. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ var KmPropertyAccessorAttributes.visibility: Visibility by visibilityDelegate(KmPropertyAccessorAttributes::flags) /** - * Represents modality of a corresponding property accessor. + * Represents modality of the corresponding property accessor. + * + * Modality determines when and where it is possible or mandatory to override a declaration. + * For additional details, see [Modality]. + * + * [Modality.SEALED] is not applicable for [KmPropertyAccessorAttributes] and setting it as a value results in undefined behavior. */ 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. + * Indicates that the corresponding property accessor is not default, i.e. it has a body and/or annotations in the source code, + * or the property is delegated. */ var KmPropertyAccessorAttributes.isNotDefault: Boolean by propertyAccessorBooleanFlag(Flag(ProtoFlags.IS_NOT_DEFAULT)) /** - * Signifies that the corresponding property accessor is `external`. + * Indicates that the corresponding property accessor is `external`. */ var KmPropertyAccessorAttributes.isExternal: Boolean by propertyAccessorBooleanFlag(Flag(ProtoFlags.IS_EXTERNAL_ACCESSOR)) /** - * Signifies that the corresponding property accessor is `inline`. + * Indicates that the corresponding property accessor is `inline`. */ var 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. + * Indicates 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(FlagImpl(0, 1, 1)) /** - * Signifies that the corresponding type is `suspend`. + * Indicates that the corresponding type is `suspend`. */ var KmType.isSuspend: Boolean by typeBooleanFlag(FlagImpl(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). + * Indicates 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( FlagImpl( @@ -334,14 +415,17 @@ var KmType.isDefinitelyNonNull: Boolean by typeBooleanFlag( /** - * Signifies that the corresponding type parameter is `reified`. + * Indicates that the corresponding type parameter is `reified`. */ var KmTypeParameter.isReified: Boolean by BooleanFlagDelegate(KmTypeParameter::flags, FlagImpl(0, 1, 1)) // --- TYPE ALIAS --- /** - * Represents visibility of a corresponding type alias. + * Represents visibility of the corresponding type alias. + * + * Note that Kotlin metadata has an extended list of visibilities; some of them are non-denotable. + * For additional details, see [Visibility]. */ var KmTypeAlias.visibility: Visibility by visibilityDelegate(KmTypeAlias::flags) @@ -350,7 +434,7 @@ var KmTypeAlias.visibility: Visibility by visibilityDelegate(KmTypeAlias::flags) /** - * Signifies that the corresponding value parameter declares a default value. Note that the default value itself can be a complex + * Indicates 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. @@ -358,19 +442,19 @@ var KmTypeAlias.visibility: Visibility by visibilityDelegate(KmTypeAlias::flags) var KmValueParameter.declaresDefaultValue: Boolean by valueParameterBooleanFlag(Flag(ProtoFlags.DECLARES_DEFAULT_VALUE)) /** - * Signifies that the corresponding value parameter is `crossinline`. + * Indicates 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`. + * Indicates 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. + * Indicates 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. @@ -379,7 +463,7 @@ var KmValueParameter.isNoinline: Boolean by valueParameterBooleanFlag(Flag(Proto 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`. + * Indicates 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. diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt index 8f84b3ecc36..0afa0c1a392 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Modifiers.kt @@ -12,10 +12,13 @@ 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! +// Pay attention to the order of enums in this file! +// Order of enum values is directly linked to order of corresponding protobuf enums in org.jetbrains.kotlin.metadata.ProtoBuf. +// Changes in the binary format should be reflected in the protobuf and therefore in enums in this file. +// Arbitrary reordering of enum members here will likely break deserialization. /** - * Represents visibility level (also known as access level) of a corresponding declaration. + * Represents visibility level (also known as access level) of the corresponding declaration. * Some of these visibilities may be non-denotable in Kotlin. */ enum class Visibility(kind: Int) { @@ -72,7 +75,9 @@ enum class Visibility(kind: Int) { } /** - * Represents modality of a corresponding declaration. + * Represents modality of the corresponding declaration. + * + * Modality determines when and where it is possible to extend/override a class/member. */ enum class Modality(kind: Int) { /** @@ -93,8 +98,8 @@ enum class Modality(kind: Int) { /** * 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. + * Pay attention that this modality is not applicable to class members. + * Setting it as a value for member modality leads to an undefined behavior. */ SEALED(ProtoModality.SEALED_VALUE) ; @@ -103,11 +108,11 @@ enum class Modality(kind: Int) { } /** - * Represents the nature of a corresponding class. + * Represents the kind of the corresponding class, i.e., the way it is declared in the source code. */ enum class ClassKind(kind: Int) { /** - * Signifies that the corresponding class is a usual `class`. + * Signifies that the corresponding class is a usual or anonymous class. */ CLASS(ProtoClassKind.CLASS_VALUE), @@ -132,7 +137,7 @@ enum class ClassKind(kind: Int) { ANNOTATION_CLASS(ProtoClassKind.ANNOTATION_CLASS_VALUE), /** - * Signifies that the corresponding class is a non-companion `object`. + * Signifies that the corresponding class is a non-companion, singleton `object`. */ OBJECT(ProtoClassKind.OBJECT_VALUE), @@ -169,7 +174,7 @@ enum class MemberKind(kind: Int) { * 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]. + * Not to be confused with property delegation which is denoted by [KmProperty.isDelegated]. */ DELEGATION(ProtoMemberKind.DELEGATION_VALUE), diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt index 82bcd0b3f62..8e8c94aefd2 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/Nodes.kt @@ -33,6 +33,10 @@ interface KmDeclarationContainer { /** * Represents a Kotlin class. + * + * 'Class' here is used in a broad sense and includes interfaces, enum classes, companion objects, et cetera. + * Precise kind of the class can be obtained via [KmClass.kind]. + * Various class attributes can be read and manipulated via extension properties, such as [KmClass.visibility] or [KmClass.isData]. */ @Suppress("DEPRECATION") class KmClass : KmClassVisitor(), KmDeclarationContainer { @@ -306,7 +310,8 @@ class KmLambda : KmLambdaVisitor() { /** * Represents a constructor of a Kotlin class. * - * @property flags constructor flags, consisting of [Flag.HAS_ANNOTATIONS], a visibility flag and [Flag.Constructor] flags + * Various constructor attributes can be read and manipulated via extension properties, + * such as [KmConstructor.visibility] or [KmConstructor.isSecondary]. */ @Suppress("DEPRECATION") class KmConstructor @Deprecated(flagsCtorDeprecated) constructor( @@ -357,7 +362,9 @@ class KmConstructor @Deprecated(flagsCtorDeprecated) constructor( /** * Represents a Kotlin function declaration. * - * @property flags function flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Function] flags + * Various function attributes can be read and manipulated via extension properties, + * such as [KmFunction.visibility] or [KmFunction.isSuspend]. + * * @property name the name of the function */ @Suppress("DEPRECATION") @@ -464,8 +471,9 @@ class KmFunction @Deprecated(flagsCtorDeprecated) constructor( /** * 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]. + * Attributes can be read and written using extension properties, e.g. [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. */ public class KmPropertyAccessorAttributes internal constructor(internal var flags: Int) { public constructor() : this(0) @@ -474,7 +482,11 @@ public class KmPropertyAccessorAttributes internal constructor(internal var flag /** * Represents a Kotlin property declaration. * - * @property flags property flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Property] flags + * Various property attributes can be read and manipulated via extension properties, + * such as [KmProperty.visibility] or [KmProperty.isVar]. + * + * Getter and setter attributes are available separately via extensions on [KmProperty.getter] and [KmProperty.setter] correspondingly. + * * @property name the name of the property */ @Suppress("DEPRECATION") @@ -489,7 +501,7 @@ class KmProperty @Deprecated(flagsCtorDeprecated) constructor( /** * Attributes of the getter of this property. - * Attributes can be retrieved with extension functions, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. + * Attributes can be retrieved with extension properties, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. * * Getter for property is always present, hence return type of this function is non-nullable. */ @@ -497,7 +509,7 @@ class KmProperty @Deprecated(flagsCtorDeprecated) constructor( /** * Attributes of the setter of this property. - * Attributes can be retrieved with extension functions, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. + * Attributes can be retrieved with extension properties, such as [KmPropertyAccessorAttributes.visibility] or [KmPropertyAccessorAttributes.isNotDefault]. * * Returns null if setter is absent, i.e. [KmProperty.isVar] is false. */ @@ -635,7 +647,9 @@ class KmProperty @Deprecated(flagsCtorDeprecated) constructor( /** * Represents a Kotlin type alias declaration. * - * @property flags type alias flags, consisting of [Flag.HAS_ANNOTATIONS] and visibility flag + * Various type alias attributes can be read and manipulated via extension properties, + * such as [KmTypeAlias.visibility] or [KmTypeAlias.hasAnnotations]. + * * @property name the name of the type alias */ @Suppress("DEPRECATION") @@ -720,7 +734,9 @@ class KmTypeAlias @Deprecated(flagsCtorDeprecated) constructor( /** * Represents a value parameter of a Kotlin constructor, function or property setter. * - * @property flags value parameter flags, consisting of [Flag.ValueParameter] flags + * Various value parameter attributes can be read and manipulated via extension properties, + * such as [KmValueParameter.declaresDefaultValue]. + * * @property name the name of the value parameter */ @Suppress("DEPRECATION") @@ -774,7 +790,9 @@ class KmValueParameter @Deprecated(flagsCtorDeprecated) constructor( /** * Represents a type parameter of a Kotlin class, function, property or type alias. * - * @property flags type parameter flags, consisting of [Flag.TypeParameter] flags + * Various type parameter attributes can be read and manipulated via extension properties, + * such as [KmTypeParameter.isReified]. + * * @property name the name of the type parameter * @property id the id of the type parameter, useful to be able to uniquely identify the type parameter in different contexts where * the name is not enough (e.g. `class A { fun foo(t: T) }`) @@ -822,7 +840,8 @@ class KmTypeParameter @Deprecated(flagsCtorDeprecated) constructor( /** * Represents a type. * - * @property flags type flags, consisting of [Flag.Type] flags + * Various type attributes can be read and manipulated via extension properties, + * such as [KmType.isNullable]. */ @Suppress("DEPRECATION") class KmType @Deprecated(flagsCtorDeprecated) constructor( @@ -1086,6 +1105,9 @@ class KmEffect( * * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format * may change in a subsequent release. + * + * Various effect expression attributes can be read and manipulated via extension properties, + * such as [KmEffectExpression.isNegated]. */ @ExperimentalContracts @Suppress("DEPRECATION")