Correctly honor expected type when converting string templates to UAST

#KT-17315 Fixed
 #KT-17316 Fixed
This commit is contained in:
Dmitry Jemerov
2017-04-18 16:57:12 +02:00
parent f801c5f3f8
commit 03cef30717
4 changed files with 44 additions and 18 deletions
@@ -250,15 +250,28 @@ internal object KotlinConverter {
}
internal fun convert(entry: KtStringTemplateEntry, parent: UElement?): UExpression = when (entry) {
is KtStringTemplateEntryWithExpression -> KotlinConverter.convertOrEmpty(entry.expression, parent)
is KtEscapeStringTemplateEntry -> KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
else -> {
KotlinStringULiteralExpression(entry, parent)
internal fun convertEntry(entry: KtStringTemplateEntry,
parentCallback: (() -> UElement?)?,
requiredType: Class<out UElement>? = null): UExpression? {
return with(requiredType) {
if (entry is KtStringTemplateEntryWithExpression) {
expr<UExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinConverter.convertOrEmpty(entry.expression, parent)
}
}
else {
expr<ULiteralExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
if (entry is KtEscapeStringTemplateEntry)
KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
else
KotlinStringULiteralExpression(entry, parent)
}
}
}
}
internal fun convertExpression(expression: KtExpression,
parentCallback: (() -> UElement?)?,
requiredType: Class<out UElement>? = null): UExpression? {
@@ -272,14 +285,17 @@ internal object KotlinConverter {
return with (requiredType) { when (expression) {
is KtVariableDeclaration -> expr<UDeclarationsExpression>(build(::convertVariablesDeclaration))
is KtStringTemplateExpression -> expr<ULiteralExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
if (expression.entries.isEmpty())
KotlinStringULiteralExpression(expression, parent, "")
is KtStringTemplateExpression -> {
if (expression.entries.isEmpty()) {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
expr<ULiteralExpression> { KotlinStringULiteralExpression(expression, parent, "") }
}
else if (expression.entries.size == 1)
convert(expression.entries[0], parent)
else
KotlinStringTemplateUPolyadicExpression(expression, parent)
convertEntry(expression.entries[0], parentCallback, requiredType)
else {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
expr<UExpression> { KotlinStringTemplateUPolyadicExpression(expression, parent) }
}
}
is KtDestructuringDeclaration -> expr<UDeclarationsExpression> {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
@@ -29,6 +29,6 @@ class KotlinStringTemplateUPolyadicExpression(
UPolyadicExpression,
KotlinUElementWithType,
KotlinEvaluatableUElement {
override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convert(it, this) } }
override val operands: List<UExpression> by lz { psi.entries.map { KotlinConverter.convertEntry(it, { this })!! } }
override val operator = UastBinaryOperator.PLUS
}
+2
View File
@@ -0,0 +1,2 @@
val bar = "bar"
val f = "foo$bar"
+12 -4
View File
@@ -1,11 +1,10 @@
package org.jetbrains.uast.test.kotlin
import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UFile
import org.jetbrains.uast.ULiteralExpression
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.uast.*
import org.jetbrains.uast.test.env.findElementByText
import org.jetbrains.uast.toUElement
import org.junit.Assert
import org.junit.Test
@@ -32,4 +31,13 @@ class KotlinUastApiTest : AbstractKotlinUastTest() {
}
}
@Test fun testConvertStringTemplateWithExpectedType() {
doTest("StringTemplateWithVar") { _, file ->
val index = file.psi.text.indexOf("foo")
val stringTemplate = file.psi.findElementAt(index)!!.getParentOfType<KtStringTemplateExpression>(false)
val uLiteral = stringTemplate.toUElementOfType<ULiteralExpression>()
assertNull(uLiteral)
}
}
}