[KLIB tool] Support metadata format by kotlinp

Use the unified metadata printing format in KLIB tool. The same format
is already used in `kotlinp` CLI tool.

^KT-62340
This commit is contained in:
Dmitriy Dolovov
2024-02-09 15:30:01 +01:00
committed by Space Team
parent 83cc0d75a7
commit f9f97f2050
4 changed files with 321 additions and 77 deletions
+3
View File
@@ -18,6 +18,9 @@ dependencies {
implementation(project(":compiler:ir.psi2ir")) implementation(project(":compiler:ir.psi2ir"))
implementation(project(":compiler:ir.serialization.native")) implementation(project(":compiler:ir.serialization.native"))
implementation(project(":kotlin-util-klib-abi")) implementation(project(":kotlin-util-klib-abi"))
implementation(project(":tools:kotlinp-klib"))
implementation(project(":kotlinx-metadata-klib")) { isTransitive = false }
implementation(project(":kotlinx-metadata")) { isTransitive = false }
} }
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> { tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
@@ -0,0 +1,239 @@
/*
* 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.cli.klib
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmFunction
import kotlinx.metadata.KmPackage
import kotlinx.metadata.KmProperty
import kotlinx.metadata.internal.common.KmModuleFragment
import kotlinx.metadata.klib.KlibModuleMetadata
import kotlinx.metadata.klib.className
import kotlinx.metadata.klib.fqName
import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
import org.jetbrains.kotlin.ir.util.IdSignatureRenderer
import org.jetbrains.kotlin.kotlinp.Printer
import org.jetbrains.kotlin.kotlinp.Settings
import org.jetbrains.kotlin.kotlinp.klib.*
import org.jetbrains.kotlin.kotlinp.klib.TypeArgumentId.VarianceId
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf
internal class KotlinpBasedMetadataDumper(
output: Appendable,
printSignatures: Boolean,
signatureVersion: KotlinIrSignatureVersion?
) {
// `null` means no signatures should be rendered.
private val signatureRenderer = runIf(printSignatures) { signatureVersion.getMostSuitableSignatureRenderer() }
private val printer = Printer(output)
fun dumpLibrary(library: KotlinLibrary, testMode: Boolean) {
val moduleMetadata = loadModuleMetadata(library)
.let { originalModuleMetadata -> if (testMode) preprocessMetadataForTests(originalModuleMetadata) else originalModuleMetadata }
val signatureComputer = prepareSignatureComputer(library, moduleMetadata)
KlibKotlinp(DEFAULT_SETTINGS, signatureComputer).renderModule(moduleMetadata, printer)
}
private fun preprocessMetadataForTests(originalModuleMetadata: KlibModuleMetadata) = KlibModuleMetadata(
name = originalModuleMetadata.name,
fragments = originalModuleMetadata.fragments.groupBy { it.fqName }.mapNotNull { (packageFqName, fragments) ->
val classNames = fragments.flatMap { it.className }.sorted()
val classes = fragments.flatMap { it.classes }.sortedBy { it.name }
val functions = fragments.flatMap { it.pkg?.functions.orEmpty() }.sortedBy { it.sortingKey() }
val properties = fragments.flatMap { it.pkg?.properties.orEmpty() }.sortedBy { it.sortingKey() }
val typeAliases = fragments.flatMap { it.pkg?.typeAliases.orEmpty() }.sortedBy { it.name }
if (classNames.isEmpty() && classes.isEmpty() && functions.isEmpty() && properties.isEmpty() && typeAliases.isEmpty())
return@mapNotNull null
classes.forEach { clazz ->
clazz.constructors.sortBy { it.sortingKey() }
clazz.functions.sortBy { it.sortingKey() }
clazz.properties.sortBy { it.sortingKey() }
clazz.typeAliases.sortBy { it.name }
}
KmModuleFragment().apply {
this.fqName = packageFqName
this.className += classNames
this.classes += classes
if (functions.isNotEmpty() || properties.isNotEmpty() || typeAliases.isNotEmpty()) {
this.pkg = KmPackage().apply {
this.functions += functions
this.properties += properties
this.typeAliases += typeAliases
}
}
}
}.sortedBy { it.fqName.orEmpty() },
annotations = originalModuleMetadata.annotations
)
private fun loadModuleMetadata(library: KotlinLibrary) = KlibModuleMetadata.read(
object : KlibModuleMetadata.MetadataLibraryProvider {
override val moduleHeaderData get() = library.moduleHeaderData
override fun packageMetadata(fqName: String, partName: String) = library.packageMetadata(fqName, partName)
override fun packageMetadataParts(fqName: String) = library.packageMetadataParts(fqName)
}
)
private fun prepareSignatureComputer(library: KotlinLibrary, moduleMetadata: KlibModuleMetadata): ExternalSignatureComputer? {
val signatureCollector = SignaturesCollector(signatureRenderer ?: return null)
val moduleDescriptor = ModuleDescriptorLoader.load(library)
moduleDescriptor.accept(signatureCollector, Unit)
return ExternalSignatureComputer(moduleMetadata, signatureCollector.signatures::get)
}
private fun KmConstructor.sortingKey() = constructorId("")
private fun KmFunction.sortingKey() = functionId("")
private fun KmProperty.sortingKey() = propertyId("")
companion object {
private val DEFAULT_SETTINGS = Settings(isVerbose = true, sortDeclarations = true)
}
}
private class SignaturesCollector(private val renderer: IdSignatureRenderer) : DeclarationDescriptorVisitorEmptyBodies<Unit, Unit>() {
private val signaturer = KonanIdSignaturer(KonanManglerDesc)
val signatures = hashMapOf<DeclarationId, String>()
override fun visitModuleDeclaration(module: ModuleDescriptor, data: Unit) {
module.getPackageFragments().forEach { it.accept(this, data) }
}
override fun visitPackageFragmentDescriptor(fragment: PackageFragmentDescriptor, data: Unit) {
fragment.getMemberScope().getContributedDescriptors().forEach { it.accept(this, data) }
}
override fun visitClassDescriptor(clazz: ClassDescriptor, data: Unit) {
if (clazz.kind == ClassKind.ENUM_ENTRY) {
collectEnumEntrySignature(clazz)
} else {
collectSignature(clazz) { clazz.id() }
}
clazz.constructors.forEach { it.accept(this, data) }
clazz.unsubstitutedMemberScope.getContributedDescriptors().forEach { it.accept(this, data) }
}
override fun visitConstructorDescriptor(constructor: ConstructorDescriptor, data: Unit) {
collectSignature(constructor) { constructor.id() }
}
override fun visitFunctionDescriptor(function: FunctionDescriptor, data: Unit) {
collectSignature(function) { function.id() }
}
override fun visitPropertyDescriptor(property: PropertyDescriptor, data: Unit) {
collectSignature(property) { property.id() }
property.getter?.accept(this, data)
property.setter?.accept(this, data)
}
override fun visitPropertyGetterDescriptor(getter: PropertyGetterDescriptor, data: Unit) {
collectSignature(getter) { getter.id() }
}
override fun visitPropertySetterDescriptor(setter: PropertySetterDescriptor, data: Unit) {
collectSignature(setter) { setter.id(ignoreParameterNames = true) }
}
override fun visitTypeAliasDescriptor(typeAlias: TypeAliasDescriptor, data: Unit) {
collectSignature(typeAlias) { typeAlias.id() }
}
private inline fun <T : DeclarationDescriptor> collectSignature(descriptor: T, id: T.() -> DeclarationId?) {
val rawSignature = signaturer.composeSignature(descriptor) ?: return
val renderedSignature = renderer.render(rawSignature)
val declarationId = descriptor.id() ?: return
signatures[declarationId] = renderedSignature
}
private fun collectEnumEntrySignature(clazz: ClassDescriptor) {
val rawSignature = signaturer.composeEnumEntrySignature(clazz) ?: return
val renderedSignature = renderer.render(rawSignature)
val declarationId = clazz.id() ?: return
signatures[declarationId] = renderedSignature
}
private fun ClassifierDescriptorWithTypeParameters.id() = classId?.asString()?.let(::ClassOrTypeAliasId)
private fun DeclarationDescriptor.qualifiedName(): String {
fun ClassifierDescriptorWithTypeParameters.classIdOrFail() = classId
?: error("Failed to compute class ID for ${this::class.java}, $this")
return when (this) {
is ClassifierDescriptorWithTypeParameters -> classIdOrFail()
is CallableDescriptor -> when (val containingDeclaration = containingDeclaration) {
is ClassifierDescriptorWithTypeParameters -> containingDeclaration.classIdOrFail().createNestedClassId(name)
is PackageFragmentDescriptor -> ClassId(containingDeclaration.fqName, name)
else -> containingDeclaration.unexpectedDeclarationType()
}
else -> unexpectedDeclarationType()
}.asString()
}
private fun ConstructorDescriptor.id() = ConstructorId(
qualifiedName = qualifiedName(),
parameters = valueParameters.map { it.id(ignoreName = false) }
)
private fun PropertyDescriptor.id() = PropertyId(
qualifiedName = qualifiedName(),
contextReceivers = contextReceiverParameters.map { it.type.id() },
extensionReceiver = extensionReceiverParameter?.type?.id(),
returnType = type.id()
)
private fun FunctionDescriptor.id(ignoreParameterNames: Boolean = false) = FunctionId(
qualifiedName = qualifiedName(),
contextReceivers = contextReceiverParameters.map { it.type.id() },
extensionReceiver = extensionReceiverParameter?.type?.id(),
parameters = valueParameters.map { it.id(ignoreParameterNames) },
returnType = returnType?.id() ?: error("Function without return type: ${this::class.java}, $this")
)
private fun Variance.id() = when (this) {
Variance.INVARIANT -> VarianceId.INVARIANT
Variance.IN_VARIANCE -> VarianceId.IN
Variance.OUT_VARIANCE -> VarianceId.OUT
}
private fun SimpleType.classifierId(): ClassifierId = when (val typeConstructorDescriptor = constructor.declarationDescriptor) {
is TypeParameterDescriptor -> TypeParameterId(typeConstructorDescriptor.index)
is ClassifierDescriptorWithTypeParameters -> ClassOrTypeAliasId(typeConstructorDescriptor.qualifiedName())
else -> typeConstructorDescriptor.unexpectedDeclarationType()
}
private fun TypeProjection.id() = if (isStarProjection) TypeArgumentId.Star else TypeArgumentId.Regular(type.id(), projectionKind.id())
private fun KotlinType.id(): TypeId {
val simpleType = asSimpleType()
return TypeId(simpleType.classifierId(), simpleType.arguments.map { it.id() })
}
private fun ValueParameterDescriptor.id(ignoreName: Boolean) =
if (ignoreName) ParameterId(type.id(), isVararg) else ParameterId(name.asString(), type.id(), isVararg)
private fun DeclarationDescriptor?.unexpectedDeclarationType(): Nothing =
error(if (this == null) "Declaration descriptor is null" else "Unexpected declaration type: ${this::class.java}, $this")
}
@@ -0,0 +1,51 @@
/*
* 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.cli.klib
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.konan.library.resolverByName
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.KotlinNativePaths
internal object ModuleDescriptorLoader {
fun load(library: KotlinLibrary): ModuleDescriptorImpl {
val storageManager = LockBasedStorageManager("klib")
val module = KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(library, languageVersionSettings, storageManager, null)
val defaultModules = mutableListOf<ModuleDescriptorImpl>()
if (!module.isNativeStdlib()) {
val resolver = resolverByName(
emptyList(),
distributionKlib = Distribution(KotlinNativePaths.homePath.absolutePath).klib,
skipCurrentDir = true,
logger = KlibToolLogger
)
resolver.defaultLinks(noStdLib = false, noDefaultLibs = true, noEndorsedLibs = true).mapTo(defaultModules) {
KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptor(it, languageVersionSettings, storageManager, module.builtIns, null)
}
}
(defaultModules + module).let { allModules ->
allModules.forEach { it.setDependencies(allModules) }
}
return module
}
val languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
private val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
}
@@ -12,17 +12,10 @@ import org.jetbrains.kotlin.backend.common.serialization.BasicIrModuleDeserializ
import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy
import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer
import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer import org.jetbrains.kotlin.backend.konan.serialization.KonanIdSignaturer
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
@@ -34,26 +27,19 @@ import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolverByName import org.jetbrains.kotlin.konan.library.resolverByName
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.util.DependencyDirectories import org.jetbrains.kotlin.konan.util.DependencyDirectories
import org.jetbrains.kotlin.utils.KotlinNativePaths
import org.jetbrains.kotlin.library.* import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.abi.* import org.jetbrains.kotlin.library.abi.*
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.kotlinLibrary import org.jetbrains.kotlin.library.metadata.kotlinLibrary
import org.jetbrains.kotlin.library.metadata.parseModuleHeader import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.util.Logger import org.jetbrains.kotlin.util.Logger
import org.jetbrains.kotlin.util.removeSuffixIfPresent import org.jetbrains.kotlin.util.removeSuffixIfPresent
import java.io.File import java.io.File
import kotlin.system.exitProcess import kotlin.system.exitProcess
import org.jetbrains.kotlin.konan.file.File as KFile import org.jetbrains.kotlin.konan.file.File as KFile
private val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
fun printUsage() { fun printUsage() {
println( println(
""" """
@@ -79,9 +65,9 @@ fun printUsage() {
(such as Compose) were used during compilation of the library, there would be different (such as Compose) were used during compilation of the library, there would be different
signatures for patched declarations. signatures for patched declarations.
signatures [DEPRECATED] Renamed to "dump-metadata-signatures". Please, use new command name. signatures [DEPRECATED] Renamed to "dump-metadata-signatures". Please, use new command name.
dump-metadata Dump the metadata of all non-private declarations in the library in the form of Kotlin-alike code. dump-metadata Dump the metadata of all declarations in the library. The output of this command is intended
The output of this command is intended to be used for debugging purposes only. to be used for debugging purposes only.
contents [DEPRECATED] Renamed to "dump-metadata". Please, use new command name. contents [DEPRECATED] Reworked and renamed to "dump-metadata". Please, use new command name.
and the options are: and the options are:
-repository <path> [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098 -repository <path> [DEPRECATED] Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098
@@ -178,18 +164,6 @@ object KlibToolLogger : Logger, IrMessageLogger {
val defaultRepository = KFile(DependencyDirectories.localKonanDir.resolve("klib").absolutePath) val defaultRepository = KFile(DependencyDirectories.localKonanDir.resolve("klib").absolutePath)
open class ModuleDeserializer(val library: ByteArray) {
protected val moduleHeader: KlibMetadataProtoBuf.Header
get() = parseModuleHeader(library)
val moduleName: String
get() = moduleHeader.moduleName
val packageFragmentNameList: List<String>
get() = moduleHeader.packageFragmentNameList
}
private class KlibRepoDeprecationWarning { private class KlibRepoDeprecationWarning {
private var alreadyLogged = false private var alreadyLogged = false
@@ -216,7 +190,7 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
val headerCompilerVersion = library.versions.compilerVersion val headerCompilerVersion = library.versions.compilerVersion
val headerLibraryVersion = library.versions.libraryVersion val headerLibraryVersion = library.versions.libraryVersion
val headerMetadataVersion = library.versions.metadataVersion val headerMetadataVersion = library.versions.metadataVersion
val moduleName = ModuleDeserializer(library.moduleHeaderData).moduleName val moduleName = parseModuleHeader(library.moduleHeaderData).moduleName
println("") println("")
println("Resolved to: ${KFile(library.libraryName).absolutePath}") println("Resolved to: ${KFile(library.libraryName).absolutePath}")
@@ -269,15 +243,15 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
} }
class KlibToolLinker( class KlibToolLinker(
module: ModuleDescriptor, irBuiltIns: IrBuiltIns, symbolTable: SymbolTable module: ModuleDescriptor, irBuiltIns: IrBuiltIns, symbolTable: SymbolTable
) : KotlinIrLinker(module, KlibToolLogger, irBuiltIns, symbolTable, emptyList()) { ) : KotlinIrLinker(module, KlibToolLogger, irBuiltIns, symbolTable, emptyList()) {
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider( override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
linker = this, linker = this,
symbolTable = symbolTable, symbolTable = symbolTable,
mangler = KonanManglerIr, mangler = KonanManglerIr,
typeSystem = IrTypeSystemContextImpl(builtIns), typeSystem = IrTypeSystemContextImpl(builtIns),
friendModules = emptyMap(), friendModules = emptyMap(),
partialLinkageSupport = PartialLinkageSupportForLinker.DISABLED, partialLinkageSupport = PartialLinkageSupportForLinker.DISABLED,
) )
override val returnUnboundSymbolsIfSignatureNotFound: Boolean override val returnUnboundSymbolsIfSignatureNotFound: Boolean
@@ -313,8 +287,7 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
fun dumpIr(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?) { fun dumpIr(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?) {
val module = loadModule() val library = libraryInRepoOrCurrentDir(repository, libraryNameOrPath)
val library = module.kotlinLibrary
checkLibraryHasIr(library) checkLibraryHasIr(library)
if (signatureVersion != null && signatureVersion != KotlinIrSignatureVersion.V2) { if (signatureVersion != null && signatureVersion != KotlinIrSignatureVersion.V2) {
@@ -322,10 +295,11 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
logWarning("using a non-default signature version in \"dump-ir\" is not supported yet") logWarning("using a non-default signature version in \"dump-ir\" is not supported yet")
} }
val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion) val module = ModuleDescriptorLoader.load(library)
val idSignaturer = KonanIdSignaturer(KonanManglerDesc) val idSignaturer = KonanIdSignaturer(KonanManglerDesc)
val symbolTable = SymbolTable(idSignaturer, IrFactoryImpl) val symbolTable = SymbolTable(idSignaturer, IrFactoryImpl)
val typeTranslator = TypeTranslatorImpl(symbolTable, versionSpec, module) val typeTranslator = TypeTranslatorImpl(symbolTable, ModuleDescriptorLoader.languageVersionSettings, module)
val irBuiltIns = IrBuiltInsOverDescriptors(module.builtIns, typeTranslator, symbolTable) val irBuiltIns = IrBuiltInsOverDescriptors(module.builtIns, typeTranslator, symbolTable)
val linker = KlibToolLinker(module, irBuiltIns, symbolTable) val linker = KlibToolLinker(module, irBuiltIns, symbolTable)
@@ -391,11 +365,7 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
fun contents(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?) { fun contents(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?) {
logWarning("\"contents\" has been renamed to \"dump-metadata\". Please, use new command name.") logWarning("\"contents\" has been renamed to \"dump-metadata\". Please, use new command name.")
dumpMetadata(output, printSignatures, signatureVersion) val module = ModuleDescriptorLoader.load(libraryInRepoOrCurrentDir(repository, libraryNameOrPath))
}
fun dumpMetadata(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?) {
val module = loadModule()
val signatureRenderer = if (printSignatures) val signatureRenderer = if (printSignatures)
DefaultKlibSignatureRenderer(signatureVersion, "// Signature: ") DefaultKlibSignatureRenderer(signatureVersion, "// Signature: ")
else else
@@ -405,13 +375,23 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
printer.print(module) printer.print(module)
} }
/**
* @param testMode if `true` then a special pre-processing is performed towards the metadata before rendering:
* - empty package fragments are removed
* - package fragments with the same package FQN are merged
* - classes are sorted in alphabetical order
*/
fun dumpMetadata(output: Appendable, printSignatures: Boolean, signatureVersion: KotlinIrSignatureVersion?, testMode: Boolean) {
KotlinpBasedMetadataDumper(output, printSignatures, signatureVersion).dumpLibrary(libraryInCurrentDir(libraryNameOrPath), testMode)
}
fun signatures(output: Appendable, signatureVersion: KotlinIrSignatureVersion?) { fun signatures(output: Appendable, signatureVersion: KotlinIrSignatureVersion?) {
logWarning("\"signatures\" has been renamed to \"dump-metadata-signatures\". Please, use new command name.") logWarning("\"signatures\" has been renamed to \"dump-metadata-signatures\". Please, use new command name.")
dumpMetadataSignatures(output, signatureVersion) dumpMetadataSignatures(output, signatureVersion)
} }
fun dumpMetadataSignatures(output: Appendable, signatureVersion: KotlinIrSignatureVersion?) { fun dumpMetadataSignatures(output: Appendable, signatureVersion: KotlinIrSignatureVersion?) {
val module = loadModule() val module = ModuleDescriptorLoader.load(libraryInRepoOrCurrentDir(repository, libraryNameOrPath))
// Don't call `checkSupportedInLibrary()` - the signatures are anyway generated on the fly. // Don't call `checkSupportedInLibrary()` - the signatures are anyway generated on the fly.
val printer = SignaturePrinter(output, DefaultKlibSignatureRenderer(signatureVersion)) val printer = SignaturePrinter(output, DefaultKlibSignatureRenderer(signatureVersion))
@@ -437,37 +417,8 @@ class Library(val libraryNameOrPath: String, val requestedRepository: String?) {
logError("Signature version ${this.number} is not supported in library ${library.libraryFile}." + logError("Signature version ${this.number} is not supported in library ${library.libraryFile}." +
" Supported versions: ${supportedSignatureVersions.joinToString { it.number.toString() }}") " Supported versions: ${supportedSignatureVersions.joinToString { it.number.toString() }}")
} }
private fun loadModule(): ModuleDescriptor {
val storageManager = LockBasedStorageManager("klib")
val library = libraryInRepoOrCurrentDir(repository, libraryNameOrPath)
val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion)
val module = KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(library, versionSpec, storageManager, null)
val defaultModules = mutableListOf<ModuleDescriptorImpl>()
if (!module.isNativeStdlib()) {
val resolver = resolverByName(
emptyList(),
distributionKlib = Distribution(KotlinNativePaths.homePath.absolutePath).klib,
skipCurrentDir = true,
logger = KlibToolLogger
)
resolver.defaultLinks(false, true, true).mapTo(defaultModules) {
KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptor(it, versionSpec, storageManager, module.builtIns, null)
}
}
(defaultModules + module).let { allModules ->
allModules.forEach { it.setDependencies(allModules) }
}
return module
}
} }
val currentLanguageVersion = LanguageVersion.LATEST_STABLE
val currentApiVersion = ApiVersion.LATEST_STABLE
fun libraryInRepo(repository: KFile, name: String) = fun libraryInRepo(repository: KFile, name: String) =
resolverByName(listOf(repository.absolutePath), skipCurrentDir = true, logger = KlibToolLogger).resolve(name) resolverByName(listOf(repository.absolutePath), skipCurrentDir = true, logger = KlibToolLogger).resolve(name)
@@ -500,7 +451,7 @@ fun main(args: Array<String>) {
"dump-abi" -> library.dumpAbi(System.out, signatureVersion) "dump-abi" -> library.dumpAbi(System.out, signatureVersion)
"dump-ir" -> library.dumpIr(System.out, printSignatures, signatureVersion) "dump-ir" -> library.dumpIr(System.out, printSignatures, signatureVersion)
"dump-ir-signatures" -> library.dumpIrSignatures(System.out, signatureVersion) "dump-ir-signatures" -> library.dumpIrSignatures(System.out, signatureVersion)
"dump-metadata" -> library.dumpMetadata(System.out, printSignatures, signatureVersion) "dump-metadata" -> library.dumpMetadata(System.out, printSignatures, signatureVersion, testMode = false)
"dump-metadata-signatures" -> library.dumpMetadataSignatures(System.out, signatureVersion) "dump-metadata-signatures" -> library.dumpMetadataSignatures(System.out, signatureVersion)
"contents" -> library.contents(System.out, printSignatures, signatureVersion) "contents" -> library.contents(System.out, printSignatures, signatureVersion)
"signatures" -> library.signatures(System.out, signatureVersion) "signatures" -> library.signatures(System.out, signatureVersion)