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:
committed by
Space Team
parent
59b8941c28
commit
6951efe63c
+40
-20
@@ -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 }
|
||||||
|
|||||||
Reference in New Issue
Block a user