From 9041d717a2d1fe09a4a8557c0d5b7bcda2f56879 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Wed, 10 Oct 2018 08:22:41 +0300 Subject: [PATCH] [JS IR BE] add `IrType.asString` that return stable string representation to use it for stringified signatures `IrType.render` was used before, but it's written for debugging purpose and generates unstable string representation. --- .../backend/js/lower/BridgesConstruction.kt | 29 +++++--------- .../kotlin/ir/backend/js/utils/IrTypeUtils.kt | 40 +++++++++++++++++++ .../backend/js/utils/SimpleNameGenerator.kt | 19 ++++++--- 3 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt index d7156732185..56002107ddf 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. 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.backend.js.lower @@ -28,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.isStatic +import org.jetbrains.kotlin.ir.backend.js.utils.asString import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl @@ -38,7 +28,6 @@ import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.isReal import org.jetbrains.kotlin.ir.util.parentAsClass -import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -203,12 +192,16 @@ class FunctionAndSignature(val function: IrSimpleFunction) { private val signature = Signature( function.name, - function.extensionReceiverParameter?.type?.render(), - function.valueParameters.map { it.type.render() } + function.extensionReceiverParameter?.type?.asString(), + function.valueParameters.map { it.type.asString() } ) - override fun equals(other: Any?) = - signature == (other as FunctionAndSignature).signature + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is FunctionAndSignature) return false + + return signature == other.signature + } override fun hashCode(): Int = signature.hashCode() } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt new file mode 100644 index 00000000000..49fc75b0308 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.backend.js.utils + +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty + +fun IrType.asString(): String = when(this) { + // TODO: should each IrErrorType have own string representation? + is IrErrorType -> "\$ErrorType\$" + // TODO: should we prohibit user classes called dynamic? + is IrDynamicType -> "dynamic" + is IrSimpleType -> + classifier.asString() + + (if (hasQuestionMark) "?" else "") + + (arguments.ifNotEmpty { + joinToString(separator = ",", prefix = "<", postfix = ">") { it.asString() } + } ?: "") + else -> error("Unexpected kind of IrType: " + javaClass.typeName) +} + +private fun IrTypeArgument.asString(): String = when(this) { + is IrStarProjection -> "*" + is IrTypeProjection -> variance.label + (if (variance != Variance.INVARIANT) " " else "") + type.asString() + else -> error("Unexpected kind of IrTypeArgument: " + javaClass.simpleName) +} + +private fun IrClassifierSymbol.asString() = when (this) { + is IrTypeParameterSymbol -> this.owner.name.asString() + is IrClassSymbol -> this.descriptor.fqNameUnsafe.asString() + else -> error("Unexpected kind of IrClassifierSymbol: " + javaClass.typeName) +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index b14dd91d987..ff9a7b545ed 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -14,13 +14,13 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.isDynamic import org.jetbrains.kotlin.ir.util.isEffectivelyExternal -import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.js.backend.ast.JsName import org.jetbrains.kotlin.js.naming.isES5IdentifierPart import org.jetbrains.kotlin.js.naming.isES5IdentifierStart import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty // TODO: this class has to be reimplemented soon class SimpleNameGenerator : NameGenerator { @@ -183,9 +183,17 @@ class SimpleNameGenerator : NameGenerator { } nameBuilder.append(declaration.name.asString()) - declaration.extensionReceiverParameter?.let { nameBuilder.append("_\$${it.type.render()}") } - declaration.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") } - declaration.valueParameters.forEach { nameBuilder.append("_${it.type.render()}") } + // TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters? + declaration.typeParameters.ifNotEmpty { + nameBuilder.append("_\$t") + joinTo(nameBuilder, "") { "_${it.name.asString()}" } + } + declaration.extensionReceiverParameter?.let { + nameBuilder.append("_r$${it.type.asString()}") + } + declaration.valueParameters.ifNotEmpty { + joinTo(nameBuilder, "") { "_${it.type.asString()}" } + } } } @@ -198,11 +206,10 @@ class SimpleNameGenerator : NameGenerator { nameDeclarator(sanitizeName(nameBuilder.toString())) } - private fun sanitizeName(name: String): String { if (name.isEmpty()) return "_" val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' } return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("") } -} \ No newline at end of file +}