From 18a4247226891bbe968d923632b5fd63ca322e4c Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 11 Jun 2019 19:19:43 +0200 Subject: [PATCH] Add kdoc for new API of kotlinx-metadata-jvm #KT-26602 --- libraries/kotlinx-metadata/jvm/ChangeLog.md | 4 + .../metadata/jvm/JvmMemberSignature.kt | 13 +- .../metadata/jvm/KotlinModuleMetadata.kt | 24 + .../metadata/jvm/jvmExtensionVisitors.kt | 7 +- .../src/kotlinx/metadata/jvm/jvmExtensions.kt | 74 +++ .../src/kotlinx/metadata/nodes.kt | 455 ++++++++++++++++++ .../src/kotlinx/metadata/visitors.kt | 4 +- 7 files changed, 571 insertions(+), 10 deletions(-) diff --git a/libraries/kotlinx-metadata/jvm/ChangeLog.md b/libraries/kotlinx-metadata/jvm/ChangeLog.md index 757fe5a6079..f341166f3a5 100644 --- a/libraries/kotlinx-metadata/jvm/ChangeLog.md +++ b/libraries/kotlinx-metadata/jvm/ChangeLog.md @@ -1,5 +1,9 @@ # kotlinx-metadata-jvm +## 0.1.0 + +- [`KT-26602`](https://youtrack.jetbrains.com/issue/KT-26602) Provide a value-based API + ## 0.0.6 - [`KT-31308`](https://youtrack.jetbrains.com/issue/KT-31308) Add module name extensions to kotlinx-metadata-jvm diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMemberSignature.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMemberSignature.kt index 631d6e412b9..0992b18c6e3 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMemberSignature.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/JvmMemberSignature.kt @@ -4,6 +4,7 @@ */ package kotlinx.metadata.jvm + import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature as JvmMemberSignatureImpl /** @@ -30,7 +31,9 @@ sealed class JvmMemberSignature { } /** - * A signature of a JVM method. + * A signature of a JVM method in the JVM-based format. + * + * Example: `JvmMethodSignature("equals", "(Ljava/lang/Object;)Z")`. * * @see JvmMemberSignature */ @@ -39,14 +42,16 @@ data class JvmMethodSignature(override val name: String, override val desc: Stri } /** - * A signature of a JVM field. + * A signature of a JVM field in the JVM-based format. + * + * Example: `JvmFieldSignature("value", "Ljava/lang/String;")`. * * @see JvmMemberSignature */ data class JvmFieldSignature(override val name: String, override val desc: String) : JvmMemberSignature() { - override fun asString() = name + ":" + desc + override fun asString() = "$name:$desc" } internal fun JvmMemberSignatureImpl.Method.wrapAsPublic() = JvmMethodSignature(name, desc) -internal fun JvmMemberSignatureImpl.Field.wrapAsPublic() = JvmFieldSignature(name, desc) \ No newline at end of file +internal fun JvmMemberSignatureImpl.Field.wrapAsPublic() = JvmFieldSignature(name, desc) diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt index d1197c70448..7b6d73bab8d 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt @@ -157,8 +157,18 @@ abstract class KmModuleVisitor(private val delegate: KmModuleVisitor? = null) { // TODO: JvmPackageName } +/** + * Represents a Kotlin JVM module file. + */ class KmModule : KmModuleVisitor() { + /** + * Table of all single- and multi-file facades declared in some package of this module, where keys are '.'-separated package names. + */ val packageParts: MutableMap = LinkedHashMap() + + /** + * Annotations on the module. + */ val annotations: MutableList = ArrayList(0) override fun visitPackageParts(fqName: String, fileFacades: List, multiFileClassParts: Map) { @@ -169,6 +179,11 @@ class KmModule : KmModuleVisitor() { annotations.add(annotation) } + /** + * Populates the given visitor with data in this module. + * + * @param visitor the visitor which will visit data in this module. + */ fun accept(visitor: KmModuleVisitor) { for ((fqName, parts) in packageParts) { visitor.visitPackageParts(fqName, parts.fileFacades, parts.multiFileClassParts) @@ -177,6 +192,15 @@ class KmModule : KmModuleVisitor() { } } +/** + * Collection of all single- and multi-file facades in a package of some module. + * + * Packages are separated by '/' in the names of file facades. + * + * @property fileFacades the list of single-file facades in this package + * @property multiFileClassParts the map of multi-file classes where keys are names of multi-file class parts, + * and values are names of the corresponding multi-file facades + */ class KmPackageParts( val fileFacades: MutableList, val multiFileClassParts: MutableMap diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensionVisitors.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensionVisitors.kt index 719988ef1d7..1d210843f05 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensionVisitors.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensionVisitors.kt @@ -119,8 +119,7 @@ open class JvmFunctionExtensionVisitor @JvmOverloads constructor( get() = TYPE /** - * Visits the JVM signature of the function in the JVM-based format, - * or null if the JVM signature of this function is unknown. + * Visits the JVM signature of the function, or null if the JVM signature of this function is unknown. * * Example: `JvmMethodSignature("equals", "(Ljava/lang/Object;)Z")` * @@ -169,10 +168,10 @@ open class JvmPropertyExtensionVisitor @JvmOverloads constructor( * Visits JVM signatures of field and accessors generated for the property. * * @param jvmFlags JVM-specific flags of the property, consisting of [JvmFlag.Property] flags - * @param fieldSignature the signature of the field, or `null` if this property has no field. + * @param fieldSignature the signature of the backing field of the property, or `null` if this property has no backing field. * Example: `JvmFieldSignature("X", "Ljava/lang/Object;")` * @param getterSignature the signature of the property getter, or `null` if this property has no getter or its signature is unknown. - * Example: `JvmMethodSignature("getX()", "Ljava/lang/Object;")` + * Example: `JvmMethodSignature("getX", "()Ljava/lang/Object;")` * @param setterSignature the signature of the property setter, or `null` if this property has no setter or its signature is unknown. * Example: `JvmMethodSignature("setX", "(Ljava/lang/Object;)V")` */ diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt index 0f9f00c44a2..fc5bafd904d 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/jvmExtensions.kt @@ -8,86 +8,160 @@ package kotlinx.metadata.jvm import kotlinx.metadata.* import kotlinx.metadata.jvm.impl.jvm +/** + * Metadata of local delegated properties used somewhere inside this class (but not in a nested class). + * Note that for classes produced by the Kotlin compiler, such properties will have default accessors. + * + * The order of local delegated properties in this list is important. The Kotlin compiler generates the corresponding property's index + * at the call site, so that reflection would be able to load the metadata of the property with that index at runtime. + * If an incorrect index is used, either the `KProperty<*>` object passed to delegate methods will point to the wrong property + * at runtime, or an exception will be thrown. + */ val KmClass.localDelegatedProperties: MutableList get() = jvm.localDelegatedProperties +/** + * Name of the module where this class is declared. + */ var KmClass.moduleName: String? get() = jvm.moduleName set(value) { jvm.moduleName = value } +/** + * JVM internal name of the original class this anonymous object is copied from. This value is set for anonymous objects + * copied from bodies of inline functions to the use site by the Kotlin compiler. + */ var KmClass.anonymousObjectOriginName: String? get() = jvm.anonymousObjectOriginName set(value) { jvm.anonymousObjectOriginName = value } +/** + * Metadata of local delegated properties used somewhere inside this package fragment (but not in any class). + * Note that for classes produced by the Kotlin compiler, such properties will have default accessors. + * + * The order of local delegated properties in this list is important. The Kotlin compiler generates the corresponding property's index + * at the call site, so that reflection would be able to load the metadata of the property with that index at runtime. + * If an incorrect index is used, either the `KProperty<*>` object passed to delegate methods will point to the wrong property + * at runtime, or an exception will be thrown. + */ val KmPackage.localDelegatedProperties: MutableList get() = jvm.localDelegatedProperties +/** + * Name of the module where this package fragment is declared. + */ var KmPackage.moduleName: String? get() = jvm.moduleName set(value) { jvm.moduleName = value } +/** + * JVM signature of the function, or null if the JVM signature of this function is unknown. + * + * Example: `JvmMethodSignature("equals", "(Ljava/lang/Object;)Z")`. + */ var KmFunction.signature: JvmMethodSignature? get() = jvm.signature set(value) { jvm.signature = value } +/** + * JVM internal name of the original class the lambda class for this function is copied from. This value is set for lambdas + * copied from bodies of inline functions to the use site by the Kotlin compiler. + */ var KmFunction.lambdaClassOriginName: String? get() = jvm.lambdaClassOriginName set(value) { jvm.lambdaClassOriginName = value } +/** + * JVM-specific flags of the property, consisting of [JvmFlag.Property] flags. + */ var KmProperty.jvmFlags: Flags get() = jvm.jvmFlags set(value) { jvm.jvmFlags = value } +/** + * JVM signature of the backing field of the property, or `null` if this property has no backing field. + * + * Example: `JvmFieldSignature("X", "Ljava/lang/Object;")`. + */ var KmProperty.fieldSignature: JvmFieldSignature? get() = jvm.fieldSignature set(value) { jvm.fieldSignature = value } +/** + * JVM signature of the property getter, or `null` if this property has no getter or its signature is unknown. + * + * Example: `JvmMethodSignature("getX", "()Ljava/lang/Object;")`. + */ var KmProperty.getterSignature: JvmMethodSignature? get() = jvm.getterSignature set(value) { jvm.getterSignature = value } +/** + * JVM signature of the property setter, or `null` if this property has no setter or its signature is unknown. + * + * Example: `JvmMethodSignature("setX", "(Ljava/lang/Object;)V")`. + */ var KmProperty.setterSignature: JvmMethodSignature? get() = jvm.setterSignature set(value) { jvm.setterSignature = value } +/** + * JVM signature of a synthetic method which is generated to store annotations on a property in the bytecode. + * + * Example: `JvmMethodSignature("getX$annotations", "()V")`. + */ var KmProperty.syntheticMethodForAnnotations: JvmMethodSignature? get() = jvm.syntheticMethodForAnnotations set(value) { jvm.syntheticMethodForAnnotations = value } +/** + * JVM signature of the constructor, or null if the JVM signature of this constructor is unknown. + * + * Example: `JvmMethodSignature("", "(Ljava/lang/Object;)V")`. + */ var KmConstructor.signature: JvmMethodSignature? get() = jvm.signature set(value) { jvm.signature = value } +/** + * Annotations on the type parameter. + */ val KmTypeParameter.annotations: MutableList get() = jvm.annotations +/** + * `true` if the type is seen as a raw type in Java. + */ var KmType.isRaw: Boolean get() = jvm.isRaw set(value) { jvm.isRaw = value } +/** + * Annotations on the type. + */ val KmType.annotations: MutableList get() = jvm.annotations diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt index 1749ee71ffa..cb5befb7936 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/nodes.kt @@ -9,25 +9,93 @@ package kotlinx.metadata import kotlinx.metadata.impl.extensions.* +/** + * Represents a Kotlin declaration container, such as a class or a package fragment. + */ interface KmDeclarationContainer { + /** + * Functions in the container. + */ val functions: MutableList + + /** + * Properties in the container. + */ val properties: MutableList + + /** + * Type aliases in the container. + */ val typeAliases: MutableList } +/** + * Represents a Kotlin class. + */ class KmClass : KmClassVisitor(), KmDeclarationContainer { + /** + * Class flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Class] flags. + */ var flags: Flags = flagsOf() + + /** + * Name of the class. + */ lateinit var name: ClassName + + /** + * Type parameters of the class. + */ val typeParameters: MutableList = ArrayList(0) + + /** + * Supertypes of the class. + */ val supertypes: MutableList = ArrayList(1) + + /** + * Functions in the class. + */ override val functions: MutableList = ArrayList() + + /** + * Properties in the class. + */ override val properties: MutableList = ArrayList() + + /** + * Type aliases in the class. + */ override val typeAliases: MutableList = ArrayList(0) + + /** + * Constructors of the class. + */ val constructors: MutableList = ArrayList(1) + + /** + * Name of the companion object of this class, if it has one. + */ var companionObject: String? = null + + /** + * Names of nested classes of this class. + */ val nestedClasses: MutableList = ArrayList(0) + + /** + * Names of enum entries, if this class is an enum class. + */ val enumEntries: MutableList = ArrayList(0) + + /** + * Names of direct subclasses of this class, if this class is `sealed`. + */ val sealedSubclasses: MutableList = ArrayList(0) + + /** + * Version requirements on this class. + */ val versionRequirements: MutableList = ArrayList(0) private val extensions: List = @@ -78,6 +146,11 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer { override fun visitExtensions(type: KmExtensionType): KmClassExtensionVisitor = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this class. + * + * @param visitor the visitor which will visit data in this class + */ fun accept(visitor: KmClassVisitor) { visitor.visit(flags, name) typeParameters.forEach { visitor.visitTypeParameter(it.flags, it.name, it.id, it.variance)?.let(it::accept) } @@ -96,9 +169,23 @@ class KmClass : KmClassVisitor(), KmDeclarationContainer { } } +/** + * Represents a Kotlin package fragment, including single file facades and multi-file class parts. + */ class KmPackage : KmPackageVisitor(), KmDeclarationContainer { + /** + * Functions in the package fragment. + */ override val functions: MutableList = ArrayList() + + /** + * Properties in the package fragment. + */ override val properties: MutableList = ArrayList() + + /** + * Type aliases in the package fragment. + */ override val typeAliases: MutableList = ArrayList(0) private val extensions: List = @@ -116,6 +203,11 @@ class KmPackage : KmPackageVisitor(), KmDeclarationContainer { override fun visitExtensions(type: KmExtensionType): KmPackageExtensionVisitor = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this package fragment. + * + * @param visitor the visitor which will visit data in this package fragment + */ fun accept(visitor: KmPackageVisitor) { functions.forEach { visitor.visitFunction(it.flags, it.name)?.let(it::accept) } properties.forEach { visitor.visitProperty(it.flags, it.name, it.getterFlags, it.setterFlags)?.let(it::accept) } @@ -125,20 +217,43 @@ class KmPackage : KmPackageVisitor(), KmDeclarationContainer { } } +/** + * Represents a synthetic class generated for a Kotlin lambda. + */ class KmLambda : KmLambdaVisitor() { + /** + * Signature of the synthetic anonymous function, representing the lambda. + */ lateinit var function: KmFunction override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor = KmFunction(flags, name).also { function = it } + /** + * Populates the given visitor with data in this lambda. + * + * @param visitor the visitor which will visit data in this lambda + */ fun accept(visitor: KmLambdaVisitor) { visitor.visitFunction(function.flags, function.name)?.let(function::accept) visitor.visitEnd() } } +/** + * Represents a constructor of a Kotlin class. + * + * @property flags constructor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag and [Flag.Constructor] flags + */ class KmConstructor(var flags: Flags) : KmConstructorVisitor() { + /** + * Value parameters of the constructor. + */ val valueParameters: MutableList = ArrayList() + + /** + * Version requirements on the constructor. + */ val versionRequirements: MutableList = ArrayList(0) private val extensions: List = @@ -153,6 +268,11 @@ class KmConstructor(var flags: Flags) : KmConstructorVisitor() { override fun visitExtensions(type: KmExtensionType): KmConstructorExtensionVisitor = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this constructor. + * + * @param visitor the visitor which will visit data in this class + */ fun accept(visitor: KmConstructorVisitor) { valueParameters.forEach { visitor.visitValueParameter(it.flags, it.name)?.let(it::accept) } versionRequirements.forEach { visitor.visitVersionRequirement()?.let(it::accept) } @@ -161,15 +281,44 @@ class KmConstructor(var flags: Flags) : KmConstructorVisitor() { } } +/** + * Represents a Kotlin function declaration. + * + * @property flags function flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Function] flags + * @property name the name of the function + */ class KmFunction( var flags: Flags, var name: String ) : KmFunctionVisitor() { + /** + * Type parameters of the function. + */ val typeParameters: MutableList = ArrayList(0) + + /** + * Type of the receiver of the function, if this is an extension function. + */ var receiverParameterType: KmType? = null + + /** + * Value parameters of the function. + */ val valueParameters: MutableList = ArrayList() + + /** + * Return type of the function. + */ lateinit var returnType: KmType + + /** + * Version requirements on the function. + */ val versionRequirements: MutableList = ArrayList(0) + + /** + * Contract of the function. + */ var contract: KmContract? = null private val extensions: List = @@ -196,6 +345,11 @@ class KmFunction( override fun visitExtensions(type: KmExtensionType): KmFunctionExtensionVisitor = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this function. + * + * @param visitor the visitor which will visit data in this function + */ fun accept(visitor: KmFunctionVisitor) { typeParameters.forEach { visitor.visitTypeParameter(it.flags, it.name, it.id, it.variance)?.let(it::accept) } receiverParameterType?.let { visitor.visitReceiverParameterType(it.flags)?.let(it::accept) } @@ -208,16 +362,45 @@ class KmFunction( } } +/** + * Represents a Kotlin property declaration. + * + * @property flags property flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag and [Flag.Property] flags + * @property name the name of the property + * @property getterFlags property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag + * and [Flag.PropertyAccessor] flags + * @property setterFlags property accessor flags, consisting of [Flag.HAS_ANNOTATIONS], visibility flag, modality flag + * and [Flag.PropertyAccessor] flags + */ class KmProperty( var flags: Flags, var name: String, var getterFlags: Flags, var setterFlags: Flags ) : KmPropertyVisitor() { + /** + * Type parameters of the property. + */ val typeParameters: MutableList = ArrayList(0) + + /** + * Type of the receiver of the property, if this is an extension property. + */ var receiverParameterType: KmType? = null + + /** + * Value parameter of the setter of this property, if this is a `var` property. + */ var setterParameter: KmValueParameter? = null + + /** + * Type of the property. + */ lateinit var returnType: KmType + + /** + * Version requirements on the property. + */ val versionRequirements: MutableList = ArrayList(0) private val extensions: List = @@ -241,6 +424,11 @@ class KmProperty( override fun visitExtensions(type: KmExtensionType): KmPropertyExtensionVisitor = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this property. + * + * @param visitor the visitor which will visit data in this property + */ fun accept(visitor: KmPropertyVisitor) { typeParameters.forEach { visitor.visitTypeParameter(it.flags, it.name, it.id, it.variance)?.let(it::accept) } receiverParameterType?.let { visitor.visitReceiverParameterType(it.flags)?.let(it::accept) } @@ -252,14 +440,40 @@ class KmProperty( } } +/** + * Represents a Kotlin type alias declaration. + * + * @property flags type alias flags, consisting of [Flag.HAS_ANNOTATIONS] and visibility flag + * @property name the name of the type alias + */ class KmTypeAlias( var flags: Flags, var name: String ) : KmTypeAliasVisitor() { + /** + * Type parameters of the type alias. + */ val typeParameters: MutableList = ArrayList(0) + + /** + * Underlying type of the type alias, i.e. the type in the right-hand side of the type alias declaration. + */ lateinit var underlyingType: KmType + + /** + * 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. + */ lateinit var expandedType: KmType + + /** + * Annotations on the type alias. + */ val annotations: MutableList = ArrayList(0) + + /** + * Version requirements on the type alias. + */ val versionRequirements: MutableList = ArrayList(0) override fun visitTypeParameter(flags: Flags, name: String, id: Int, variance: KmVariance): KmTypeParameterVisitor = @@ -278,6 +492,11 @@ class KmTypeAlias( override fun visitVersionRequirement(): KmVersionRequirementVisitor = KmVersionRequirement().addTo(versionRequirements) + /** + * Populates the given visitor with data in this type alias. + * + * @param visitor the visitor which will visit data in this type alias + */ fun accept(visitor: KmTypeAliasVisitor) { typeParameters.forEach { visitor.visitTypeParameter(it.flags, it.name, it.id, it.variance)?.let(it::accept) } visitor.visitUnderlyingType(underlyingType.flags)?.let(underlyingType::accept) @@ -288,11 +507,24 @@ class KmTypeAlias( } } +/** + * Represents a value parameter of a Kotlin constructor, function or property setter. + * + * @property flags value parameter flags, consisting of [Flag.ValueParameter] flags + * @property name the name of the value parameter + */ class KmValueParameter( var flags: Flags, var name: String ) : KmValueParameterVisitor() { + /** + * Type of the value parameter, if this is **not** a `vararg` parameter. + */ var type: KmType? = null + + /** + * Type of the value parameter, if this is a `vararg` parameter. + */ var varargElementType: KmType? = null override fun visitType(flags: Flags): KmTypeVisitor = @@ -301,6 +533,11 @@ class KmValueParameter( override fun visitVarargElementType(flags: Flags): KmTypeVisitor = KmType(flags).also { varargElementType = it } + /** + * Populates the given visitor with data in this value parameter. + * + * @param visitor the visitor which will visit data in this value parameter + */ fun accept(visitor: KmValueParameterVisitor) { type?.let { visitor.visitType(it.flags)?.let(it::accept) } varargElementType?.let { visitor.visitVarargElementType(it.flags)?.let(it::accept) } @@ -308,12 +545,24 @@ class KmValueParameter( } } +/** + * Represents a type parameter of a Kotlin class, function, property or type alias. + * + * @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 { fun foo(t: T) }`) + * @property variance the declaration-site variance of the type parameter + */ class KmTypeParameter( var flags: Flags, var name: String, var id: Int, var variance: KmVariance ) : KmTypeParameterVisitor() { + /** + * Upper bounds of the type parameter. + */ val upperBounds: MutableList = ArrayList(1) private val extensions: List = @@ -325,6 +574,11 @@ class KmTypeParameter( override fun visitExtensions(type: KmExtensionType): KmTypeParameterExtensionVisitor? = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this type parameter. + * + * @param visitor the visitor which will visit data in this type parameter + */ fun accept(visitor: KmTypeParameterVisitor) { upperBounds.forEach { visitor.visitUpperBound(it.flags)?.let(it::accept) } extensions.forEach { visitor.visitExtensions(it.type)?.let(it::accept) } @@ -332,11 +586,50 @@ class KmTypeParameter( } } +/** + * Represents a type. + * + * @property flags type flags, consisting of [Flag.Type] flags + */ class KmType(var flags: Flags) : KmTypeVisitor() { + /** + * Classifier of the type. + */ lateinit var classifier: KmClassifier + + /** + * Arguments of the type, if the type's classifier is a class or a type alias. + */ val arguments: MutableList = ArrayList(0) + + /** + * Abbreviation of this type. Note that all types are expanded for metadata produced by the Kotlin compiler. For example: + * + * typealias A = MutableList + * + * fun foo(a: A) {} + * + * The type of the `foo`'s parameter in the metadata is actually `MutableList`, and its abbreviation is `A`. + */ var abbreviatedType: KmType? = null + + /** + * Outer type of this type, if this type's classifier is an inner class. For example: + * + * class A { inner class B } + * + * fun foo(a: A<*>.B) {} + * + * The type of the `foo`'s parameter in the metadata is `B` (a type whose classifier is class `B`, and it has one type argument, + * type `Byte?`), and its outer type is `A<*>` (a type whose classifier is class `A`, and it has one type argument, star projection). + */ var outerType: KmType? = null + + /** + * Upper bound of this type, if this type is flexible. In that case, all other data refers to the lower bound of the type. + * + * Flexible types in Kotlin include platform types in Kotlin/JVM and `dynamic` type in Kotlin/JS. + */ var flexibleTypeUpperBound: KmFlexibleTypeUpperBound? = null private val extensions: List = @@ -373,6 +666,11 @@ class KmType(var flags: Flags) : KmTypeVisitor() { override fun visitExtensions(type: KmExtensionType): KmTypeExtension = extensions.singleOfType(type) + /** + * Populates the given visitor with data in this type. + * + * @param visitor the visitor which will visit data in this type + */ fun accept(visitor: KmTypeVisitor) { when (val classifier = classifier) { is KmClassifier.Class -> visitor.visitClass(classifier.name) @@ -396,11 +694,36 @@ 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. + */ class KmVersionRequirement : KmVersionRequirementVisitor() { + /** + * Kind of the version that this declaration requires. + */ lateinit var kind: KmVersionRequirementVersionKind + + /** + * Level of the diagnostic that must be reported on the usages of the declaration in case the version requirement is not satisfied. + */ lateinit var level: KmVersionRequirementLevel + + /** + * Optional error code to be displayed in the diagnostic. + */ var errorCode: Int? = null + + /** + * Optional message to be displayed in the diagnostic. + */ var message: String? = null + + /** + * Version required by this requirement. + */ lateinit var version: KmVersion override fun visit(kind: KmVersionRequirementVersionKind, level: KmVersionRequirementLevel, errorCode: Int?, message: String?) { @@ -414,6 +737,11 @@ class KmVersionRequirement : KmVersionRequirementVisitor() { this.version = KmVersion(major, minor, patch) } + /** + * Populates the given visitor with data in this version requirement. + * + * @param visitor the visitor which will visit data in this version requirement + */ fun accept(visitor: KmVersionRequirementVisitor) { visitor.visit(kind, level, errorCode, message) visitor.visitVersion(version.major, version.minor, version.patch) @@ -421,23 +749,55 @@ class KmVersionRequirement : KmVersionRequirementVisitor() { } } +/** + * Represents a contract of a Kotlin function. + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + */ class KmContract : KmContractVisitor() { + /** + * Effects of this contract. + */ val effects: MutableList = ArrayList(1) override fun visitEffect(type: KmEffectType, invocationKind: KmEffectInvocationKind?): KmEffectVisitor = KmEffect(type, invocationKind).addTo(effects) + /** + * Populates the given visitor with data in this contract. + * + * @param visitor the visitor which will visit data in this contract + */ fun accept(visitor: KmContractVisitor) { effects.forEach { visitor.visitEffect(it.type, it.invocationKind)?.let(it::accept) } visitor.visitEnd() } } +/** + * Represents an effect (a part of the contract of a Kotlin function). + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + * + * @property type type of the effect + * @property invocationKind optional number of invocations of the lambda parameter of this function, + * specified further in the effect expression + */ class KmEffect( var type: KmEffectType, var invocationKind: KmEffectInvocationKind? ) : KmEffectVisitor() { + /** + * Arguments of the effect constructor, i.e. the constant value for the [KmEffectType.RETURNS_CONSTANT] effect, + * or the parameter reference for the [KmEffectType.CALLS] effect. + */ val constructorArguments: MutableList = ArrayList(1) + + /** + * Conclusion of the effect. If this value is set, the effect represents an implication with this value as the right-hand side. + */ var conclusion: KmEffectExpression? = null override fun visitConstructorArgument(): KmEffectExpressionVisitor = @@ -446,6 +806,11 @@ class KmEffect( override fun visitConclusionOfConditionalEffect(): KmEffectExpressionVisitor = KmEffectExpression().also { conclusion = it } + /** + * Populates the given visitor with data in this effect. + * + * @param visitor the visitor which will visit data in this effect + */ fun accept(visitor: KmEffectVisitor) { constructorArguments.forEach { visitor.visitConstructorArgument()?.let(it::accept) } conclusion?.let { visitor.visitConclusionOfConditionalEffect()?.let(it::accept) } @@ -453,12 +818,44 @@ class KmEffect( } } +/** + * Represents an effect expression, the contents of an effect (a part of the contract of a Kotlin function). + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + */ class KmEffectExpression : KmEffectExpressionVisitor() { + /** + * Effect expression flags, consisting of [Flag.EffectExpression] flags. + */ var flags: Flags = flagsOf() + + /** + * 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. + */ var parameterIndex: Int? = null + + /** + * Constant value used in the effect expression. + */ var constantValue: KmConstantValue? = null + + /** + * Type used as the target of an `is`-expression in the effect expression. + */ var isInstanceType: KmType? = null + + /** + * Arguments of an `&&`-expression. If this list is non-empty, the resulting effect expression is a conjunction of this expression + * and elements of the list. + */ val andArguments: MutableList = ArrayList(0) + + /** + * Arguments of an `||`-expression. If this list is non-empty, the resulting effect expression is a disjunction of this expression + * and elements of the list. + */ val orArguments: MutableList = ArrayList(0) override fun visit(flags: Flags, parameterIndex: Int?) { @@ -479,6 +876,11 @@ class KmEffectExpression : KmEffectExpressionVisitor() { override fun visitOrArgument(): KmEffectExpressionVisitor = KmEffectExpression().addTo(orArguments) + /** + * Populates the given visitor with data in this effect expression. + * + * @param visitor the visitor which will visit data in this effect expression + */ fun accept(visitor: KmEffectExpressionVisitor) { visitor.visit(flags, parameterIndex) constantValue?.let { visitor.visitConstantValue(it.value) } @@ -489,27 +891,80 @@ class KmEffectExpression : KmEffectExpressionVisitor() { } } +/** + * Represents a classifier of a Kotlin type. A classifier is a class, type parameter or type alias. + * For example, in `MutableMap`, `MutableMap` is the classifier. + */ sealed class KmClassifier { + /** + * Represents a class used as a classifier in a type. + * + * @property name the name of the class + */ data class Class(val name: ClassName) : KmClassifier() + /** + * Represents a type parameter used as a classifier in a type. + * + * @property id id of the type parameter + */ data class TypeParameter(val id: Int) : KmClassifier() + /** + * Represents a type alias used as a classifier in a type. Note that all types are expanded for metadata produced + * by the Kotlin compiler, so the type with a type alias classifier may only appear in [KmType.abbreviatedType]. + * + * @property name the name of the type alias + */ data class TypeAlias(val name: ClassName) : KmClassifier() } +/** + * Represents type projection used in a type argument of the type based on a class or on a type alias. + * For example, in `MutableMap`, `in String?` is the type projection which is the first type argument of the type. + * + * @property variance the variance of the type projection, 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?) { companion object { + /** + * Star projection (`*`). + * For example, in `MutableMap`, `*` is the star projection which is the second type argument of the type. + */ @JvmField val STAR = KmTypeProjection(null, null) } } +/** + * Represents an upper bound of a flexible Kotlin type. + * + * @property type upper bound of the flexible type + * @property typeFlexibilityId id of the kind of flexibility this type has. For example, "kotlin.jvm.PlatformType" for JVM platform types, + * or "kotlin.DynamicType" for JS dynamic type + */ data class KmFlexibleTypeUpperBound(var type: KmType, var typeFlexibilityId: String?) +/** + * Represents a version used in a version requirement. + * + * @property major the major component of the version (e.g. "1" in "1.2.3") + * @property minor the minor component of the version (e.g. "2" 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) { override fun toString(): String = "$major.$minor.$patch" } +/** + * Represents a constant value used in an effect expression. + * + * Contracts are an internal feature of the standard Kotlin library, and their behavior and/or binary format + * may change in a subsequent release. + * + * @property value the constant value. May be `true`, `false` or `null` + */ data class KmConstantValue(val value: Any?) internal fun T.addTo(collection: MutableCollection): T { diff --git a/libraries/kotlinx-metadata/src/kotlinx/metadata/visitors.kt b/libraries/kotlinx-metadata/src/kotlinx/metadata/visitors.kt index 1e37c6f0a3c..3fc592c6bdf 100644 --- a/libraries/kotlinx-metadata/src/kotlinx/metadata/visitors.kt +++ b/libraries/kotlinx-metadata/src/kotlinx/metadata/visitors.kt @@ -406,7 +406,7 @@ abstract class KmTypeAliasVisitor @JvmOverloads constructor(private val delegate /** * Visits the 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 not 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, expanded type is equal to the underlying type. * * @param flags type flags, consisting of [Flag.Type] flags */ @@ -468,7 +468,7 @@ abstract class KmValueParameterVisitor @JvmOverloads constructor(private val del } /** - * A visitor to visit a type parameter of a Kotlin class, function or property. + * A visitor to visit a type parameter of a Kotlin class, function, property or type alias. * * When using this class, zero or more [visitUpperBound] calls must be done first, followed by [visitEnd]. */