diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 08496bfb211..5035a80637d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -418,7 +418,7 @@ class IrModuleToJsTransformer( } private fun Set.computeTag(declaration: IrDeclaration): String? { - val tag = (backendContext.irFactory as IdSignatureRetriever).declarationSignature(declaration)?.toString() + val tag = (backendContext.irFactory as IdSignatureRetriever).declarationSignature(declaration)?.render() if (tag == null && !contains(declaration)) { error("signature for ${declaration.render()} not found") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt index 538b8245851..e46d6ea263a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignature.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.symbols.IrFileSymbol import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.ir.util.render as newRender /** * [IdSignature] is a unique key that corresponds to each Kotlin Declaration. It is used to reference declarations in klib. @@ -248,7 +249,13 @@ sealed class IdSignature { open fun asPublic(): CommonSignature? = null - abstract fun render(): String + @Deprecated( + "Rendering of signatures has been extracted to IdSignatureRenderer.render()", + replaceWith = ReplaceWith("render()", "org.jetbrains.kotlin.ir.util.render"), + level = DeprecationLevel.HIDDEN + ) + fun render(): String = newRender() + final override fun toString() = newRender() fun Flags.test(): Boolean = decode(flags()) @@ -261,13 +268,10 @@ sealed class IdSignature { // TODO: this API is a bit hacky, consider to act somehow else open val visibleCrossFile: Boolean get() = true - override fun toString(): String = - "${if (isLocal) "local " else ""}${render()}" - /** * This signature corresponds to a publicly accessible Kotlin declaration. * - * @property description This property does not affect linkage and is used only for showing humnan-readable error messages. + * @property description This property does not affect linkage and is used only for showing human-readable error messages. * Note: currently, we store here the mangled name from which [id] was computed. Later we can reconsider. */ class CommonSignature( @@ -319,8 +323,6 @@ sealed class IdSignature { override fun flags(): Long = mask - override fun render(): String = "$packageFqName/$declarationFqName|$id[${mask.toString(2)}]" - override fun asPublic(): CommonSignature = this override fun equals(other: Any?): Boolean = @@ -359,16 +361,6 @@ sealed class IdSignature { return if (container is FileSignature) inner.packageFqName() else container.packageFqName() } - override fun render(): String { - return buildString { - append("[ ") - append(container) - append(" <- ") - append(inner) - append(" ]") - } - } - override fun equals(other: Any?): Boolean = other is CompositeSignature && container == other.container && inner == other.inner override fun hashCode(): Int = container.hashCode() * 31 + inner.hashCode() @@ -393,8 +385,6 @@ sealed class IdSignature { override fun packageFqName(): FqName = propertySignature.packageFqName() - override fun render(): String = accessorSignature.render() - override fun flags(): Long = accessorSignature.mask override fun asPublic(): CommonSignature = accessorSignature @@ -448,10 +438,6 @@ sealed class IdSignature { override fun packageFqName(): FqName = fqName - override fun render(): String { - return "File '$fileName'" - } - override val hasTopLevel: Boolean get() = false } @@ -468,34 +454,18 @@ sealed class IdSignature { override val isLocal: Boolean get() = true - fun index(): Int = hashSig?.toInt() ?: error("Expected index in ${render()}") + fun index(): Int = hashSig?.toInt() ?: error("Expected index in $this") override fun topLevelSignature(): IdSignature { - error("Illegal access: Local Sig does not have toplevel (${render()}") + error("Illegal access: Local Sig does not have toplevel ($this") } override fun nearestPublicSig(): IdSignature { - error("Illegal access: Local Sig does not have information about its public part (${render()}") + error("Illegal access: Local Sig does not have information about its public part ($this") } override fun packageFqName(): FqName { - error("Illegal access: Local signature does not have package (${render()}") - } - - override fun render(): String { - return buildString { - append("Local[") - append(localFqn) - hashSig?.let { - append(",") - append(it) - } - description?.let { - append(" | ") - append(it) - } - append("]") - } + error("Illegal access: Local signature does not have package ($this") } override fun equals(other: Any?): Boolean { @@ -548,9 +518,6 @@ sealed class IdSignature { override fun packageFqName(): FqName = memberSignature.packageFqName() - override fun render(): String = - memberSignature.render() - override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -597,8 +564,6 @@ sealed class IdSignature { override fun nearestPublicSig(): IdSignature = container.nearestPublicSig() - override fun render(): String = "${container.render()}:$id" - override fun equals(other: Any?): Boolean = other is FileLocalSignature && id == other.id && container == other.container @@ -612,9 +577,7 @@ sealed class IdSignature { * * This signature is not navigatable through files. */ - class ScopeLocalDeclaration(val id: Int, _description: String? = null) : IdSignature() { - - val description: String = _description ?: "" + class ScopeLocalDeclaration(val id: Int, val description: String? = null) : IdSignature() { override val isPubliclyVisible: Boolean get() = false @@ -629,8 +592,6 @@ sealed class IdSignature { override fun packageFqName(): FqName = error("Is not supported for Local ID") - override fun render(): String = "#$id" - override fun equals(other: Any?): Boolean = other is ScopeLocalDeclaration && id == other.id @@ -654,8 +615,6 @@ sealed class IdSignature { override fun packageFqName(): FqName = original.packageFqName() - override fun render(): String = "ic#$stage:${original.render()}-$index" - override fun equals(other: Any?): Boolean { return other is LoweredDeclarationSignature && original == other.original && stage == other.stage && index == other.index } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignatureRenderer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignatureRenderer.kt new file mode 100644 index 00000000000..4a3978b27aa --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IdSignatureRenderer.kt @@ -0,0 +1,75 @@ +/* + * 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.ir.util + +fun IdSignature.render(renderer: IdSignatureRenderer = IdSignatureRenderer.DEFAULT): String = renderer.render(this) + +class IdSignatureRenderer private constructor(private val showDescriptionForPublicSignatures: Boolean) { + fun render(signature: IdSignature): String = buildString { render(signature) } + + private fun StringBuilder.render(signature: IdSignature): StringBuilder = when (signature) { + is IdSignature.CommonSignature -> render(signature) + is IdSignature.AccessorSignature -> render(signature) + is IdSignature.CompositeSignature -> render(signature) + is IdSignature.FileSignature -> render(signature) + is IdSignature.LocalSignature -> render(signature) + is IdSignature.FileLocalSignature -> render(signature) + is IdSignature.ScopeLocalDeclaration -> render(signature) + is IdSignature.SpecialFakeOverrideSignature -> render(signature) + is IdSignature.LoweredDeclarationSignature -> render(signature) + } + + private fun StringBuilder.render(signature: IdSignature.CommonSignature): StringBuilder = with(signature) { + append(packageFqName).append('/').append(declarationFqName).append('|') + append(if (showDescriptionForPublicSignatures) signature.description ?: id else id) + append('[').append(mask.toString(2)).append(']') + } + + private fun StringBuilder.render(signature: IdSignature.AccessorSignature): StringBuilder = + render(signature.accessorSignature) + + private fun StringBuilder.render(signature: IdSignature.CompositeSignature): StringBuilder = + append("[ ").render(signature.container).append(" <- ").render(signature.inner).append(" ]") + + private fun StringBuilder.render(signature: IdSignature.FileSignature): StringBuilder = + append("File '").append(signature.fileName).append('\'') + + private fun StringBuilder.render(signature: IdSignature.LocalSignature): StringBuilder = with(signature) { + append("Local[").append(localFqn) + hashSig?.let { append(",").append(hashSig) } + renderDescriptionForLocalSignature(description) // Always include description for local signatures if there is any. + append(']') + } + + private fun StringBuilder.render(signature: IdSignature.FileLocalSignature): StringBuilder = with(signature) { + render(container).append(':').append(id) + renderDescriptionForLocalSignature(description) // Always include description for local signatures if there is any. + } + + private fun StringBuilder.render(signature: IdSignature.ScopeLocalDeclaration): StringBuilder = with(signature) { + append('#').append(id) + renderDescriptionForLocalSignature(description) // Always include description for local signatures if there is any. + } + + private fun StringBuilder.render(signature: IdSignature.SpecialFakeOverrideSignature): StringBuilder = + render(signature.memberSignature) + + private fun StringBuilder.render(signature: IdSignature.LoweredDeclarationSignature): StringBuilder = with(signature) { + append("ic#").append(stage).append(':') + render(original) + append('-').append(index) + } + + private fun StringBuilder.renderDescriptionForLocalSignature(description: String?): StringBuilder { + description?.let { append('|').append(description) } + return this + } + + companion object { + val DEFAULT = IdSignatureRenderer(showDescriptionForPublicSignatures = true) + val LEGACY = IdSignatureRenderer(showDescriptionForPublicSignatures = false) + } +} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/IrDeserializationExceptions.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/IrDeserializationExceptions.kt index e360970800c..8fa9f9a555d 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/IrDeserializationExceptions.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/IrDeserializationExceptions.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.common.linkage.issues import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.render sealed class IrDeserializationException(message: String) : Exception(message) { override val message: String get() = super.message!! diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/KotlinIrLinkerIssues.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/KotlinIrLinkerIssues.kt index 1d9b33b0cf4..78441897444 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/KotlinIrLinkerIssues.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/issues/KotlinIrLinkerIssues.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.linkage.issues.PotentialConflictReaso import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IrMessageLogger +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.ResolvedDependency import org.jetbrains.kotlin.utils.ResolvedDependencyId diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageErrorMessages.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageErrorMessages.kt index 9cf440a7577..9e74acae38a 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageErrorMessages.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/linkage/partial/PartialLinkageErrorMessages.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.util.IdSignature.* import org.jetbrains.kotlin.ir.util.isAnonymousObject import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentClassOrNull +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageUtils.Module as PLModule diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt index 8e2f5b3654f..c985b695fe8 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt @@ -1436,7 +1436,7 @@ open class IrFileSerializer( // TODO: keep order similar val sigIndex = protoIdSignatureMap[idSig] ?: if (it is IrErrorDeclaration) protoIdSignature(idSig) else error("Not found ID for $idSig (${it.render()})") - topLevelDeclarations.add(SerializedDeclaration(sigIndex, idSig.toString(), byteArray)) + topLevelDeclarations.add(SerializedDeclaration(sigIndex, idSig.render(), byteArray)) proto.addDeclarationId(sigIndex) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrMangledNameAndSignatureDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrMangledNameAndSignatureDumpHandler.kt index 261da7bc3a4..3c8399c1edb 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrMangledNameAndSignatureDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrMangledNameAndSignatureDumpHandler.kt @@ -213,14 +213,17 @@ class IrMangledNameAndSignatureDumpHandler(testServices: TestServices) : Abstrac ) } + // N.B. We do use IdSignatureRenderer.LEGACY because it renders public signatures with hashes which are + // computed by mangled names. So no real need in testing IdSignatureRenderer.DEFAULT which renders mangled names + // instead of hashes. fun printActualMangledNamesAndSignatures() { printMangledNames(computedMangledNames) symbol.signature?.let { - println("// Public signature: ${it.render()}") + println("// Public signature: ${it.render(IdSignatureRenderer.LEGACY)}") } symbol.privateSignature?.let { - println("// Private signature: ${it.render()}") + println("// Private signature: ${it.render(IdSignatureRenderer.LEGACY)}") } } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JvmIrLinkageModeTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JvmIrLinkageModeTest.kt index 680c67cc0ad..e25372e36d0 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JvmIrLinkageModeTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/JvmIrLinkageModeTest.kt @@ -12,11 +12,10 @@ import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.IdSignature -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid diff --git a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt index 33e38813c1c..a477f0eda62 100644 --- a/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt +++ b/kotlin-native/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/DefaultIdSignatureRenderer.kt @@ -5,6 +5,7 @@ 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.render class DefaultIdSignatureRenderer(private val prefix: String? = null) : IdSignatureRenderer { private val idSignaturer = KonanIdSignaturer(KonanManglerDesc)