Enhance kotlinx-metadata-jvm KDoc: add missing documentation, apply Grazie suggestions

This commit is contained in:
Leonid Startsev
2023-06-09 13:59:28 +02:00
committed by Space Team
parent 5088c9370d
commit 654874e30f
9 changed files with 108 additions and 26 deletions
@@ -16,7 +16,7 @@ import java.util.*
import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.LazyThreadSafetyMode.PUBLICATION
/** /**
* Represents the parsed metadata of a Kotlin JVM class file. * Represents the parsed metadata of a Kotlin JVM class file. Entry point for parsing metadata on JVM.
* *
* To create an instance of [KotlinClassMetadata], first obtain an instance of [Metadata] annotation on a class file, and then call [KotlinClassMetadata.read]. * To create an instance of [KotlinClassMetadata], first obtain an instance of [Metadata] annotation on a class file, and then call [KotlinClassMetadata.read].
* [Metadata] annotation can be obtained either via reflection or created from data from a binary class file, using its constructor or helper function [kotlinx.metadata.jvm.Metadata]. * [Metadata] annotation can be obtained either via reflection or created from data from a binary class file, using its constructor or helper function [kotlinx.metadata.jvm.Metadata].
@@ -28,9 +28,11 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION
* Normally, one would need at least a [Class] and a [FileFacade], as these are two most common kinds. * Normally, one would need at least a [Class] and a [FileFacade], as these are two most common kinds.
* *
* Most of the subclasses offer a conversion method to transform metadata into a Km data structure — for example, [KotlinClassMetadata.Class.toKmClass]. * Most of the subclasses offer a conversion method to transform metadata into a Km data structure — for example, [KotlinClassMetadata.Class.toKmClass].
* Km data structures represent Kotlin declarations and offer variety of properties to introspect and alter them. * Km data structures represent Kotlin declarations and offer a variety of properties to introspect and alter them.
* Note that parsing may be lazy, depending on the implementation; therefore, one may not see an [IllegalArgumentException] indicating malformed metadata * Note that parsing may be lazy, depending on the implementation; therefore, one may not see an [IllegalArgumentException] indicating malformed metadata
* until one calls `toKmClass` or a similar method. * until one calls `toKmClass` or a similar method.
*
* @property annotationData Raw contents of the metadata represented by [Metadata] annotation in the class file.
*/ */
sealed class KotlinClassMetadata(val annotationData: Metadata) { sealed class KotlinClassMetadata(val annotationData: Metadata) {
@@ -48,14 +50,14 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/** /**
* Returns a new [KmClass] instance created from this class metadata. * Returns a new [KmClass] instance created from this class metadata.
* *
* @throws IllegalArgumentException if metadata is malformed or inconsistent and can't be transformed into [KmClass]. * @throws IllegalArgumentException if metadata is malformed or inconsistent and cannot be transformed into [KmClass].
*/ */
fun toKmClass(): KmClass = wrapIntoMetadataExceptionWhenNeeded { fun toKmClass(): KmClass = wrapIntoMetadataExceptionWhenNeeded {
KmClass().apply(this::accept) KmClass().apply(this::accept)
} }
/** /**
* Makes the given visitor visit metadata of this class. * Makes the given visitor visit the metadata of this class.
* *
* @param v the visitor that must visit this class * @param v the visitor that must visit this class
*/ */
@@ -99,7 +101,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/** /**
* Represents metadata of a class file containing a compiled Kotlin file facade. * Represents metadata of a class file containing a compiled Kotlin file facade.
* *
* File facade is a JVM class that contains declarations which do not belong to any Kotlin class: top-level functions, properties and type aliases. * File facade is a JVM class that contains declarations which do not belong to any Kotlin class: top-level functions, properties, and type aliases.
* For example, file Main.kt that contains only `fun main()` would produce a `MainKt.class` with FileFacade with this function metadata. * For example, file Main.kt that contains only `fun main()` would produce a `MainKt.class` with FileFacade with this function metadata.
* If Kotlin source file contains both classes and top-level declarations, only top-level declarations would be available in the corresponding file facade. * If Kotlin source file contains both classes and top-level declarations, only top-level declarations would be available in the corresponding file facade.
* Classes would have their own JVM classfiles and their own metadata of [Class] kind. * Classes would have their own JVM classfiles and their own metadata of [Class] kind.
@@ -112,7 +114,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/** /**
* Creates a new [KmPackage] instance from this file facade metadata. * Creates a new [KmPackage] instance from this file facade metadata.
* *
* @throws IllegalArgumentException if metadata is malformed or inconsistent and can't be transformed into [KmPackage]. * @throws IllegalArgumentException if metadata is malformed or inconsistent and cannot be transformed into [KmPackage].
*/ */
fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded { fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded {
KmPackage().apply(this::accept) KmPackage().apply(this::accept)
@@ -175,7 +177,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
* Creates a new [KmLambda] instance from this synthetic class metadata. * Creates a new [KmLambda] instance from this synthetic class metadata.
* Returns `null` if this synthetic class does not represent a lambda. * Returns `null` if this synthetic class does not represent a lambda.
* *
* @throws IllegalArgumentException if metadata is malformed or inconsistent and can't be transformed into [KmLambda]. * @throws IllegalArgumentException if metadata is malformed or inconsistent and cannot be transformed into [KmLambda].
*/ */
fun toKmLambda(): KmLambda? = wrapIntoMetadataExceptionWhenNeeded { fun toKmLambda(): KmLambda? = wrapIntoMetadataExceptionWhenNeeded {
if (isLambda) KmLambda().apply(this::accept) else null if (isLambda) KmLambda().apply(this::accept) else null
@@ -188,7 +190,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
get() = annotationData.data1.isNotEmpty() get() = annotationData.data1.isNotEmpty()
/** /**
* Makes the given visitor visit metadata of this file facade, if this synthetic class represents a Kotlin lambda * Makes the given visitor visit metadata of this file facade if this synthetic class represents a Kotlin lambda
* (`isLambda` == true). * (`isLambda` == true).
* *
* Throws [IllegalArgumentException] if this synthetic class does not represent a Kotlin lambda. * Throws [IllegalArgumentException] if this synthetic class does not represent a Kotlin lambda.
@@ -340,7 +342,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/** /**
* Creates a new [KmPackage] instance from this multi-file class part metadata. * Creates a new [KmPackage] instance from this multi-file class part metadata.
* *
* @throws IllegalArgumentException if metadata is malformed or inconsistent and can't be transformed into [KmPackage]. * @throws IllegalArgumentException if metadata is malformed or inconsistent and cannot be transformed into [KmPackage].
*/ */
fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded { fun toKmPackage(): KmPackage = wrapIntoMetadataExceptionWhenNeeded {
KmPackage().apply(this::accept) KmPackage().apply(this::accept)
@@ -398,6 +400,10 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
*/ */
class Unknown internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) class Unknown internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData)
/**
* Collection of methods for reading and writing [KotlinClassMetadata],
* as well as metadata kind constants and [COMPATIBLE_METADATA_VERSION] constant.
*/
companion object { companion object {
/** /**
* Writes contents of [kmClass] as the class metadata. * Writes contents of [kmClass] as the class metadata.
@@ -589,7 +595,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
const val FILE_FACADE_KIND = 2 const val FILE_FACADE_KIND = 2
/** /**
* A class file kind signifying that the corresponding class file is synthetic, e.g. it's a class for lambda, `$DefaultImpls` class * A class file kind signifying that the corresponding class file is synthetic, e.g. it is a class for lambda, `$DefaultImpls` class
* for interface method implementations, `$WhenMappings` class for optimized `when` over enums, etc. * for interface method implementations, `$WhenMappings` class for optimized `when` over enums, etc.
* *
* @see Metadata.kind * @see Metadata.kind
@@ -104,7 +104,7 @@ class KotlinModuleMetadata private constructor(
} }
/** /**
* Makes the given visitor visit metadata of this module file. * Makes the given visitor visit the metadata of this module file.
* *
* @param v the visitor that must visit this module file * @param v the visitor that must visit this module file
*/ */
@@ -128,13 +128,16 @@ class KotlinModuleMetadata private constructor(
v.visitEnd() v.visitEnd()
} }
/**
* Collection of methods for reading and writing [KotlinModuleMetadata].
*/
companion object { companion object {
/** /**
* Parses the given byte array with the .kotlin_module file content and returns the [KotlinModuleMetadata] instance, * Parses the given byte array with the .kotlin_module file content and returns the [KotlinModuleMetadata] instance,
* or `null` if this byte array encodes a module with an unsupported metadata version. * or `null` if this byte array encodes a module with an unsupported metadata version.
* *
* @throws IllegalArgumentException if an error happened while parsing the given byte array, * @throws IllegalArgumentException if an error happened while parsing the given byte array,
* which means that it's either not the content of a `.kotlin_module` file, or it has been corrupted. * which means that it is either not the content of a `.kotlin_module` file, or it has been corrupted.
*/ */
@JvmStatic @JvmStatic
@UnstableMetadataApi @UnstableMetadataApi
@@ -6,7 +6,7 @@
package kotlinx.metadata.jvm package kotlinx.metadata.jvm
/** /**
* Annotation marks an API that is still in development and not feature-complete or finalized. * Marks an API that is still in development and not feature-complete or finalized.
* Such an API does not provide compatibility guarantees. * Such an API does not provide compatibility guarantees.
* It can be changed in future releases without migration aids or removed without replacement. * It can be changed in future releases without migration aids or removed without replacement.
*/ */
@@ -14,4 +14,5 @@ package kotlinx.metadata.jvm
"This part of API is not yet finished, does not provide any compatibility guarantees and can be changed in the future without notice", "This part of API is not yet finished, does not provide any compatibility guarantees and can be changed in the future without notice",
level = RequiresOptIn.Level.WARNING level = RequiresOptIn.Level.WARNING
) )
@MustBeDocumented
annotation class UnstableMetadataApi annotation class UnstableMetadataApi
@@ -28,7 +28,7 @@ val ClassName.jvmInternalName: String get() = toJvmInternalName()
/** /**
* Helper function to instantiate [Metadata]. * Helper function to instantiate [Metadata].
* In contrary to direct constructor call, this one accept nullable parameters to substitute nulls with default values. * Contrary to a direct constructor call, this one accepts nullable parameters to substitute nulls with default values.
* Also, this one does not accept [Metadata.bytecodeVersion] as it is deprecated. * Also, this one does not accept [Metadata.bytecodeVersion] as it is deprecated.
*/ */
fun Metadata( fun Metadata(
@@ -54,6 +54,7 @@ class Flag(private val offset: Int, private val bitWidth: Int, private val value
operator fun invoke(flags: Flags): Boolean = operator fun invoke(flags: Flags): Boolean =
(flags ushr offset) and ((1 shl bitWidth) - 1) == value (flags ushr offset) and ((1 shl bitWidth) - 1) == value
/** @suppress deprecated in another PR */
companion object Common { companion object Common {
/** /**
* Signifies that the corresponding declaration has at least one annotation. * Signifies that the corresponding declaration has at least one annotation.
@@ -15,4 +15,5 @@ package kotlinx.metadata
"The API is related to the experimental feature \"context receivers\" (see KEEP-259) and may be changed or removed in any future release.", "The API is related to the experimental feature \"context receivers\" (see KEEP-259) and may be changed or removed in any future release.",
RequiresOptIn.Level.ERROR RequiresOptIn.Level.ERROR
) )
@MustBeDocumented
annotation class ExperimentalContextReceivers annotation class ExperimentalContextReceivers
@@ -12,17 +12,29 @@ package kotlinx.metadata
* On JVM, only annotations on type parameters and types are serialized to the Kotlin metadata * On JVM, only annotations on type parameters and types are serialized to the Kotlin metadata
* (see `KmType.annotations` and `KmTypeParameter.annotations` JVM extensions) * (see `KmType.annotations` and `KmTypeParameter.annotations` JVM extensions)
* *
* @param className the fully qualified name of the annotation class * @property className The fully qualified name of the annotation class
* @param arguments explicitly specified arguments to the annotation; does not include default values for annotation parameters * @property arguments Explicitly specified arguments to the annotation; does not include default values for annotation parameters
* (specified in the annotation class declaration) * (specified in the annotation class declaration)
*/ */
class KmAnnotation(val className: ClassName, val arguments: Map<String, KmAnnotationArgument>) { class KmAnnotation(val className: ClassName, val arguments: Map<String, KmAnnotationArgument>) {
/**
* Checks if this KmAnnotation is equal to the [other].
* Instances of KmAnnotation are equal if they have same [className] and [arguments].
*/
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
this === other || other is KmAnnotation && className == other.className && arguments == other.arguments this === other || other is KmAnnotation && className == other.className && arguments == other.arguments
/**
* Returns hash code of this instance.
* Hash code is computed based on [className] and [arguments].
*/
override fun hashCode(): Int = 31 * className.hashCode() + arguments.hashCode() override fun hashCode(): Int = 31 * className.hashCode() + arguments.hashCode()
/**
* Returns string representation of this instance with `@` sign, [className], and [arguments] in parenthesis.
*/
override fun toString(): String { override fun toString(): String {
val args = arguments.toList().joinToString { (k, v) -> "$k = $v" } val args = arguments.toList().joinToString { (k, v) -> "$k = $v" }
return "@$className($args)" return "@$className($args)"
@@ -119,7 +131,7 @@ sealed class KmAnnotationArgument {
} }
/** /**
* An annotation argument with an array type, i.e. several values of one arbitrary type. * An annotation argument with an array type, i.e., several values of one arbitrary type.
* *
* For example, in `@Foo(["a", "b", "c"])` argument of `Foo` is an `ArrayValue` with [elements] * For example, in `@Foo(["a", "b", "c"])` argument of `Foo` is an `ArrayValue` with [elements]
* being a list of three [StringValue] elements: "a", "b", and "c" (without quotes). * being a list of three [StringValue] elements: "a", "b", and "c" (without quotes).
@@ -304,7 +304,7 @@ class KmLambda : KmLambdaVisitor() {
/** /**
* Represents a constructor of a Kotlin class. * Represents a constructor of a Kotlin class.
* *
* @property flags constructor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag and [Flag.Constructor] flags * @property flags constructor flags, consisting of [Flag.HAS_ANNOTATIONS], a visibility flag and [Flag.Constructor] flags
*/ */
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class KmConstructor(var flags: Flags) : KmConstructorVisitor() { class KmConstructor(var flags: Flags) : KmConstructorVisitor() {
@@ -574,7 +574,7 @@ class KmTypeAlias(
/** /**
* Expanded type of the type alias, i.e. the full expansion of the underlying type, where all type aliases are substituted * Expanded type of the type alias, i.e. the full expansion of the underlying type, where all type aliases are substituted
* with their expanded types. If no type aliases are used in the underlying type, expanded type is equal to the underlying type. * with their expanded types. If no type aliases are used in the underlying type, the expanded type is equal to the underlying type.
*/ */
lateinit var expandedType: KmType lateinit var expandedType: KmType
@@ -690,7 +690,7 @@ class KmValueParameter(
* @property flags type parameter flags, consisting of [Flag.TypeParameter] flags * @property flags type parameter flags, consisting of [Flag.TypeParameter] flags
* @property name the name of the type parameter * @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 * @property id the id of the type parameter, useful to be able to uniquely identify the type parameter in different contexts where
* the name isn't enough (e.g. `class A<T> { fun <T> foo(t: T) }`) * the name is not enough (e.g. `class A<T> { fun <T> foo(t: T) }`)
* @property variance the declaration-site variance of the type parameter * @property variance the declaration-site variance of the type parameter
*/ */
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -853,7 +853,7 @@ class KmType(var flags: Flags) : KmTypeVisitor() {
* Represents a version requirement on a Kotlin declaration. * Represents a version requirement on a Kotlin declaration.
* *
* Version requirement is an internal feature of the Kotlin compiler and the standard Kotlin library, * Version requirement is an internal feature of the Kotlin compiler and the standard Kotlin library,
* enabled for example with the internal [kotlin.internal.RequireKotlin] annotation. * enabled, for example, with the internal [kotlin.internal.RequireKotlin] annotation.
*/ */
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class KmVersionRequirement : KmVersionRequirementVisitor() { class KmVersionRequirement : KmVersionRequirementVisitor() {
@@ -1002,7 +1002,7 @@ class KmEffectExpression : KmEffectExpressionVisitor() {
/** /**
* Optional 1-based index of the value parameter of the function, for effects which assert something about * Optional 1-based index of the value parameter of the function, for effects which assert something about
* the function parameters. The index 0 means the extension receiver parameter. * the function parameters. Index 0 means the extension receiver parameter.
*/ */
var parameterIndex: Int? = null var parameterIndex: Int? = null
@@ -1068,7 +1068,7 @@ class KmEffectExpression : KmEffectExpressionVisitor() {
} }
/** /**
* Represents a classifier of a Kotlin type. A classifier is a class, type parameter or type alias. * Represents a classifier of a Kotlin type. A classifier is a class, type parameter, or type alias.
* For example, in `MutableMap<in String?, *>`, `MutableMap` is the classifier. * For example, in `MutableMap<in String?, *>`, `MutableMap` is the classifier.
*/ */
sealed class KmClassifier { sealed class KmClassifier {
@@ -1103,6 +1103,9 @@ sealed class KmClassifier {
* @property type the projected type, or `null` if this is a star projection * @property type the projected type, or `null` if this is a star projection
*/ */
data class KmTypeProjection(var variance: KmVariance?, var type: KmType?) { data class KmTypeProjection(var variance: KmVariance?, var type: KmType?) {
/**
* Contains default instance for star projection: [KmTypeProjection.STAR].
*/
companion object { companion object {
/** /**
* Star projection (`*`). * Star projection (`*`).
@@ -1130,6 +1133,10 @@ data class KmFlexibleTypeUpperBound(var type: KmType, var typeFlexibilityId: Str
* @property patch the patch component of the version (e.g. "3" in "1.2.3") * @property patch the patch component of the version (e.g. "3" in "1.2.3")
*/ */
data class KmVersion(val major: Int, val minor: Int, val patch: Int) { data class KmVersion(val major: Int, val minor: Int, val patch: Int) {
/**
* Returns a string representation of this version in "$major.$minor.$patch" form.
*/
override fun toString(): String = "$major.$minor.$patch" override fun toString(): String = "$major.$minor.$patch"
} }
@@ -897,8 +897,26 @@ enum class KmVariance {
*/ */
@ExperimentalContracts @ExperimentalContracts
enum class KmEffectType { enum class KmEffectType {
/**
* Represents `returns(value)` contract effect:
* a situation when a function returns normally with the specified return value.
* Return value is stored in the [KmEffect.constructorArguments].
*/
RETURNS_CONSTANT, RETURNS_CONSTANT,
/**
* Represents `callsInPlace` contract effect:
* A situation when the referenced lambda is invoked in place (optionally) specified number of times.
*
* Referenced lambda is stored in the [KmEffect.constructorArguments].
* Number of invocations, if specified, is stored in [KmEffect.invocationKind].
*/
CALLS, CALLS,
/**
* Represents `returnsNotNull` contract effect:
* a situation when a function returns normally with any value that is not null.
*/
RETURNS_NOT_NULL, RETURNS_NOT_NULL,
} }
@@ -910,8 +928,19 @@ enum class KmEffectType {
*/ */
@ExperimentalContracts @ExperimentalContracts
enum class KmEffectInvocationKind { enum class KmEffectInvocationKind {
/**
* A function parameter will be invoked one time or not invoked at all.
*/
AT_MOST_ONCE, AT_MOST_ONCE,
/**
* A function parameter will be invoked exactly one time.
*/
EXACTLY_ONCE, EXACTLY_ONCE,
/**
* A function parameter will be invoked one or more times.
*/
AT_LEAST_ONCE, AT_LEAST_ONCE,
} }
@@ -919,8 +948,19 @@ enum class KmEffectInvocationKind {
* Severity of the diagnostic reported by the compiler when a version requirement is not satisfied. * Severity of the diagnostic reported by the compiler when a version requirement is not satisfied.
*/ */
enum class KmVersionRequirementLevel { enum class KmVersionRequirementLevel {
/**
* Represents a diagnostic with 'WARNING' severity.
*/
WARNING, WARNING,
/**
* Represents a diagnostic with 'ERROR' severity.
*/
ERROR, ERROR,
/**
* Excludes the declaration from the resolution process completely when the version requirement is not satisfied.
*/
HIDDEN, HIDDEN,
} }
@@ -928,7 +968,18 @@ enum class KmVersionRequirementLevel {
* The kind of the version that is required by a version requirement. * The kind of the version that is required by a version requirement.
*/ */
enum class KmVersionRequirementVersionKind { enum class KmVersionRequirementVersionKind {
/**
* Indicates that certain language version is required.
*/
LANGUAGE_VERSION, LANGUAGE_VERSION,
/**
* Indicates that certain compiler version is required.
*/
COMPILER_VERSION, COMPILER_VERSION,
/**
* Indicates that certain API version is required.
*/
API_VERSION, API_VERSION,
} }