[KLIB tool] Introduce KlibToolOutput for capturing stdout and errors/warnings
With `KlibToolOutput` it's possible to forward the output of each KLIB tool's command to either system stdout/stderr streams or to some buffers which then can be read by tests. ^KT-62340
This commit is contained in:
committed by
Space Team
parent
5b7c11ae39
commit
9878c1fa16
+1
-1
@@ -40,7 +40,7 @@ internal class DeclarationPrinter(
|
||||
|
||||
private fun Printer.printPlain(header: String, signature: String? = null, suffix: String? = null) {
|
||||
if (signature != null) println(signature)
|
||||
println(if (suffix != null ) header + suffix else header)
|
||||
println(if (suffix != null) header + suffix else header)
|
||||
}
|
||||
|
||||
private inner class PrinterVisitor : DeclarationDescriptorVisitorEmptyBodies<Unit, Unit>() {
|
||||
|
||||
+2
-3
@@ -5,15 +5,14 @@ import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.util.IdSignatureRenderer
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
|
||||
|
||||
internal class DefaultKlibSignatureRenderer(
|
||||
signatureVersion: KotlinIrSignatureVersion?,
|
||||
private val individualSignatureRenderer: IdSignatureRenderer,
|
||||
private val prefix: String? = null,
|
||||
) : KlibSignatureRenderer {
|
||||
private val idSignaturer = KonanIdSignaturer(KonanManglerDesc)
|
||||
private val individualSignatureRenderer = signatureVersion.getMostSuitableSignatureRenderer()
|
||||
|
||||
override fun render(descriptor: DeclarationDescriptor): String? {
|
||||
val idSignature = if (descriptor is ClassDescriptor && descriptor.kind == ClassKind.ENUM_ENTRY) {
|
||||
|
||||
+2
-3
@@ -6,11 +6,10 @@
|
||||
package org.jetbrains.kotlin.cli.klib
|
||||
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.IdSignatureRenderer
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
|
||||
|
||||
internal class IrSignaturesRenderer(private val output: Appendable, signatureVersion: KotlinIrSignatureVersion?) {
|
||||
private val individualSignatureRenderer = signatureVersion.getMostSuitableSignatureRenderer()
|
||||
internal class IrSignaturesRenderer(private val output: Appendable, private val individualSignatureRenderer: IdSignatureRenderer) {
|
||||
|
||||
fun render(signatures: IrSignaturesExtractor.Signatures) {
|
||||
header("Declared signatures: ${signatures.declaredSignatures.size}")
|
||||
|
||||
+22
-17
@@ -6,34 +6,37 @@
|
||||
package org.jetbrains.kotlin.cli.klib
|
||||
|
||||
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
internal class KlibToolArgumentsParser {
|
||||
fun parseArguments(rawArgs: Array<String>): KlibToolArguments {
|
||||
internal class KlibToolArgumentsParser(private val output: KlibToolOutput) {
|
||||
fun parseArguments(rawArgs: Array<String>): KlibToolArguments? {
|
||||
if (rawArgs.size < 2) {
|
||||
printUsage()
|
||||
exitProcess(0)
|
||||
return null
|
||||
}
|
||||
|
||||
val extraArgs: Map<ExtraOption, List<String>> = parseOptions(rawArgs.drop(2).toTypedArray<String>())
|
||||
.entries
|
||||
.mapNotNull { (option, values) ->
|
||||
?.entries
|
||||
?.mapNotNull { (option, values) ->
|
||||
val knownOption = ExtraOption.parseOrNull(option)
|
||||
if (knownOption == null) {
|
||||
logWarning("Unrecognized command-line argument: $option")
|
||||
output.logWarning("Unrecognized command-line argument: $option")
|
||||
return@mapNotNull null
|
||||
}
|
||||
knownOption to values
|
||||
}.toMap()
|
||||
}?.toMap()
|
||||
?: return null
|
||||
|
||||
val signatureVersion = extraArgs[ExtraOption.SIGNATURE_VERSION]?.last()?.let { rawSignatureVersion ->
|
||||
rawSignatureVersion.toIntOrNull()?.let(::KotlinIrSignatureVersion)
|
||||
?: logError("Invalid signature version: $rawSignatureVersion")
|
||||
rawSignatureVersion.toIntOrNull()?.let(::KotlinIrSignatureVersion) ?: run {
|
||||
output.logError("Invalid signature version: $rawSignatureVersion")
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
if (signatureVersion != null && signatureVersion !in KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS)
|
||||
logError("Unsupported signature version: ${signatureVersion.number}")
|
||||
|
||||
if (signatureVersion != null && signatureVersion !in KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS) {
|
||||
output.logError("Unsupported signature version: ${signatureVersion.number}")
|
||||
return null
|
||||
}
|
||||
|
||||
return KlibToolArguments(
|
||||
commandName = rawArgs[0],
|
||||
@@ -45,15 +48,17 @@ internal class KlibToolArgumentsParser {
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseOptions(args: Array<String>): Map<String, List<String>> {
|
||||
private fun parseOptions(args: Array<String>): Map<String, List<String>>? {
|
||||
val options = mutableMapOf<String, MutableList<String>>()
|
||||
for (index in args.indices step 2) {
|
||||
val key = args[index]
|
||||
if (key[0] != '-') {
|
||||
logError("Expected a flag with initial dash: $key")
|
||||
output.logError("Expected a flag with initial dash: $key")
|
||||
return null
|
||||
}
|
||||
if (index + 1 == args.size) {
|
||||
logError("Expected an value after $key")
|
||||
output.logError("Expected an value after $key")
|
||||
return null
|
||||
}
|
||||
val value = listOf(args[index + 1])
|
||||
options[key]?.addAll(value) ?: options.put(key, value.toMutableList())
|
||||
@@ -62,7 +67,7 @@ internal class KlibToolArgumentsParser {
|
||||
}
|
||||
|
||||
private fun printUsage() {
|
||||
println(
|
||||
output.stderr.appendLine(
|
||||
"""
|
||||
Usage: klib <command> <library> [<option>]
|
||||
|
||||
|
||||
+4
-2
@@ -18,12 +18,14 @@ import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||
|
||||
internal class KlibToolIrLinker(
|
||||
output: KlibToolOutput,
|
||||
module: ModuleDescriptor,
|
||||
irBuiltIns: IrBuiltIns,
|
||||
symbolTable: SymbolTable
|
||||
) : KotlinIrLinker(module, KlibToolLogger, irBuiltIns, symbolTable, exportedDependencies = emptyList()) {
|
||||
) : KotlinIrLinker(module, KlibToolLogger(output), irBuiltIns, symbolTable, exportedDependencies = emptyList()) {
|
||||
override val fakeOverrideBuilder = IrLinkerFakeOverrideProvider(
|
||||
linker = this,
|
||||
symbolTable = symbolTable,
|
||||
@@ -35,7 +37,7 @@ internal class KlibToolIrLinker(
|
||||
|
||||
override val returnUnboundSymbolsIfSignatureNotFound get() = true
|
||||
|
||||
override val translationPluginContext get() = TODO("Not needed for ir dumping")
|
||||
override val translationPluginContext get() = shouldNotBeCalled()
|
||||
|
||||
override fun createModuleDeserializer(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
|
||||
+13
-19
@@ -7,15 +7,22 @@ package org.jetbrains.kotlin.cli.klib
|
||||
|
||||
import org.jetbrains.kotlin.ir.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
internal object KlibToolLogger : Logger, IrMessageLogger {
|
||||
override fun log(message: String) = println(message)
|
||||
override fun warning(message: String) = logWarning(message)
|
||||
override fun error(message: String) = logWarning(message)
|
||||
internal class KlibToolLogger(private val output: KlibToolOutput) : Logger, IrMessageLogger {
|
||||
override fun log(message: String) {
|
||||
output.logInfo(message)
|
||||
}
|
||||
|
||||
override fun warning(message: String) {
|
||||
output.logWarning(message)
|
||||
}
|
||||
|
||||
override fun error(message: String) {
|
||||
output.logError(message)
|
||||
}
|
||||
|
||||
@Deprecated(Logger.FATAL_DEPRECATION_MESSAGE, ReplaceWith(Logger.FATAL_REPLACEMENT))
|
||||
override fun fatal(message: String) = logError(message, withStacktrace = true)
|
||||
override fun fatal(message: String) = throw IllegalStateException("error: $message")
|
||||
|
||||
override fun report(severity: IrMessageLogger.Severity, message: String, location: IrMessageLogger.Location?) {
|
||||
when (severity) {
|
||||
@@ -25,16 +32,3 @@ internal object KlibToolLogger : Logger, IrMessageLogger {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun logWarning(text: String) {
|
||||
println("warning: $text")
|
||||
}
|
||||
|
||||
internal fun logError(text: String, withStacktrace: Boolean = false): Nothing {
|
||||
if (withStacktrace)
|
||||
error("error: $text")
|
||||
else {
|
||||
System.err.println("error: $text")
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* TODO: Consider using [org.jetbrains.kotlin.cli.common.messages.MessageCollector] instead of this class.
|
||||
* Note: The [org.jetbrains.kotlin.cli.common.messages.MessageCollector] is designed to track an individual short messages
|
||||
* logged at different levels, but is not supposed to collect plain output (such as, for example, IR dump).
|
||||
*/
|
||||
internal class KlibToolOutput(
|
||||
stdout: Appendable,
|
||||
val stderr: Appendable
|
||||
) : Appendable by stdout {
|
||||
var hasErrors: Boolean = false
|
||||
private set
|
||||
|
||||
internal fun logInfo(text: String) {
|
||||
stderr.append("info: ").appendLine(text)
|
||||
}
|
||||
|
||||
internal fun logWarning(text: String) {
|
||||
stderr.append("warning: ").appendLine(text)
|
||||
}
|
||||
|
||||
internal fun logError(text: String) {
|
||||
hasErrors = true
|
||||
stderr.append("error: ").appendLine(text)
|
||||
}
|
||||
|
||||
internal fun logErrorWithStackTrace(t: Throwable) {
|
||||
hasErrors = true
|
||||
stderr.appendLine(t.stackTraceToString())
|
||||
}
|
||||
}
|
||||
+3
-8
@@ -22,21 +22,16 @@ 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?
|
||||
private val output: KlibToolOutput,
|
||||
private val signatureRenderer: IdSignatureRenderer?, // `null` means no signatures should be rendered.
|
||||
) {
|
||||
// `null` means no signatures should be rendered.
|
||||
private val signatureRenderer = runIf(printSignatures) { signatureVersion.getMostSuitableSignatureRenderer() }
|
||||
|
||||
private val printer = Printer(output)
|
||||
|
||||
@@ -102,7 +97,7 @@ internal class KotlinpBasedMetadataDumper(
|
||||
private fun prepareSignatureComputer(library: KotlinLibrary, moduleMetadata: KlibModuleMetadata): ExternalSignatureComputer? {
|
||||
val signatureCollector = SignaturesCollector(signatureRenderer ?: return null)
|
||||
|
||||
val moduleDescriptor = ModuleDescriptorLoader.load(library)
|
||||
val moduleDescriptor = ModuleDescriptorLoader(output).load(library)
|
||||
moduleDescriptor.accept(signatureCollector, Unit)
|
||||
|
||||
return ExternalSignatureComputer(moduleMetadata, signatureCollector.signatures::get)
|
||||
|
||||
+8
-4
@@ -19,7 +19,9 @@ import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.utils.KotlinNativePaths
|
||||
|
||||
internal object ModuleDescriptorLoader {
|
||||
internal class ModuleDescriptorLoader(output: KlibToolOutput) {
|
||||
private val logger = KlibToolLogger(output)
|
||||
|
||||
fun load(library: KotlinLibrary): ModuleDescriptorImpl {
|
||||
val storageManager = LockBasedStorageManager("klib")
|
||||
|
||||
@@ -31,7 +33,7 @@ internal object ModuleDescriptorLoader {
|
||||
emptyList(),
|
||||
distributionKlib = Distribution(KotlinNativePaths.homePath.absolutePath).klib,
|
||||
skipCurrentDir = true,
|
||||
logger = KlibToolLogger
|
||||
logger = logger
|
||||
)
|
||||
resolver.defaultLinks(noStdLib = false, noDefaultLibs = true, noEndorsedLibs = true).mapTo(defaultModules) {
|
||||
KlibFactories.DefaultDeserializedDescriptorFactory.createDescriptor(it, languageVersionSettings, storageManager, module.builtIns, null)
|
||||
@@ -45,7 +47,9 @@ internal object ModuleDescriptorLoader {
|
||||
return module
|
||||
}
|
||||
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
|
||||
companion object {
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE)
|
||||
|
||||
private val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
|
||||
private val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions
|
||||
import org.jetbrains.kotlin.ir.util.IdSignatureRenderer
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
@@ -27,25 +28,27 @@ import org.jetbrains.kotlin.library.unpackZippedKonanLibraryTo
|
||||
import org.jetbrains.kotlin.psi2ir.descriptors.IrBuiltInsOverDescriptors
|
||||
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
|
||||
import org.jetbrains.kotlin.util.removeSuffixIfPresent
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import java.io.File
|
||||
import kotlin.system.exitProcess
|
||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
||||
|
||||
private val defaultRepository = KFile(DependencyDirectories.localKonanDir.resolve("klib").absolutePath)
|
||||
|
||||
private class KlibRepoDeprecationWarning {
|
||||
private class KlibRepoDeprecationWarning(private val output: KlibToolOutput) {
|
||||
private var alreadyLogged = false
|
||||
|
||||
fun logOnceIfNecessary() {
|
||||
if (!alreadyLogged) {
|
||||
alreadyLogged = true
|
||||
logWarning("Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098")
|
||||
output.logWarning("Local KLIB repositories to be dropped soon. See https://youtrack.jetbrains.com/issue/KT-61098")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
internal class KlibToolCommand(private val output: KlibToolOutput, private val args: KlibToolArguments) {
|
||||
|
||||
private val klibRepoDeprecationWarning = KlibRepoDeprecationWarning()
|
||||
private val klibRepoDeprecationWarning = KlibRepoDeprecationWarning(output)
|
||||
|
||||
private val repository = args.repository?.let {
|
||||
klibRepoDeprecationWarning.logOnceIfNecessary() // Due to use of "-repository" option.
|
||||
@@ -60,17 +63,16 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
val headerMetadataVersion = library.versions.metadataVersion
|
||||
val moduleName = parseModuleHeader(library.moduleHeaderData).moduleName
|
||||
|
||||
println("")
|
||||
println("Resolved to: ${KFile(library.libraryName).absolutePath}")
|
||||
println("Module name: $moduleName")
|
||||
println("ABI version: $headerAbiVersion")
|
||||
println("Compiler version: $headerCompilerVersion")
|
||||
println("Library version: $headerLibraryVersion")
|
||||
println("Metadata version: $headerMetadataVersion")
|
||||
output.appendLine()
|
||||
output.appendLine("Resolved to: ${KFile(library.libraryName).absolutePath}")
|
||||
output.appendLine("Module name: $moduleName")
|
||||
output.appendLine("ABI version: $headerAbiVersion")
|
||||
output.appendLine("Compiler version: $headerCompilerVersion")
|
||||
output.appendLine("Library version: $headerLibraryVersion")
|
||||
output.appendLine("Metadata version: $headerMetadataVersion")
|
||||
|
||||
if (library is KonanLibrary) {
|
||||
val targets = library.targetList.joinToString(", ")
|
||||
print("Available targets: $targets\n")
|
||||
output.appendLine("Available targets: ${library.targetList.joinToString()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +80,7 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
klibRepoDeprecationWarning.logOnceIfNecessary()
|
||||
|
||||
if (!repository.exists) {
|
||||
logWarning("Repository does not exist: $repository. Creating...")
|
||||
output.logWarning("Repository does not exist: $repository. Creating...")
|
||||
repository.mkdirs()
|
||||
}
|
||||
|
||||
@@ -95,36 +97,35 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
fun remove() {
|
||||
klibRepoDeprecationWarning.logOnceIfNecessary()
|
||||
|
||||
if (!repository.exists) logError("Repository does not exist: $repository")
|
||||
|
||||
val library = try {
|
||||
libraryInRepo(repository, args.libraryNameOrPath)
|
||||
} catch (e: Throwable) {
|
||||
println(e.message)
|
||||
null
|
||||
|
||||
if (!repository.exists) {
|
||||
output.logError("Repository does not exist: $repository")
|
||||
return
|
||||
}
|
||||
|
||||
runCatching {
|
||||
libraryInRepo(repository, args.libraryNameOrPath).libraryFile.deleteRecursively()
|
||||
}
|
||||
library?.libraryFile?.deleteRecursively()
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun dumpIr(output: Appendable) {
|
||||
fun dumpIr() {
|
||||
val library = libraryInRepoOrCurrentDir(repository, args.libraryNameOrPath)
|
||||
checkLibraryHasIr(library)
|
||||
|
||||
if (!checkLibraryHasIr(library)) return
|
||||
|
||||
if (args.signatureVersion != null && args.signatureVersion != KotlinIrSignatureVersion.V2) {
|
||||
// TODO: support passing any signature version through `DumpIrTreeOptions`, KT-62828
|
||||
logWarning("using a non-default signature version in \"dump-ir\" is not supported yet")
|
||||
output.logWarning("using a non-default signature version in \"dump-ir\" is not supported yet")
|
||||
}
|
||||
|
||||
val module = ModuleDescriptorLoader.load(library)
|
||||
val module = ModuleDescriptorLoader(output).load(library)
|
||||
|
||||
val idSignaturer = KonanIdSignaturer(KonanManglerDesc)
|
||||
val symbolTable = SymbolTable(idSignaturer, IrFactoryImpl)
|
||||
val typeTranslator = TypeTranslatorImpl(symbolTable, ModuleDescriptorLoader.languageVersionSettings, module)
|
||||
val irBuiltIns = IrBuiltInsOverDescriptors(module.builtIns, typeTranslator, symbolTable)
|
||||
|
||||
val linker = KlibToolIrLinker(module, irBuiltIns, symbolTable)
|
||||
val linker = KlibToolIrLinker(output, module, irBuiltIns, symbolTable)
|
||||
module.allDependencyModules.forEach {
|
||||
linker.deserializeOnlyHeaderModule(it, it.kotlinLibrary)
|
||||
linker.resolveModuleDeserializer(it, null).init()
|
||||
@@ -137,19 +138,22 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLibraryAbiReader::class)
|
||||
fun dumpAbi(output: Appendable) {
|
||||
fun dumpAbi() {
|
||||
val library = libraryInCurrentDir(args.libraryNameOrPath)
|
||||
checkLibraryHasIr(library)
|
||||
|
||||
if (!checkLibraryHasIr(library)) return
|
||||
|
||||
val abiSignatureVersion = args.signatureVersion?.let { signatureVersion ->
|
||||
signatureVersion.checkSupportedInLibrary(library)
|
||||
if (!signatureVersion.checkSupportedInLibrary(library)) return
|
||||
|
||||
val abiSignatureVersion = AbiSignatureVersion.resolveByVersionNumber(signatureVersion.number)
|
||||
if (!abiSignatureVersion.isSupportedByAbiReader)
|
||||
logError(
|
||||
if (!abiSignatureVersion.isSupportedByAbiReader) {
|
||||
output.logError(
|
||||
"Signature version ${signatureVersion.number} is not supported by the KLIB ABI reader." +
|
||||
" Supported versions: ${AbiSignatureVersion.allSupportedByAbiReader.joinToString { it.versionNumber.toString() }}"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
abiSignatureVersion
|
||||
} ?: run {
|
||||
@@ -161,13 +165,15 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
.sortedDescending()
|
||||
.firstNotNullOfOrNull { versionsSupportedByAbiReader[it] }
|
||||
|
||||
if (abiSignatureVersion == null)
|
||||
logError(
|
||||
if (abiSignatureVersion == null) {
|
||||
output.logError(
|
||||
"There is no signature version that would be both supported in library ${library.libraryFile}" +
|
||||
" and by the KLIB ABI reader. Supported versions in the library:" +
|
||||
" ${library.versions.irSignatureVersions.joinToString { it.number.toString() }}" +
|
||||
". Supported versions by the KLIB ABI reader: ${AbiSignatureVersion.allSupportedByAbiReader.joinToString { it.versionNumber.toString() }}"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
abiSignatureVersion
|
||||
}
|
||||
@@ -186,79 +192,119 @@ internal class KlibToolCommand(private val args: KlibToolArguments) {
|
||||
}
|
||||
|
||||
// TODO: This command is deprecated. Drop it after 2.0. KT-65380
|
||||
fun contents(output: Appendable) {
|
||||
logWarning("\"contents\" has been renamed to \"dump-metadata\". Please, use new command name.")
|
||||
val module = ModuleDescriptorLoader.load(libraryInRepoOrCurrentDir(repository, args.libraryNameOrPath))
|
||||
val signatureRenderer = if (args.printSignatures)
|
||||
DefaultKlibSignatureRenderer(args.signatureVersion, "// Signature: ")
|
||||
fun contents() {
|
||||
output.logWarning("\"contents\" has been renamed to \"dump-metadata\". Please, use new command name.")
|
||||
|
||||
val idSignatureRenderer = args.signatureVersion.getMostSuitableSignatureRenderer() ?: return
|
||||
|
||||
val module = ModuleDescriptorLoader(output).load(libraryInRepoOrCurrentDir(repository, args.libraryNameOrPath))
|
||||
val klibSignatureRenderer = if (args.printSignatures)
|
||||
DefaultKlibSignatureRenderer(idSignatureRenderer, "// Signature: ")
|
||||
else
|
||||
KlibSignatureRenderer.NO_SIGNATURE
|
||||
val printer = DeclarationPrinter(output, signatureRenderer)
|
||||
val printer = DeclarationPrinter(output, klibSignatureRenderer)
|
||||
|
||||
printer.print(module)
|
||||
}
|
||||
|
||||
fun dumpMetadata(output: Appendable) {
|
||||
KotlinpBasedMetadataDumper(output, args.printSignatures, args.signatureVersion).dumpLibrary(libraryInCurrentDir(args.libraryNameOrPath), args.testMode)
|
||||
fun dumpMetadata() {
|
||||
val idSignatureRenderer: IdSignatureRenderer? = runIf(args.printSignatures) {
|
||||
args.signatureVersion.getMostSuitableSignatureRenderer() ?: return
|
||||
}
|
||||
KotlinpBasedMetadataDumper(output, idSignatureRenderer).dumpLibrary(libraryInCurrentDir(args.libraryNameOrPath), args.testMode)
|
||||
}
|
||||
|
||||
fun signatures(output: Appendable) {
|
||||
logWarning("\"signatures\" has been renamed to \"dump-metadata-signatures\". Please, use new command name.")
|
||||
dumpMetadataSignatures(output)
|
||||
fun signatures() {
|
||||
output.logWarning("\"signatures\" has been renamed to \"dump-metadata-signatures\". Please, use new command name.")
|
||||
dumpMetadataSignatures()
|
||||
}
|
||||
|
||||
fun dumpMetadataSignatures(output: Appendable) {
|
||||
val module = ModuleDescriptorLoader.load(libraryInRepoOrCurrentDir(repository, args.libraryNameOrPath))
|
||||
fun dumpMetadataSignatures() {
|
||||
// Don't call `checkSupportedInLibrary()` - the signatures are anyway generated on the fly.
|
||||
val printer = SignaturePrinter(output, DefaultKlibSignatureRenderer(args.signatureVersion))
|
||||
|
||||
val idSignatureRenderer = args.signatureVersion.getMostSuitableSignatureRenderer() ?: return
|
||||
|
||||
val module = ModuleDescriptorLoader(output).load(libraryInRepoOrCurrentDir(repository, args.libraryNameOrPath))
|
||||
val printer = SignaturePrinter(output, DefaultKlibSignatureRenderer(idSignatureRenderer))
|
||||
|
||||
printer.print(module)
|
||||
}
|
||||
|
||||
fun dumpIrSignatures(output: Appendable) {
|
||||
fun dumpIrSignatures() {
|
||||
val library = libraryInCurrentDir(args.libraryNameOrPath)
|
||||
checkLibraryHasIr(library)
|
||||
args.signatureVersion?.checkSupportedInLibrary(library)
|
||||
|
||||
if (!checkLibraryHasIr(library) || !args.signatureVersion.checkSupportedInLibrary(library)) return
|
||||
|
||||
val idSignatureRenderer = args.signatureVersion.getMostSuitableSignatureRenderer() ?: return
|
||||
|
||||
val signatures = IrSignaturesExtractor(library).extract()
|
||||
IrSignaturesRenderer(output, args.signatureVersion).render(signatures)
|
||||
IrSignaturesRenderer(output, idSignatureRenderer).render(signatures)
|
||||
}
|
||||
|
||||
private fun checkLibraryHasIr(library: KotlinLibrary) {
|
||||
if (!library.hasIr) logError("Library ${library.libraryFile} is an IR-less library")
|
||||
private fun checkLibraryHasIr(library: KotlinLibrary): Boolean {
|
||||
if (!library.hasIr) {
|
||||
output.logError("Library ${library.libraryFile} is an IR-less library")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun KotlinIrSignatureVersion.checkSupportedInLibrary(library: KotlinLibrary) {
|
||||
val supportedSignatureVersions = library.versions.irSignatureVersions
|
||||
if (this !in supportedSignatureVersions)
|
||||
logError("Signature version ${this.number} is not supported in library ${library.libraryFile}." +
|
||||
" Supported versions: ${supportedSignatureVersions.joinToString { it.number.toString() }}")
|
||||
private fun KotlinIrSignatureVersion?.checkSupportedInLibrary(library: KotlinLibrary): Boolean {
|
||||
if (this != null) {
|
||||
val supportedSignatureVersions = library.versions.irSignatureVersions
|
||||
if (this !in supportedSignatureVersions) {
|
||||
output.logError("Signature version ${this.number} is not supported in library ${library.libraryFile}." +
|
||||
" Supported versions: ${supportedSignatureVersions.joinToString { it.number.toString() }}")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun KotlinIrSignatureVersion?.getMostSuitableSignatureRenderer(): IdSignatureRenderer? = when (this) {
|
||||
KotlinIrSignatureVersion.V1 -> IdSignatureRenderer.LEGACY
|
||||
null, KotlinIrSignatureVersion.V2 -> IdSignatureRenderer.DEFAULT
|
||||
else -> {
|
||||
output.logError("Unsupported signature version: $number")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun libraryInRepo(repository: KFile, name: String) =
|
||||
resolverByName(listOf(repository.absolutePath), skipCurrentDir = true, logger = KlibToolLogger(output)).resolve(name)
|
||||
|
||||
private fun libraryInCurrentDir(name: String) = resolverByName(emptyList(), logger = KlibToolLogger(output)).resolve(name)
|
||||
|
||||
private fun libraryInRepoOrCurrentDir(repository: KFile, name: String) =
|
||||
resolverByName(listOf(repository.absolutePath), logger = KlibToolLogger(output)).resolve(name)
|
||||
}
|
||||
|
||||
private fun libraryInRepo(repository: KFile, name: String) =
|
||||
resolverByName(listOf(repository.absolutePath), skipCurrentDir = true, logger = KlibToolLogger).resolve(name)
|
||||
|
||||
private fun libraryInCurrentDir(name: String) = resolverByName(emptyList(), logger = KlibToolLogger).resolve(name)
|
||||
|
||||
private fun libraryInRepoOrCurrentDir(repository: KFile, name: String) =
|
||||
resolverByName(listOf(repository.absolutePath), logger = KlibToolLogger).resolve(name)
|
||||
|
||||
fun main(rawArgs: Array<String>) {
|
||||
val args = KlibToolArgumentsParser().parseArguments(rawArgs)
|
||||
val command = KlibToolCommand(args)
|
||||
val output = KlibToolOutput(stdout = System.out, stderr = System.err)
|
||||
|
||||
when (args.commandName) {
|
||||
"dump-abi" -> command.dumpAbi(System.out)
|
||||
"dump-ir" -> command.dumpIr(System.out)
|
||||
"dump-ir-signatures" -> command.dumpIrSignatures(System.out)
|
||||
"dump-metadata" -> command.dumpMetadata(System.out)
|
||||
"dump-metadata-signatures" -> command.dumpMetadataSignatures(System.out)
|
||||
"contents" -> command.contents(System.out)
|
||||
"signatures" -> command.signatures(System.out)
|
||||
"info" -> command.info()
|
||||
"install" -> command.install()
|
||||
"remove" -> command.remove()
|
||||
else -> logError("Unknown command: ${args.commandName}")
|
||||
val args = KlibToolArgumentsParser(output).parseArguments(rawArgs)
|
||||
if (args != null) {
|
||||
val command = KlibToolCommand(output, args)
|
||||
|
||||
try {
|
||||
when (args.commandName) {
|
||||
"dump-abi" -> command.dumpAbi()
|
||||
"dump-ir" -> command.dumpIr()
|
||||
"dump-ir-signatures" -> command.dumpIrSignatures()
|
||||
"dump-metadata" -> command.dumpMetadata()
|
||||
"dump-metadata-signatures" -> command.dumpMetadataSignatures()
|
||||
"contents" -> command.contents()
|
||||
"signatures" -> command.signatures()
|
||||
"info" -> command.info()
|
||||
"install" -> command.install()
|
||||
"remove" -> command.remove()
|
||||
else -> output.logError("Unknown command: ${args.commandName}")
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
output.logErrorWithStackTrace(t)
|
||||
}
|
||||
}
|
||||
|
||||
if (output.hasErrors)
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.ir.util.IdSignatureRenderer
|
||||
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
|
||||
|
||||
internal fun KotlinIrSignatureVersion?.getMostSuitableSignatureRenderer() = when (this) {
|
||||
KotlinIrSignatureVersion.V1 -> IdSignatureRenderer.LEGACY
|
||||
null, KotlinIrSignatureVersion.V2 -> IdSignatureRenderer.DEFAULT
|
||||
else -> error("Unsupported signature version: $number")
|
||||
}
|
||||
Reference in New Issue
Block a user