Compare module metadata in JVM ABI consistency tests
This commit is contained in:
committed by
Space Team
parent
ba217ad688
commit
b74501ee93
@@ -25,6 +25,14 @@ fun ClassFileFactory.getClassFiles(): Iterable<OutputFile> {
|
|||||||
return asList().filterClassFiles()
|
return asList().filterClassFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ClassFileFactory.getKotlinModuleFile(): OutputFile? = asList().filter { it.relativePath.endsWith(".kotlin_module") }.run {
|
||||||
|
when (size) {
|
||||||
|
0 -> null
|
||||||
|
1 -> single()
|
||||||
|
else -> error("Module has non-unique .kotlin_metadata file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun List<OutputFile>.filterClassFiles(): List<OutputFile> {
|
fun List<OutputFile>.filterClassFiles(): List<OutputFile> {
|
||||||
return filter { it.relativePath.endsWith(".class") }
|
return filter { it.relativePath.endsWith(".class") }
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -9,3 +9,9 @@ MODULE main
|
|||||||
<set-?>: kotlin/Int
|
<set-?>: kotlin/Int
|
||||||
K2
|
K2
|
||||||
value: kotlin/Int
|
value: kotlin/Int
|
||||||
|
MODULE METADATA
|
||||||
|
Property: module.metadata.optionalAnnotations
|
||||||
|
K1
|
||||||
|
[Anno]
|
||||||
|
K2
|
||||||
|
[]
|
||||||
|
|||||||
+35
-9
@@ -10,8 +10,10 @@ import org.jetbrains.kotlin.abicmp.defects.Location
|
|||||||
import org.jetbrains.kotlin.abicmp.reports.*
|
import org.jetbrains.kotlin.abicmp.reports.*
|
||||||
import org.jetbrains.kotlin.abicmp.tag
|
import org.jetbrains.kotlin.abicmp.tag
|
||||||
import org.jetbrains.kotlin.abicmp.tasks.ClassTask
|
import org.jetbrains.kotlin.abicmp.tasks.ClassTask
|
||||||
|
import org.jetbrains.kotlin.abicmp.tasks.ModuleMetadataTask
|
||||||
import org.jetbrains.kotlin.abicmp.tasks.checkerConfiguration
|
import org.jetbrains.kotlin.abicmp.tasks.checkerConfiguration
|
||||||
import org.jetbrains.kotlin.codegen.getClassFiles
|
import org.jetbrains.kotlin.codegen.getClassFiles
|
||||||
|
import org.jetbrains.kotlin.codegen.getKotlinModuleFile
|
||||||
import org.jetbrains.kotlin.test.backend.ir.AbiCheckerSuppressor
|
import org.jetbrains.kotlin.test.backend.ir.AbiCheckerSuppressor
|
||||||
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
||||||
import org.jetbrains.kotlin.test.model.*
|
import org.jetbrains.kotlin.test.model.*
|
||||||
@@ -35,6 +37,7 @@ class JvmAbiConsistencyHandler(testServices: TestServices) : AnalysisHandler<Bin
|
|||||||
val missingInK1: Set<String>,
|
val missingInK1: Set<String>,
|
||||||
val missingInK2: Set<String>,
|
val missingInK2: Set<String>,
|
||||||
val nonEmptyClassReports: MutableList<ClassReport>,
|
val nonEmptyClassReports: MutableList<ClassReport>,
|
||||||
|
val moduleMetadataReport: ModuleMetadataReport,
|
||||||
)
|
)
|
||||||
|
|
||||||
private class TestReport {
|
private class TestReport {
|
||||||
@@ -63,9 +66,14 @@ class JvmAbiConsistencyHandler(testServices: TestServices) : AnalysisHandler<Bin
|
|||||||
node("MODULE $module") {
|
node("MODULE $module") {
|
||||||
reportMissing("K1", report.missingInK1)
|
reportMissing("K1", report.missingInK1)
|
||||||
reportMissing("K2", report.missingInK2)
|
reportMissing("K2", report.missingInK2)
|
||||||
|
|
||||||
report.nonEmptyClassReports.forEach { classReport ->
|
report.nonEmptyClassReports.forEach { classReport ->
|
||||||
with(classReport) { appendClassReport() }
|
with(classReport) { appendClassReport() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!report.moduleMetadataReport.isEmpty()) {
|
||||||
|
with(report.moduleMetadataReport) { appendModuleMetadataReport() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,27 +172,45 @@ class JvmAbiConsistencyHandler(testServices: TestServices) : AnalysisHandler<Bin
|
|||||||
if (AbiCheckerSuppressor.ignoredByBackendOrInliner(testServices)) return
|
if (AbiCheckerSuppressor.ignoredByBackendOrInliner(testServices)) return
|
||||||
val classesFromK1 = info.fromK1.classFileFactory.getClassFiles().associate { it.relativePath to it.asByteArray() }
|
val classesFromK1 = info.fromK1.classFileFactory.getClassFiles().associate { it.relativePath to it.asByteArray() }
|
||||||
val classesFromK2 = info.fromK2.classFileFactory.getClassFiles().associate { it.relativePath to it.asByteArray() }
|
val classesFromK2 = info.fromK2.classFileFactory.getClassFiles().associate { it.relativePath to it.asByteArray() }
|
||||||
val missingInK2 = Sets.difference(classesFromK1.keys, classesFromK2.keys)
|
val missingInK2 = Sets.difference(classesFromK1.keys, classesFromK2.keys).toMutableSet()
|
||||||
val missingInK1 = Sets.difference(classesFromK2.keys, classesFromK1.keys)
|
val missingInK1 = Sets.difference(classesFromK2.keys, classesFromK1.keys).toMutableSet()
|
||||||
val commonClasses = Sets.intersection(classesFromK1.keys, classesFromK2.keys)
|
val commonClasses = Sets.intersection(classesFromK1.keys, classesFromK2.keys)
|
||||||
|
|
||||||
|
val configuration = checkerConfiguration {
|
||||||
|
// Indication of constants is different in K2 as expected
|
||||||
|
// We simply turn the checker off to avoid producing an enormous number of difference reports
|
||||||
|
disable("class.metadata.property.hasConstant")
|
||||||
|
}
|
||||||
|
|
||||||
val nonEmptyClassReports = mutableListOf<ClassReport>()
|
val nonEmptyClassReports = mutableListOf<ClassReport>()
|
||||||
commonClasses.forEach { classInternalName ->
|
commonClasses.forEach { classInternalName ->
|
||||||
val k1ClassNode = parseClassNode(classesFromK1[classInternalName]!!)
|
val k1ClassNode = parseClassNode(classesFromK1[classInternalName]!!)
|
||||||
val k2ClassNode = parseClassNode(classesFromK2[classInternalName]!!)
|
val k2ClassNode = parseClassNode(classesFromK2[classInternalName]!!)
|
||||||
val classReport = ClassReport(Location.Class("", classInternalName), classInternalName, "K1", "K2", DefectReport())
|
val classReport = ClassReport(Location.Class("", classInternalName), classInternalName, "K1", "K2", DefectReport())
|
||||||
ClassTask(checkerConfiguration {
|
ClassTask(configuration, k1ClassNode, k2ClassNode, classReport).run()
|
||||||
// Indication of constants is different in K2 as expected
|
|
||||||
// We simply turn the checker off to avoid producing an enormous number of difference reports
|
|
||||||
disable("class.metadata.property.hasConstant")
|
|
||||||
}, k1ClassNode, k2ClassNode, classReport).run()
|
|
||||||
if (classReport.isNotEmpty()) {
|
if (classReport.isNotEmpty()) {
|
||||||
nonEmptyClassReports.add(classReport)
|
nonEmptyClassReports.add(classReport)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonEmptyClassReports.isNotEmpty() || missingInK1.isNotEmpty() || missingInK2.isNotEmpty()) {
|
val k1ModuleFile = info.fromK1.classFileFactory.getKotlinModuleFile()
|
||||||
testReport.addModuleReport(module.name, ModuleReport(missingInK1, missingInK2, nonEmptyClassReports))
|
val k2ModuleFile = info.fromK2.classFileFactory.getKotlinModuleFile()
|
||||||
|
|
||||||
|
if (k1ModuleFile == null && k2ModuleFile != null) {
|
||||||
|
missingInK1.add(k2ModuleFile.relativePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k1ModuleFile != null && k2ModuleFile == null) {
|
||||||
|
missingInK2.add(k1ModuleFile.relativePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
val moduleMetadataReport = ModuleMetadataReport("K1", "K2")
|
||||||
|
if (k1ModuleFile != null && k2ModuleFile != null) {
|
||||||
|
ModuleMetadataTask(configuration, k1ModuleFile.asByteArray(), k2ModuleFile.asByteArray(), moduleMetadataReport).run()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonEmptyClassReports.isNotEmpty() || missingInK1.isNotEmpty() || missingInK2.isNotEmpty() || !moduleMetadataReport.isEmpty()) {
|
||||||
|
testReport.addModuleReport(module.name, ModuleReport(missingInK1, missingInK2, nonEmptyClassReports, moduleMetadataReport))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-7
@@ -5,19 +5,22 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.abicmp.checkers
|
package org.jetbrains.kotlin.abicmp.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.abicmp.reports.MetadataPropertyReport
|
||||||
|
import org.jetbrains.kotlin.abicmp.reports.NamedDiffEntry
|
||||||
import kotlin.metadata.KmConstructor
|
import kotlin.metadata.KmConstructor
|
||||||
import kotlin.metadata.KmFunction
|
import kotlin.metadata.KmFunction
|
||||||
import kotlin.metadata.KmProperty
|
import kotlin.metadata.KmProperty
|
||||||
import kotlin.metadata.KmTypeAlias
|
import kotlin.metadata.KmTypeAlias
|
||||||
import org.jetbrains.kotlin.abicmp.reports.MetadataPropertyReport
|
import kotlin.metadata.jvm.KmModule
|
||||||
import org.jetbrains.kotlin.abicmp.reports.NamedDiffEntry
|
import kotlin.metadata.jvm.KmPackageParts
|
||||||
|
import kotlin.metadata.jvm.UnstableMetadataApi
|
||||||
|
|
||||||
interface GenericMetadataChecker<T> : Checker {
|
interface GenericMetadataChecker<T> : Checker {
|
||||||
fun check(metadata1: T, metadata2: T, report: MetadataPropertyReport)
|
fun check(metadata1: T, metadata2: T, report: MetadataPropertyReport)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class GenericMetadataPropertyChecker<T>(name: String) :
|
abstract class GenericMetadataPropertyChecker<T>(name: String) :
|
||||||
PropertyChecker<String, T>("class.metadata.$name"),
|
PropertyChecker<String, T>(name),
|
||||||
GenericMetadataChecker<T> {
|
GenericMetadataChecker<T> {
|
||||||
|
|
||||||
override fun check(metadata1: T, metadata2: T, report: MetadataPropertyReport) {
|
override fun check(metadata1: T, metadata2: T, report: MetadataPropertyReport) {
|
||||||
@@ -29,22 +32,34 @@ abstract class GenericMetadataPropertyChecker<T>(name: String) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
fun moduleMetadataPropertyChecker(name: String, propertyGetter: (KmModule) -> String) =
|
||||||
|
object : GenericMetadataPropertyChecker<KmModule>("module.metadata.$name") {
|
||||||
|
override fun getProperty(node: KmModule) = propertyGetter(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
fun packagePartsPropertyChecker(name: String, propertyGetter: (KmPackageParts) -> String) =
|
||||||
|
object : GenericMetadataPropertyChecker<KmPackageParts>("module.metadata.$name") {
|
||||||
|
override fun getProperty(node: KmPackageParts) = propertyGetter(node)
|
||||||
|
}
|
||||||
|
|
||||||
fun constructorMetadataPropertyChecker(name: String, propertyGetter: (KmConstructor) -> String) =
|
fun constructorMetadataPropertyChecker(name: String, propertyGetter: (KmConstructor) -> String) =
|
||||||
object : GenericMetadataPropertyChecker<KmConstructor>("constructor.$name") {
|
object : GenericMetadataPropertyChecker<KmConstructor>("class.metadata.constructor.$name") {
|
||||||
override fun getProperty(node: KmConstructor) = propertyGetter(node)
|
override fun getProperty(node: KmConstructor) = propertyGetter(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun functionMetadataPropertyChecker(name: String, propertyGetter: (KmFunction) -> String) =
|
fun functionMetadataPropertyChecker(name: String, propertyGetter: (KmFunction) -> String) =
|
||||||
object : GenericMetadataPropertyChecker<KmFunction>("function.$name") {
|
object : GenericMetadataPropertyChecker<KmFunction>("class.metadata.function.$name") {
|
||||||
override fun getProperty(node: KmFunction) = propertyGetter(node)
|
override fun getProperty(node: KmFunction) = propertyGetter(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun typeAliasMetadataPropertyChecker(name: String, propertyGetter: (KmTypeAlias) -> String) =
|
fun typeAliasMetadataPropertyChecker(name: String, propertyGetter: (KmTypeAlias) -> String) =
|
||||||
object : GenericMetadataPropertyChecker<KmTypeAlias>("typeAlias.$name") {
|
object : GenericMetadataPropertyChecker<KmTypeAlias>("class.metadata.typeAlias.$name") {
|
||||||
override fun getProperty(node: KmTypeAlias) = propertyGetter(node)
|
override fun getProperty(node: KmTypeAlias) = propertyGetter(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun propertyMetadataPropertyChecker(name: String, propertyGetter: (KmProperty) -> String) =
|
fun propertyMetadataPropertyChecker(name: String, propertyGetter: (KmProperty) -> String) =
|
||||||
object : GenericMetadataPropertyChecker<KmProperty>("property.$name") {
|
object : GenericMetadataPropertyChecker<KmProperty>("class.metadata.property.$name") {
|
||||||
override fun getProperty(node: KmProperty) = propertyGetter(node)
|
override fun getProperty(node: KmProperty) = propertyGetter(node)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.abicmp.reports
|
|||||||
import org.jetbrains.kotlin.abicmp.tag
|
import org.jetbrains.kotlin.abicmp.tag
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
|
|
||||||
class MetadataPropertyReport(val id: String, val header1: String, val header2: String) : ComparisonReport {
|
open class MetadataPropertyReport(val id: String, val header1: String, val header2: String) : ComparisonReport {
|
||||||
|
|
||||||
private val propertyDiffs = ArrayList<NamedDiffEntry>()
|
protected val propertyDiffs = ArrayList<NamedDiffEntry>()
|
||||||
|
|
||||||
override fun isEmpty() = propertyDiffs.isEmpty()
|
override fun isEmpty() = propertyDiffs.isEmpty()
|
||||||
|
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.abicmp.reports
|
||||||
|
|
||||||
|
import java.io.PrintWriter
|
||||||
|
|
||||||
|
class ModuleMetadataReport(header1: String, header2: String) : MetadataPropertyReport("MODULE METADATA", header1, header2) {
|
||||||
|
|
||||||
|
private val packagePartsReports = ArrayList<MetadataPropertyReport>()
|
||||||
|
|
||||||
|
override fun isEmpty() = propertyDiffs.isEmpty() && getFilteredPackagePartsReports().isEmpty()
|
||||||
|
|
||||||
|
override fun writeAsHtml(output: PrintWriter) {
|
||||||
|
if (isEmpty()) return
|
||||||
|
super.writeAsHtml(output)
|
||||||
|
packagePartsReports.forEach { it.writeAsHtml(output) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TextTreeBuilderContext.appendModuleMetadataReport() {
|
||||||
|
node("MODULE METADATA") {
|
||||||
|
appendNamedDiffEntries(header1, header2, propertyDiffs, "Property")
|
||||||
|
|
||||||
|
for (report in getFilteredPackagePartsReports()) {
|
||||||
|
with(report) { appendReport() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun packagePartsReport(id: String) = MetadataPropertyReport(id, header1, header2).also { packagePartsReports.add(it) }
|
||||||
|
|
||||||
|
private fun getFilteredPackagePartsReports() = packagePartsReports.filter { !it.isEmpty() }.sortedBy { it.id }
|
||||||
|
|
||||||
|
}
|
||||||
+20
@@ -153,6 +153,23 @@ private val allPackageMetadataCheckers = listOf(
|
|||||||
fileFacadeMetadataListChecker("localDelegatedProperties") { loadLocalDelegatedProperties(it).keys.toList() }
|
fileFacadeMetadataListChecker("localDelegatedProperties") { loadLocalDelegatedProperties(it).keys.toList() }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
private val allPackagePartsMetadataCheckers = listOf(
|
||||||
|
packagePartsPropertyChecker("multiFileParts") {
|
||||||
|
it.multiFileClassParts.toList().map { filePart -> "(${filePart.first}, ${filePart.second})" }.toList().sorted()
|
||||||
|
.joinToString(prefix = "[", postfix = "]")
|
||||||
|
},
|
||||||
|
packagePartsPropertyChecker("fileFacades") { it.fileFacades.toList().sorted().joinToString(prefix = "[", postfix = "]") }
|
||||||
|
)
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
private val allModuleMetadataCheckers = listOf(
|
||||||
|
moduleMetadataPropertyChecker("optionalAnnotations") {
|
||||||
|
it.optionalAnnotationClasses.map { clazz -> clazz.name }.sorted().joinToString(prefix = "[", postfix = "]")
|
||||||
|
},
|
||||||
|
moduleMetadataPropertyChecker("packageParts") { it.packageParts.keys.toList().sorted().joinToString(prefix = "[", postfix = "]") }
|
||||||
|
)
|
||||||
|
|
||||||
private val allMultifileClassFacadeMetadataCheckers = listOf(
|
private val allMultifileClassFacadeMetadataCheckers = listOf(
|
||||||
multiFileClassFacadeMetadataListChecker("partClassNames") { it.partClassNames }
|
multiFileClassFacadeMetadataListChecker("partClassNames") { it.partClassNames }
|
||||||
)
|
)
|
||||||
@@ -190,6 +207,7 @@ inline fun checkerConfiguration(b: CheckerConfigurationBuilder.() -> Unit): Chec
|
|||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
class CheckerConfiguration(private val enabledExclusively: Set<String>, private val disabled: Set<String>) {
|
class CheckerConfiguration(private val enabledExclusively: Set<String>, private val disabled: Set<String>) {
|
||||||
|
|
||||||
private fun <T : Checker> List<T>.filterOutDisabled() = filter { it.isEnabled() }
|
private fun <T : Checker> List<T>.filterOutDisabled() = filter { it.isEnabled() }
|
||||||
@@ -206,6 +224,8 @@ class CheckerConfiguration(private val enabledExclusively: Set<String>, private
|
|||||||
val enabledMultifileClassFacadeMetadataCheckers = allMultifileClassFacadeMetadataCheckers.filterOutDisabled()
|
val enabledMultifileClassFacadeMetadataCheckers = allMultifileClassFacadeMetadataCheckers.filterOutDisabled()
|
||||||
val enabledMultifileClassPartMetadataCheckers = allMultifileClassPartMetadataCheckers.filterOutDisabled()
|
val enabledMultifileClassPartMetadataCheckers = allMultifileClassPartMetadataCheckers.filterOutDisabled()
|
||||||
val enabledAllSyntheticClassMetadataCheckers = allSyntheticClassMetadataCheckers.filterOutDisabled()
|
val enabledAllSyntheticClassMetadataCheckers = allSyntheticClassMetadataCheckers.filterOutDisabled()
|
||||||
|
val enabledModuleMetadataCheckers = allModuleMetadataCheckers.filterOutDisabled()
|
||||||
|
val enabledPackagePartsMetadataCheckers = allPackagePartsMetadataCheckers.filterOutDisabled()
|
||||||
|
|
||||||
private fun Checker.isEnabled(): Boolean {
|
private fun Checker.isEnabled(): Boolean {
|
||||||
if (enabledExclusively.isNotEmpty() && name !in enabledExclusively) return false
|
if (enabledExclusively.isNotEmpty() && name !in enabledExclusively) return false
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.abicmp.tasks
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.abicmp.reports.ModuleMetadataReport
|
||||||
|
import kotlin.metadata.jvm.KotlinModuleMetadata
|
||||||
|
import kotlin.metadata.jvm.UnstableMetadataApi
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
class ModuleMetadataTask(
|
||||||
|
private val configuration: CheckerConfiguration,
|
||||||
|
metadata1Bytes: ByteArray,
|
||||||
|
metadata2Bytes: ByteArray,
|
||||||
|
private val report: ModuleMetadataReport,
|
||||||
|
) : Runnable {
|
||||||
|
|
||||||
|
private val metadata1 = metadata1Bytes.toKmModule()
|
||||||
|
private val metadata2 = metadata2Bytes.toKmModule()
|
||||||
|
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
for (checker in configuration.enabledModuleMetadataCheckers) {
|
||||||
|
checker.check(metadata1, metadata2, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPackageParts()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkPackageParts() {
|
||||||
|
val packageParts1 = metadata1.packageParts
|
||||||
|
val packageParts2 = metadata2.packageParts
|
||||||
|
|
||||||
|
val commonIds = packageParts1.keys.intersect(packageParts2.keys).sorted()
|
||||||
|
for (id in commonIds) {
|
||||||
|
val packagePart1 = packageParts1[id]!!
|
||||||
|
val packagePart2 = packageParts2[id]!!
|
||||||
|
val packagePartsReport = report.packagePartsReport(id)
|
||||||
|
PackagePartsMetadataTask(configuration, packagePart1, packagePart2, packagePartsReport).run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
private fun ByteArray.toKmModule() = KotlinModuleMetadata.read(this).kmModule
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.abicmp.tasks
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.abicmp.reports.MetadataPropertyReport
|
||||||
|
import kotlin.metadata.jvm.KmPackageParts
|
||||||
|
import kotlin.metadata.jvm.UnstableMetadataApi
|
||||||
|
|
||||||
|
@OptIn(UnstableMetadataApi::class)
|
||||||
|
class PackagePartsMetadataTask(
|
||||||
|
private val configuration: CheckerConfiguration,
|
||||||
|
private val packagePart1: KmPackageParts,
|
||||||
|
private val packagePart2: KmPackageParts,
|
||||||
|
private val packagePartsReport: MetadataPropertyReport
|
||||||
|
): Runnable {
|
||||||
|
override fun run() {
|
||||||
|
for (checker in configuration.enabledPackagePartsMetadataCheckers) {
|
||||||
|
checker.check(packagePart1, packagePart2, packagePartsReport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user