From 18f9ada6763ad4f998c0b7db0df02292ac13956d Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Fri, 4 Aug 2023 00:06:39 +0200 Subject: [PATCH] [KLIB] ABI reader: More verbose KDocs ^KT-54402 --- .../kotlin/library/abi/LibraryAbi.kt | 178 ++++++++++++++++-- .../kotlin/library/abi/LibraryAbiReader.kt | 19 +- .../kotlin/library/abi/LibraryAbiRenderer.kt | 15 ++ 3 files changed, 192 insertions(+), 20 deletions(-) diff --git a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbi.kt b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbi.kt index f0aa044fec3..05fbb800552 100644 --- a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbi.kt +++ b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbi.kt @@ -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 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 { require(AbiQualifiedName.SEPARATOR !in value) { "Compound name contains illegal characters: $value" } } + /** All name segments comprising this compound name. */ val nameSegments: List 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() == 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 { } 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 } +/** + * 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 } +/** + * 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 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 } +/** + * 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 } +/** 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 @@ -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 diff --git a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiReader.kt b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiReader.kt index a5d45738131..6c36ec0d591 100644 --- a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiReader.kt +++ b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiReader.kt @@ -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): 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) : 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) : 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) : 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 { private val filters = filters.toTypedArray() diff --git a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiRenderer.kt b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiRenderer.kt index fdccf0c5814..584cda43e4c 100644 --- a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiRenderer.kt +++ b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/LibraryAbiRenderer.kt @@ -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.