[KLIB] ABI reader: More verbose KDocs

^KT-54402
This commit is contained in:
Dmitriy Dolovov
2023-08-04 00:06:39 +02:00
committed by Space Team
parent a20db23b1f
commit 18f9ada676
3 changed files with 192 additions and 20 deletions
@@ -45,11 +45,19 @@ interface AbiSignatureVersion {
val description: String?
companion object {
/** All [AbiSignatureVersion]s supported by the current implementation of the ABI reader. */
val allSupportedByAbiReader: List<AbiSignatureVersion> get() = AbiSignatureVersions.Supported.entries
/**
* A function to get an instance of [AbiSignatureVersion] by the unique [versionNumber].
*/
fun resolveByVersionNumber(versionNumber: Int): AbiSignatureVersion = AbiSignatureVersions.resolveByVersionNumber(versionNumber)
}
}
/**
* A set of ABI signatures for a specific [AbiDeclaration]. This set can contain at most one signature per an [AbiSignatureVersion].
*/
@ExperimentalLibraryAbiReader
interface AbiSignatures {
/**
@@ -91,14 +99,31 @@ value class AbiCompoundName(val value: String) : Comparable<AbiCompoundName> {
require(AbiQualifiedName.SEPARATOR !in value) { "Compound name contains illegal characters: $value" }
}
/** All name segments comprising this compound name. */
val nameSegments: List<AbiSimpleName> get() = value.split(SEPARATOR).map(::AbiSimpleName)
/** The count of name segments comprising this compound name. */
val nameSegmentsCount: Int get() = value.count { it == SEPARATOR } + 1
/** The right-most name segment of this compound name. */
val simpleName: AbiSimpleName get() = AbiSimpleName(value.substringAfterLast(SEPARATOR))
override fun compareTo(other: AbiCompoundName) = value.compareTo(other.value)
override fun toString() = value
/**
* Whether a declaration with `this` instance of [AbiCompoundName] is a container of a declaration with `member` [AbiCompoundName].
*
* Examples:
* ```
* AbiCompoundName("") isContainerOf AbiCompoundName(<any>) == true
* AbiCompoundName("foo.bar") isContainerOf AbiCompoundName("foo.bar.baz.qux") == true
* AbiCompoundName("foo.bar") isContainerOf AbiCompoundName("foo.bar.baz") == true
* AbiCompoundName("foo.bar") isContainerOf AbiCompoundName("foo.barbaz") == false
* AbiCompoundName("foo.bar") isContainerOf AbiCompoundName("foo.bar") == false
* AbiCompoundName("foo.bar") isContainerOf AbiCompoundName("foo") == false
* ```
*/
infix fun isContainerOf(member: AbiCompoundName): Boolean {
val containerName = value
return when (val containerNameLength = containerName.length) {
@@ -114,6 +139,7 @@ value class AbiCompoundName(val value: String) : Comparable<AbiCompoundName> {
}
companion object {
/** The symbol that is used for separation of individual name segments in [AbiCompoundName]. */
const val SEPARATOR = '.'
}
}
@@ -136,10 +162,20 @@ data class AbiQualifiedName(val packageName: AbiCompoundName, val relativeName:
override fun toString() = "$packageName$SEPARATOR$relativeName"
companion object {
/**
* The symbol that is used to separate the package name from the relative declaration name in
* the single-string representation of [AbiQualifiedName].
*/
const val SEPARATOR = '/'
}
}
/**
* The common interface for all declarations.
*
* @property qualifiedName The declaration qualified name.
* @property signatures The set of signatures of the declaration.
*/
@ExperimentalLibraryAbiReader
sealed interface AbiDeclaration {
val qualifiedName: AbiQualifiedName
@@ -152,47 +188,87 @@ sealed interface AbiDeclaration {
fun hasAnnotation(annotationClassName: AbiQualifiedName): Boolean
}
/**
* A declaration that also has a modality.
*
* @property modality The modality of the declaration.
*/
@ExperimentalLibraryAbiReader
sealed interface AbiDeclarationWithModality : AbiDeclaration {
val modality: AbiModality
}
/**
* All known types of modality.
*/
@ExperimentalLibraryAbiReader
enum class AbiModality {
FINAL, OPEN, ABSTRACT, SEALED
}
/**
* The entity that can contain nested [AbiDeclaration]s.
*
* @property declarations Nested declarations.
* Important: The order of declarations is preserved exactly as in serialized IR.
*/
@ExperimentalLibraryAbiReader
interface AbiDeclarationContainer {
/** Important: The order of declarations is preserved exactly as in serialized IR. */
val declarations: List<AbiDeclaration>
}
/**
* The auxiliary container used just to keep together all top-level [AbiDeclaration]s in a KLIB.
*/
@ExperimentalLibraryAbiReader
interface AbiTopLevelDeclarations : AbiDeclarationContainer
/**
* An [AbiDeclaration] that represents a Kotlin class.
*
* @property kind Class kind.
* @property isInner Whether the class is an inner class.
* @property isValue Whether the class is a value-class.
* @property isFunction Whether the interface represented by this [AbiClass] is a fun-interface.
* @property superTypes The set of non-trivial supertypes (i.e. excluding [kotlin.Any]).
* Important: The order of supertypes is preserved exactly as in serialized IR.
*/
@ExperimentalLibraryAbiReader
interface AbiClass : AbiDeclarationWithModality, AbiDeclarationContainer, AbiTypeParametersContainer {
val kind: AbiClassKind
val isInner: Boolean
val isValue: Boolean
val isFunction: Boolean
/**
* The set of non-trivial supertypes (i.e. excluding [kotlin.Any]).
* Important: The order of supertypes is preserved exactly as in serialized IR.
*/
val superTypes: List<AbiType>
}
/**
* All known Kotlin class kinds.
*/
@ExperimentalLibraryAbiReader
enum class AbiClassKind {
CLASS, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS
}
/** An [AbiDeclaration] that represents a particular enum entry. */
@ExperimentalLibraryAbiReader
interface AbiEnumEntry : AbiDeclaration
/**
* An [AbiDeclaration] that represents a function or a class constructor.
*
* @property isConstructor Whether this is a class constructor.
* @property isInline Whether this is an `inline` function.
* @property isSuspend Whether this is a `suspend` function.
* @property hasExtensionReceiverParameter If this function has an extension receiver parameter.
* @property contextReceiverParametersCount The number of context receiver parameters.
* @property valueParameters The function value parameters.
* Important: All value parameters of the function are stored in the single place, in the [valueParameters] list in
* a well-defined order. First, unless [hasExtensionReceiverParameter] is false, goes the extension receiver parameter.
* It is followed by [contextReceiverParametersCount] context receiver parameters. The remainder are the regular
* value parameters of the function.
* @property returnType The function's return type. Always `null` for constructors.
*/
@ExperimentalLibraryAbiReader
interface AbiFunction : AbiDeclarationWithModality, AbiTypeParametersContainer {
val isConstructor: Boolean
@@ -200,17 +276,19 @@ interface AbiFunction : AbiDeclarationWithModality, AbiTypeParametersContainer {
val isSuspend: Boolean
val hasExtensionReceiverParameter: Boolean
val contextReceiverParametersCount: Int
/**
* Important: All value parameters of the function are stored in the single place, in the [valueParameters] list in
* a well-defined order. First, unless [hasExtensionReceiverParameter] is false, goes the extension receiver parameter.
* It is followed by [contextReceiverParametersCount] context receiver parameters. The remainder are the regular
* value parameters of the function.
*/
val valueParameters: List<AbiValueParameter>
val returnType: AbiType?
}
/**
* An individual value parameter of a function.
*
* @property type The type of the value parameter.
* @property isVararg Whether the value parameter is a var-arg parameter.
* @property hasDefaultArg Whether the value parameter has a default value.
* @property isNoinline If the parameter is marked with `noinline` keyword.
* @property isCrossinline If the parameter is marked with `crossinline` keyword.
*/
@ExperimentalLibraryAbiReader
interface AbiValueParameter {
val type: AbiType
@@ -220,6 +298,13 @@ interface AbiValueParameter {
val isCrossinline: Boolean
}
/**
* An [AbiDeclaration] that represents a property.
*
* @property kind The property kind.
* @property getter The getter accessor, fi any.
* @property setter The setter accessor, fi any.
*/
@ExperimentalLibraryAbiReader
interface AbiProperty : AbiDeclarationWithModality {
val kind: AbiPropertyKind
@@ -227,32 +312,61 @@ interface AbiProperty : AbiDeclarationWithModality {
val setter: AbiFunction?
}
/** All known kinds of properties. */
@ExperimentalLibraryAbiReader
enum class AbiPropertyKind { VAL, CONST_VAL, VAR }
/**
* A declaration that also may have type parameters.
*
* @property typeParameters The declaration's type parameters.
* Important: The order of [typeParameters] is preserved exactly as in serialized IR.
*/
@ExperimentalLibraryAbiReader
sealed interface AbiTypeParametersContainer : AbiDeclaration {
/** Important: The order of [typeParameters] is preserved exactly as in serialized IR. */
val typeParameters: List<AbiTypeParameter>
}
/**
* An individual type parameter.
*
* @property tag A unique string identifying the type parameter withing the containing declaration's scope. Can be used
* to distinguish this type parameter from other type parameters. Important: Please note that the [tag] property is
* automatically generated by the ABI reader. The [tag] is not read from KLIB, and therefore it has no connection
* with the type parameter's name.
* @property variance The type parameter variance.
* @property isReified Whether the type parameter is a reified parameter.
* @property upperBounds The set of non-trivial upper bounds (i.e. excluding nullable [kotlin.Any]).
* Important: The order of upper bounds is preserved exactly as in serialized IR.
*/
@ExperimentalLibraryAbiReader
interface AbiTypeParameter {
val tag: String
val variance: AbiVariance
val isReified: Boolean
/**
* The set of non-trivial upper bounds (i.e. excluding nullable [kotlin.Any]).
* Important: The order of upper bounds is preserved exactly as in serialized IR.
*/
val upperBounds: List<AbiType>
}
/** Represents a Kotlin type. Can be either of: [Dynamic], [Error], [Simple]. */
@ExperimentalLibraryAbiReader
sealed interface AbiType {
/** The Kotlin/JavaScript `dynamic` type. */
interface Dynamic : AbiType
/**
* The error type. Normally, this type should not occur in a KLIB, because by its own nature this type implies that
* there was an error during compilation such that the compiler failed to fully resolve the type leading to compilation halted
* even before anything has been written to the KLIB.
*/
interface Error : AbiType
/**
* A regular type.
*
* @property classifierReference A reference pointing to the concrete classified used in the type.
* @property arguments Type arguments.
* @property nullability The nullability flag of the type.
*/
interface Simple : AbiType {
val classifierReference: AbiClassifierReference
val arguments: List<AbiTypeArgument>
@@ -260,31 +374,57 @@ sealed interface AbiType {
}
}
/**
* An individual argument of a type.
*/
@ExperimentalLibraryAbiReader
sealed interface AbiTypeArgument {
/** A `<*>` (start projection) type argument. */
interface StarProjection : AbiTypeArgument
/**
* A regular type argument.
*
* @property type The type argument's type.
* @property variance The type arguemnt's variance.
*/
interface TypeProjection : AbiTypeArgument {
val type: AbiType
val variance: AbiVariance
}
}
/**
* A reference to a concrete classifier. Used in [AbiType.Simple].
*/
@ExperimentalLibraryAbiReader
sealed interface AbiClassifierReference {
/**
* A reference that points to the concrete class.
*/
interface ClassReference : AbiClassifierReference {
val className: AbiQualifiedName
}
/**
* A reference that points to a type parameter (the matching is done by [tag]).
*/
interface TypeParameterReference : AbiClassifierReference {
val tag: String
}
}
/**
* All known types of type nullability.
*/
@ExperimentalLibraryAbiReader
enum class AbiTypeNullability {
MARKED_NULLABLE, NOT_SPECIFIED, DEFINITELY_NOT_NULL
}
/**
* All known sorts of type argument's variance,
*/
@ExperimentalLibraryAbiReader
enum class AbiVariance {
INVARIANT, IN, OUT
@@ -11,8 +11,15 @@ import java.io.File
/** The default implementation of [LibraryAbi] reader. */
@ExperimentalLibraryAbiReader
object LibraryAbiReader {
/** Inspect the KLIB at [library]. The KLIB can be either in a directory (unzipped) or in a file (zipped) form. */
/**
* Inspect the KLIB at [library]. The KLIB can be either in a directory (unzipped) or in a file (zipped) form.
*
* @param library The file representing the KLIB location.
* @param filters The filters that are applied while reading the KLIB to exclude/ignore certain entities.
*/
fun readAbiInfo(library: File, vararg filters: AbiReadingFilter): LibraryAbi = readAbiInfo(library, filters.asList())
/** @see [readAbiInfo] */
fun readAbiInfo(library: File, filters: List<AbiReadingFilter>): LibraryAbi = LibraryAbiReaderImpl(library, filters).readAbi()
}
@@ -24,9 +31,13 @@ object LibraryAbiReader {
*/
@ExperimentalLibraryAbiReader
interface AbiReadingFilter {
/** Tests for each package being read by the ABI reader if it should be excluded/ignored. */
fun isPackageExcluded(packageName: AbiCompoundName): Boolean = false
/** Tests for each declaration being read by the ABI reader if it should be excluded/ignored */
fun isDeclarationExcluded(declaration: AbiDeclaration): Boolean = false
/** The default implementation of a filter that ignores certain packages. */
class ExcludedPackages(excludedPackageNames: Collection<AbiCompoundName>) : AbiReadingFilter {
private val excludedPackageNames = excludedPackageNames.toSet()
@@ -37,6 +48,7 @@ interface AbiReadingFilter {
}
}
/** The default implementation of a filter that ignores certain classes. */
class ExcludedClasses(excludedClassNames: Collection<AbiQualifiedName>) : AbiReadingFilter {
private val excludedClassNames = excludedClassNames.toSet()
@@ -44,6 +56,10 @@ interface AbiReadingFilter {
declaration is AbiClass && declaration.qualifiedName in excludedClassNames
}
/**
* The default implementation of a filter that ignores declarations that have at least
* one annotation from [nonPublicMarkerNames] list.
*/
class NonPublicMarkerAnnotations(nonPublicMarkerNames: Collection<AbiQualifiedName>) : AbiReadingFilter {
private val nonPublicMarkerNames = nonPublicMarkerNames.toSet().toTypedArray()
@@ -55,6 +71,7 @@ interface AbiReadingFilter {
}
}
/** The default composite filter implementation: Exposes multiple incorporated filters as a single filter. */
class Composite(filters: List<AbiReadingFilter>) : AbiReadingFilter {
private val filters = filters.toTypedArray()
@@ -10,14 +10,29 @@ import org.jetbrains.kotlin.library.abi.impl.AbiRendererImpl
/** The default rendering implementation. */
@ExperimentalLibraryAbiReader
object LibraryAbiRenderer {
/**
* Render the [LibraryAbi] to the string representation.
*
* @param libraryAbi The [LibraryAbi] instance previously read by [LibraryAbiReader].
* @param settings The rendering settings.
*/
fun render(libraryAbi: LibraryAbi, settings: AbiRenderingSettings): String =
buildString { render(libraryAbi, this, settings) }
/**
* Render the [LibraryAbi] to the string representation.
*
* @param libraryAbi The [LibraryAbi] instance previously read by [LibraryAbiReader].
* @param output The output to write the rendered text to.
* @param settings The rendering settings.
*/
fun render(libraryAbi: LibraryAbi, output: Appendable, settings: AbiRenderingSettings): Unit =
AbiRendererImpl(libraryAbi, settings, output).render()
}
/**
* The settings applied during rendering of [LibraryAbi].
*
* @param renderedSignatureVersion The IR signature version to render. This should be a version among the versions
* listed in [LibraryAbi.signatureVersions].
* @param renderManifest Whether KLIB manifest properties should be rendered.