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
/**
* 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].
* [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.
*
* 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
* 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) {
@@ -48,14 +50,14 @@ sealed class KotlinClassMetadata(val annotationData: 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 {
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
*/
@@ -99,7 +101,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/**
* 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.
* 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.
@@ -112,7 +114,7 @@ sealed class KotlinClassMetadata(val annotationData: 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 {
KmPackage().apply(this::accept)
@@ -175,7 +177,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
* Creates a new [KmLambda] instance from this synthetic class metadata.
* 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 {
if (isLambda) KmLambda().apply(this::accept) else null
@@ -188,7 +190,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
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).
*
* 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.
*
* @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 {
KmPackage().apply(this::accept)
@@ -398,6 +400,10 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
*/
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 {
/**
* Writes contents of [kmClass] as the class metadata.
@@ -589,7 +595,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
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.
*
* @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
*/
@@ -128,13 +128,16 @@ class KotlinModuleMetadata private constructor(
v.visitEnd()
}
/**
* Collection of methods for reading and writing [KotlinModuleMetadata].
*/
companion object {
/**
* 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.
*
* @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
@UnstableMetadataApi
@@ -6,7 +6,7 @@
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.
* 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",
level = RequiresOptIn.Level.WARNING
)
annotation class UnstableMetadataApi
@MustBeDocumented
annotation class UnstableMetadataApi
@@ -28,7 +28,7 @@ val ClassName.jvmInternalName: String get() = toJvmInternalName()
/**
* 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.
*/
fun Metadata(
@@ -48,4 +48,4 @@ fun Metadata(
extraString ?: "",
packageName ?: "",
extraInt ?: 0
)
)
@@ -54,6 +54,7 @@ class Flag(private val offset: Int, private val bitWidth: Int, private val value
operator fun invoke(flags: Flags): Boolean =
(flags ushr offset) and ((1 shl bitWidth) - 1) == value
/** @suppress deprecated in another PR */
companion object Common {
/**
* 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.",
RequiresOptIn.Level.ERROR
)
@MustBeDocumented
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
* (see `KmType.annotations` and `KmTypeParameter.annotations` JVM extensions)
*
* @param 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
* (specified in the annotation class declaration)
* @property className The fully qualified name of the annotation class
* @property arguments Explicitly specified arguments to the annotation; does not include default values for annotation parameters
* (specified in the annotation class declaration)
*/
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 =
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()
/**
* Returns string representation of this instance with `@` sign, [className], and [arguments] in parenthesis.
*/
override fun toString(): String {
val args = arguments.toList().joinToString { (k, v) -> "$k = $v" }
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]
* 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.
*
* @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")
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
* 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
@@ -690,7 +690,7 @@ class KmValueParameter(
* @property flags type parameter flags, consisting of [Flag.TypeParameter] flags
* @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 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
*/
@Suppress("DEPRECATION")
@@ -853,7 +853,7 @@ class KmType(var flags: Flags) : KmTypeVisitor() {
* Represents a version requirement on a Kotlin declaration.
*
* 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")
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
* 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
@@ -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.
*/
sealed class KmClassifier {
@@ -1103,6 +1103,9 @@ sealed class KmClassifier {
* @property type the projected type, or `null` if this is a star projection
*/
data class KmTypeProjection(var variance: KmVariance?, var type: KmType?) {
/**
* Contains default instance for star projection: [KmTypeProjection.STAR].
*/
companion object {
/**
* 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")
*/
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"
}
@@ -897,8 +897,26 @@ enum class KmVariance {
*/
@ExperimentalContracts
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,
/**
* 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,
/**
* Represents `returnsNotNull` contract effect:
* a situation when a function returns normally with any value that is not null.
*/
RETURNS_NOT_NULL,
}
@@ -910,8 +928,19 @@ enum class KmEffectType {
*/
@ExperimentalContracts
enum class KmEffectInvocationKind {
/**
* A function parameter will be invoked one time or not invoked at all.
*/
AT_MOST_ONCE,
/**
* A function parameter will be invoked exactly one time.
*/
EXACTLY_ONCE,
/**
* A function parameter will be invoked one or more times.
*/
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.
*/
enum class KmVersionRequirementLevel {
/**
* Represents a diagnostic with 'WARNING' severity.
*/
WARNING,
/**
* Represents a diagnostic with 'ERROR' severity.
*/
ERROR,
/**
* Excludes the declaration from the resolution process completely when the version requirement is not satisfied.
*/
HIDDEN,
}
@@ -928,7 +968,18 @@ enum class KmVersionRequirementLevel {
* The kind of the version that is required by a version requirement.
*/
enum class KmVersionRequirementVersionKind {
/**
* Indicates that certain language version is required.
*/
LANGUAGE_VERSION,
/**
* Indicates that certain compiler version is required.
*/
COMPILER_VERSION,
/**
* Indicates that certain API version is required.
*/
API_VERSION,
}