Enhance documentation for KotlinClassMetadata

This commit is contained in:
Leonid Startsev
2023-01-18 18:48:24 +01:00
committed by Space Team
parent f327d68fe0
commit 5999c2b324
6 changed files with 67 additions and 15 deletions
@@ -18,12 +18,6 @@ sealed class JvmMemberSignature {
abstract val name: String
abstract val descriptor: String
@Deprecated("Use descriptor instead", ReplaceWith("descriptor"), level = DeprecationLevel.WARNING)
val desc: String get() = descriptor
@Deprecated("asString() is deprecated as redundant. Use toString() instead", ReplaceWith("toString()"), level = DeprecationLevel.WARNING)
fun asString(): String = toString()
/**
* Returns a string representation of the signature.
*
@@ -32,6 +26,18 @@ sealed class JvmMemberSignature {
* In case of a field [name] and [descriptor] are concatenated with `:` separator, e.g. `value:Ljava/lang/String;`
*/
abstract override fun toString(): String
// Two following declarations are deprecated since 0.6.1, should be error in 0.7.0+
@Deprecated("Deprecated for removal. Use descriptor instead", ReplaceWith("descriptor"), level = DeprecationLevel.WARNING)
val desc: String get() = descriptor
@Deprecated(
"asString() is deprecated as redundant. Use toString() instead",
ReplaceWith("toString()"),
level = DeprecationLevel.WARNING
)
fun asString(): String = toString()
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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:Suppress("DEPRECATION")
@@ -20,11 +20,20 @@ import kotlin.LazyThreadSafetyMode.PUBLICATION
*
* 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].
*
* [KotlinClassMetadata] itself does not have any meaningful methods or properties; to work with it, it is required to do a `when` over subclasses.
* Different subclasses of [KotlinClassMetadata] represent different kinds of class files produced by Kotlin compiler.
* It is recommended to study documentation for each subclass and decide what subclasses one has to handle in the `when` expression,
* trying to cover as much as possible.
* Normally, one would need at least a [Class] and a [FileFacade], as these are two most common kinds.
*/
sealed class KotlinClassMetadata(val annotationData: Metadata) {
/**
* Represents metadata of a class file containing a declaration of a Kotlin class.
*
* Anything that does not belong to a Kotlin class (top-level declarations) is not present in
* [Class] metadata, even if such declaration was in the same source file. See [FileFacade] for details.
*/
class Class internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) {
private val classData by lazy(PUBLICATION) {
@@ -34,7 +43,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
}
/**
* Visits metadata of this class with a new [KmClass] instance and returns that instance.
* Returns a new [KmClass] instance created from this class metadata.
*/
fun toKmClass(): KmClass =
KmClass().apply(this::accept)
@@ -83,6 +92,11 @@ 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.
* 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.
*/
class FileFacade internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) {
private val packageData by lazy(PUBLICATION) {
@@ -92,7 +106,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
}
/**
* Visits metadata of this file facade with a new [KmPackage] instance and returns that instance.
* Creates a new [KmPackage] instance from this file facade metadata.
*/
fun toKmPackage(): KmPackage =
KmPackage().apply(this::accept)
@@ -151,8 +165,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
}
/**
* Visits metadata of this synthetic class with a new [KmLambda] instance and returns that instance.
*
* Creates a new [KmLambda] instance from this synthetic class metadata.
* Returns `null` if this synthetic class does not represent a lambda.
*/
fun toKmLambda(): KmLambda? =
@@ -223,6 +236,32 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/**
* Represents metadata of a class file containing a compiled multi-file class facade.
*
* Multi-file class facade is a facade file produced from several Kotlin source files marked with [JvmMultifileClass] and same [JvmName].
* It does not have any declarations; it only contains [partClassNames] to indicate where individual parts are located.
*
* Consider the following example.
* Suppose we have two files, partOne.kt and partTwo.kt:
*
* ```
* // partOne.kt
* @file:JvmMultifileClass
* @file:JvmName("MultiFileClass")
*
* fun partOne(): String = "one"
*
* // partTwo.kt
* @file:JvmMultifileClass
* @file:JvmName("MultiFileClass")
*
* fun partTwo(): String = "two"
* ```
*
* In this case, there would be three classfiles produced by the compiler, each with its own metadata.
* Metadata for `MultiFileClass.class` would be of type [MultiFileClassFacade]
* and contain [partClassNames] that would indicate class file names for the parts: `[MultiFileClass__PartOneKt, MultiFileClass__PartTwoKt]`.
* Using these names, you can load metadata from those classes with type [MultiFileClassPart].
*
* @see MultiFileClassPart
* @see JvmMultifileClass
*/
class MultiFileClassFacade internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) {
@@ -268,8 +307,13 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
/**
* Represents metadata of a class file containing a compiled multi-file class part, i.e. an internal class with method bodies
* and their metadata, accessed only from the corresponding facade.
* and their metadata, accessed only from the corresponding [facade][MultiFileClassFacade]. Just like [FileFacade], this metadata contains only top-level declarations,
* as classes have their own one.
*
* It does not contain any references to other parts; to locate all the parts, one should construct a corresponding
* [facade][MultiFileClassFacade] beforehand.
*
* @see MultiFileClassFacade
* @see JvmMultifileClass
*/
class MultiFileClassPart internal constructor(annotationData: Metadata) : KotlinClassMetadata(annotationData) {
@@ -286,7 +330,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) {
get() = annotationData.extraString
/**
* Visits metadata of this multi-file class part with a new [KmPackage] instance and returns that instance.
* Creates a new [KmPackage] instance from this multi-file class part metadata.
*/
fun toKmPackage(): KmPackage =
KmPackage().apply(this::accept)
@@ -11,7 +11,7 @@ package kotlinx.metadata.jvm
* It can be changed in future releases without migration aids or removed without replacement.
*/
@RequiresOptIn(
"This part of API is not yet finished, does not provide 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
)
annotation class UnstableMetadataApi
@@ -18,6 +18,7 @@ fun ClassName.toJvmInternalName(): String =
if (this.isLocalClassName()) substring(1)
else replace('.', '$')
// Deprecated since 0.6.1, should be error in 0.7.0+
@Deprecated(
"Renamed to toJvmInternalName() to avoid confusion with String properties",
ReplaceWith("toJvmInternalName()"),
@@ -25,6 +25,7 @@ typealias ClassName = String // Not a value class because of Java usages
*/
fun ClassName.isLocalClassName(): Boolean = this.startsWith(".")
// Deprecated since 0.6.1, should be error in 0.7.0+
@Deprecated(
"Renamed to isLocalClassName() to avoid confusion with String properties",
ReplaceWith("isLocalClassName()"),
@@ -12,7 +12,7 @@ package kotlinx.metadata
* Therefore, it does not provide any compatibility guarantees.
*/
@RequiresOptIn(
"The API uses 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
)
annotation class ExperimentalContextReceivers