Metadata comparator: Support new metadata attributes (see below)

Support new metadata attributes that were added to Kotlin metadata
but are not yet supported in `MetadataDeclarationsComparator`:
- DNN type flag
- context receivers
- underlying type & property name for inline classes

^KT-62753
This commit is contained in:
Dmitriy Dolovov
2024-01-08 11:44:30 +01:00
committed by Space Team
parent 59b8941c28
commit 6951efe63c
2 changed files with 43 additions and 20 deletions
@@ -14,19 +14,7 @@ import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsCompar
import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator.Result import org.jetbrains.kotlin.commonizer.metadata.utils.MetadataDeclarationsComparator.Result
import org.jetbrains.kotlin.commonizer.utils.KNI_BRIDGE_FUNCTION_PREFIX import org.jetbrains.kotlin.commonizer.utils.KNI_BRIDGE_FUNCTION_PREFIX
import java.util.* import java.util.*
import kotlin.Any
import kotlin.Array
import kotlin.Boolean
import kotlin.Int
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.apply
import kotlin.arrayOf
import kotlin.check
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.error
import kotlin.let
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
@@ -37,7 +25,6 @@ import kotlin.reflect.KProperty1
* The entry point is [MetadataDeclarationsComparator.Companion.compare] function. * The entry point is [MetadataDeclarationsComparator.Companion.compare] function.
*/ */
// TODO: extract to kotlinx-metadata-klib library? // TODO: extract to kotlinx-metadata-klib library?
@Suppress("unused")
class MetadataDeclarationsComparator private constructor(private val config: Config) { class MetadataDeclarationsComparator private constructor(private val config: Config) {
interface Config { interface Config {
@@ -55,9 +42,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
} }
sealed class Result { sealed class Result {
object Success : Result() { data object Success : Result()
override fun toString() = "Success"
}
class Failure(val mismatches: Collection<Mismatch>) : Result() { class Failure(val mismatches: Collection<Mismatch>) : Result() {
init { init {
@@ -68,11 +53,11 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
} }
} }
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate", "unused")
sealed interface PathElement { sealed interface PathElement {
val name: String val name: String
object Root : PathElement { data object Root : PathElement {
override val name get() = "Root" override val name get() = "Root"
} }
@@ -172,12 +157,14 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
UNDERLYING, UNDERLYING,
EXPANDED, EXPANDED,
RECEIVER, RECEIVER,
CONTEXT_RECEIVER,
ABBREVIATED, ABBREVIATED,
OUTER, OUTER,
UPPER_BOUND, UPPER_BOUND,
VALUE_PARAMETER, VALUE_PARAMETER,
VALUE_PARAMETER_VARARG, VALUE_PARAMETER_VARARG,
TYPE_ARGUMENT; TYPE_ARGUMENT,
INLINE_CLASS_UNDERLYING;
override fun toString() = "TypeKind.$name" override fun toString() = "TypeKind.$name"
} }
@@ -218,6 +205,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
val EnumEntry by EntityKindImpl val EnumEntry by EntityKindImpl
val EnumEntryInKlib by EntityKindImpl val EnumEntryInKlib by EntityKindImpl
val EnumEntryInKlibOrdinal by EntityKindImpl val EnumEntryInKlibOrdinal by EntityKindImpl
val InlineClassUnderlyingProperty by EntityKindImpl
val CompileTimeValue by EntityKindImpl val CompileTimeValue by EntityKindImpl
@@ -278,6 +266,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
val existentValue: Any, val existentValue: Any,
val missingInA: Boolean val missingInA: Boolean
) : Mismatch() { ) : Mismatch() {
@Suppress("unused")
val missingInB: Boolean val missingInB: Boolean
get() = !missingInA get() = !missingInA
@@ -512,6 +501,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
) )
} }
@OptIn(ExperimentalContextReceivers::class)
private fun compareClasses( private fun compareClasses(
classContext: Context, classContext: Context,
classA: KmClass, classA: KmClass,
@@ -523,6 +513,21 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
compareTypeParameterLists(classContext, classA.typeParameters, classB.typeParameters) compareTypeParameterLists(classContext, classA.typeParameters, classB.typeParameters)
compareTypeLists(classContext, classA.supertypes, classB.supertypes, TypeKind.SUPERTYPE) compareTypeLists(classContext, classA.supertypes, classB.supertypes, TypeKind.SUPERTYPE)
compareTypeLists(classContext, classA.contextReceiverTypes, classB.contextReceiverTypes, TypeKind.CONTEXT_RECEIVER)
compareNullableEntities(
containerContext = classContext,
entityA = classA.inlineClassUnderlyingType,
entityB = classB.inlineClassUnderlyingType,
entityKind = TypeKind.INLINE_CLASS_UNDERLYING,
entitiesComparator = ::compareTypes
)
compareNullableValues(
containerContext = classContext,
valueA = classA.inlineClassUnderlyingPropertyName,
valueB = classB.inlineClassUnderlyingPropertyName,
valueKind = EntityKind.InlineClassUnderlyingProperty
)
compareConstructorLists(classContext, classA.constructors, classB.constructors) compareConstructorLists(classContext, classA.constructors, classB.constructors)
compareTypeAliasLists(classContext, classA.typeAliases, classB.typeAliases) compareTypeAliasLists(classContext, classA.typeAliases, classB.typeAliases)
@@ -572,6 +577,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
) )
} }
@OptIn(ExperimentalContextReceivers::class)
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
private fun compareProperties( private fun compareProperties(
propertyContext: Context, propertyContext: Context,
@@ -597,6 +603,12 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
entityKind = TypeKind.RECEIVER, entityKind = TypeKind.RECEIVER,
entitiesComparator = ::compareTypes entitiesComparator = ::compareTypes
) )
compareTypeLists(
containerContext = propertyContext,
typeListA = propertyA.contextReceiverTypes,
typeListB = propertyB.contextReceiverTypes,
typeKind = TypeKind.CONTEXT_RECEIVER
)
compareEntities( compareEntities(
containerContext = propertyContext, containerContext = propertyContext,
entityA = propertyA.returnType, entityA = propertyA.returnType,
@@ -616,7 +628,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
compareNullableValues(propertyContext, propertyA.compileTimeValue, propertyB.compileTimeValue, EntityKind.CompileTimeValue) compareNullableValues(propertyContext, propertyA.compileTimeValue, propertyB.compileTimeValue, EntityKind.CompileTimeValue)
} }
@OptIn(ExperimentalContracts::class) @OptIn(ExperimentalContracts::class, ExperimentalContextReceivers::class)
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
private fun compareFunctions( private fun compareFunctions(
functionContext: Context, functionContext: Context,
@@ -635,6 +647,12 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
entityKind = TypeKind.RECEIVER, entityKind = TypeKind.RECEIVER,
entitiesComparator = ::compareTypes entitiesComparator = ::compareTypes
) )
compareTypeLists(
containerContext = functionContext,
typeListA = functionA.contextReceiverTypes,
typeListB = functionB.contextReceiverTypes,
typeKind = TypeKind.CONTEXT_RECEIVER
)
compareEntities( compareEntities(
containerContext = functionContext, containerContext = functionContext,
entityA = functionA.returnType, entityA = functionA.returnType,
@@ -850,6 +868,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
mismatches += Mismatch.DifferentValues(valueKind, valueName.orEmpty(), containerContext.path, valueA, valueB) mismatches += Mismatch.DifferentValues(valueKind, valueName.orEmpty(), containerContext.path, valueA, valueB)
} }
@Suppress("ConvertArgumentToSet")
private fun <E : Any> compareValueLists( private fun <E : Any> compareValueLists(
containerContext: Context, containerContext: Context,
listA: Collection<E>, listA: Collection<E>,
@@ -1061,6 +1080,7 @@ class MetadataDeclarationsComparator private constructor(private val config: Con
private val TYPE_FLAGS: Array<KProperty1<KmType, Boolean>> = arrayOf( private val TYPE_FLAGS: Array<KProperty1<KmType, Boolean>> = arrayOf(
KmType::isNullable, KmType::isNullable,
KmType::isSuspend, KmType::isSuspend,
KmType::isDefinitelyNonNull,
) )
private val TYPE_PARAMETER_FLAGS: Array<KProperty1<KmTypeParameter, Boolean>> = arrayOf( private val TYPE_PARAMETER_FLAGS: Array<KProperty1<KmTypeParameter, Boolean>> = arrayOf(
@@ -56,6 +56,9 @@ private val FILTER_OUT_ACCEPTABLE_MISMATCHES: (Mismatch) -> Boolean = { mismatch
when (mismatch) { when (mismatch) {
is Mismatch.MissingEntity -> when (mismatch.kind) { is Mismatch.MissingEntity -> when (mismatch.kind) {
EntityKind.TypeKind.INLINE_CLASS_UNDERLYING, EntityKind.InlineClassUnderlyingProperty -> {
isAcceptableMismatch = true
}
EntityKind.TypeKind.ABBREVIATED -> { EntityKind.TypeKind.ABBREVIATED -> {
val usefulPath = mismatch.path val usefulPath = mismatch.path
.dropWhile { it !is PathElement.Package } .dropWhile { it !is PathElement.Package }