From 291d535de7645b7d57194bcbcc470047ac2e3566 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 20 Sep 2016 15:24:14 +0300 Subject: [PATCH] Fix IR generation for string templates containing single entry. --- .../psi2ir/generators/StatementGenerator.kt | 26 +++++++------- .../impl/IrStringConcatenationImpl.kt | 13 ++++--- .../ir/irText/expressions/stringTemplates.kt | 7 +++- .../ir/irText/expressions/stringTemplates.txt | 35 +++++++++++++++++++ 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index d1869be5a08..e3eab4804d4 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -203,18 +203,20 @@ class StatementGenerator( override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Nothing?): IrStatement { val entries = expression.entries - when (entries.size) { - 1 -> return entries[0].genExpr() - 0 -> return IrConstImpl.string(expression.startOffset, expression.endOffset, - getInferredTypeWithImplicitCastsOrFail(expression), "") + val resultType = getInferredTypeWithImplicitCastsOrFail(expression) + return when (entries.size) { + 1 -> { + val irArg = entries[0].genExpr() + if (irArg is IrConst<*> && irArg.kind == IrConstKind.String) + irArg + else + IrStringConcatenationImpl(expression.startOffset, expression.endOffset, resultType, listOf(irArg)) + } + 0 -> + IrConstImpl.string(expression.startOffset, expression.endOffset, resultType, "") + else -> + IrStringConcatenationImpl(expression.startOffset, expression.endOffset, resultType, entries.map { it.genExpr() }) } - - val irStringTemplate = IrStringConcatenationImpl(expression.startOffset, expression.endOffset, - getInferredTypeWithImplicitCastsOrFail(expression)) - entries.forEach { - irStringTemplate.addArgument(it.genExpr()) - } - return irStringTemplate } override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement = @@ -267,7 +269,7 @@ class StatementGenerator( IrGetEnumValueImpl(expression.startOffset, expression.endOffset, classValueType, descriptor) else -> { IrGetObjectValueImpl(expression.startOffset, expression.endOffset, classValueType, - descriptor.companionObjectDescriptor ?: throw AssertionError("Class value without companion object: $descriptor")) + descriptor.companionObjectDescriptor ?: throw AssertionError("Class value without companion object: $descriptor")) } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrStringConcatenationImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrStringConcatenationImpl.kt index a22f0ffe699..1f744dd4bc2 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrStringConcatenationImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrStringConcatenationImpl.kt @@ -16,20 +16,19 @@ package org.jetbrains.kotlin.ir.expressions.impl -import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation -import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType import java.util.* -class IrStringConcatenationImpl( - startOffset: Int, - endOffset: Int, - type: KotlinType -) : IrExpressionBase(startOffset, endOffset, type), IrStringConcatenation { +class IrStringConcatenationImpl(startOffset: Int, endOffset: Int, type: KotlinType) : + IrExpressionBase(startOffset, endOffset, type), IrStringConcatenation { + constructor(startOffset: Int, endOffset: Int, type: KotlinType, arguments: Collection) : this(startOffset, endOffset, type) { + this.arguments.addAll(arguments) + } + override val arguments: MutableList = ArrayList() override fun addArgument(argument: IrExpression) { diff --git a/compiler/testData/ir/irText/expressions/stringTemplates.kt b/compiler/testData/ir/irText/expressions/stringTemplates.kt index c8a65990d65..844d204cdd2 100644 --- a/compiler/testData/ir/irText/expressions/stringTemplates.kt +++ b/compiler/testData/ir/irText/expressions/stringTemplates.kt @@ -1,4 +1,5 @@ fun foo(): String = "" +val x = 42 val test1 = "" val test2 = "abc" @@ -7,4 +8,8 @@ val test4 = """abc""" val test5 = """ abc """ -val test6 = "$test1 ${foo()}" \ No newline at end of file +val test6 = "$test1 ${foo()}" + +val test7 = "$test1" +val test8 = "${foo()}" +val test9 = "$x" \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/stringTemplates.txt b/compiler/testData/ir/irText/expressions/stringTemplates.txt index e6348401b27..1d0478ba620 100644 --- a/compiler/testData/ir/irText/expressions/stringTemplates.txt +++ b/compiler/testData/ir/irText/expressions/stringTemplates.txt @@ -3,6 +3,14 @@ FILE /stringTemplates.kt BLOCK_BODY RETURN type=kotlin.Nothing from='foo(): String' CONST String type=kotlin.String value='' + PROPERTY public val x: kotlin.Int = 42 + FIELD PROPERTY_BACKING_FIELD public val x: kotlin.Int = 42 + EXPRESSION_BODY + CONST Int type=kotlin.Int value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'x: Int' type=kotlin.Int origin=null PROPERTY public val test1: kotlin.String = "" FIELD PROPERTY_BACKING_FIELD public val test1: kotlin.String = "" EXPRESSION_BODY @@ -63,3 +71,30 @@ abc BLOCK_BODY RETURN type=kotlin.Nothing from='(): String' GET_FIELD 'test6: String' type=kotlin.String origin=null + PROPERTY public val test7: kotlin.String = "" + FIELD PROPERTY_BACKING_FIELD public val test7: kotlin.String = "" + EXPRESSION_BODY + STRING_CONCATENATION type=kotlin.String + CALL '(): String' type=kotlin.String origin=GET_PROPERTY + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): String' + GET_FIELD 'test7: String' type=kotlin.String origin=null + PROPERTY public val test8: kotlin.String + FIELD PROPERTY_BACKING_FIELD public val test8: kotlin.String + EXPRESSION_BODY + STRING_CONCATENATION type=kotlin.String + CALL 'foo(): String' type=kotlin.String origin=null + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): String' + GET_FIELD 'test8: String' type=kotlin.String origin=null + PROPERTY public val test9: kotlin.String = "42" + FIELD PROPERTY_BACKING_FIELD public val test9: kotlin.String = "42" + EXPRESSION_BODY + STRING_CONCATENATION type=kotlin.String + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): String' + GET_FIELD 'test9: String' type=kotlin.String origin=null