org.jetbrains.kotlin.jvm.abi.JvmAbiClassInfoBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jvm-abi-gen Show documentation
Show all versions of jvm-abi-gen Show documentation
ABI generation for Kotlin/JVM
The newest version!
/*
* 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.jvm.abi
/**
* Collects information about kept/stripped/deleted classes, and then adapts it so that it would be consistent if private interfaces
* are present in the module. The latter is done only if [removePrivateClasses] is enabled.
*
* When using this class, call [recordInitialClassInfo]/[addInnerClass] repeatedly until all necessary data is collected, and then call
* [buildClassInfo] to get the resulting class infos.
*
* Private interface is a special case from the ABI standpoint because it is allowed to expose private interface by inheriting a public
* class from it, see KT-20088. This code keeps all private interfaces which are implemented (perhaps indirectly) by at least one public
* (in terms of ABI) class in the module. Also, in case such private interface is nested, all its outer classes should be kept but pruned.
*/
internal class JvmAbiClassInfoBuilder(private val removePrivateClasses: Boolean) {
private val abiClassInfo = mutableMapOf()
private val innerClassToOuter = mutableMapOf()
private val allSuperInterfaces = mutableMapOf>()
fun recordInitialClassInfo(className: String, info: AbiClassInfo, superInterfaces: List) {
abiClassInfo[className] = info
if (removePrivateClasses) {
allSuperInterfaces[className] = superInterfaces
}
}
fun addInnerClass(innerClass: String, outerClass: String?) {
if (outerClass == null) return
if (removePrivateClasses) {
innerClassToOuter.getOrPut(innerClass) { outerClass }
}
}
fun buildClassInfo(): Map {
if (removePrivateClasses) {
for ((className, info) in abiClassInfo.toMap()) {
if (info != AbiClassInfo.Deleted) {
keepInterfacesOf(className)
}
}
}
return abiClassInfo
}
private fun keepInterfacesOf(className: String) {
for (superInterface in allSuperInterfaces[className].orEmpty()) {
if (abiClassInfo.put(superInterface, AbiClassInfo.Public) == AbiClassInfo.Public)
continue
for (outerClass in generateSequence(superInterface, innerClassToOuter::get).drop(1)) {
if (abiClassInfo[outerClass] == AbiClassInfo.Deleted) {
abiClassInfo[outerClass] = AbiClassInfo.Stripped(emptyMap(), prune = true)
}
}
keepInterfacesOf(superInterface)
}
}
}