diff --git a/idea/resources/META-INF/jvm.xml.191 b/idea/resources/META-INF/jvm.xml.191
new file mode 100644
index 00000000000..6bbe371b8ec
--- /dev/null
+++ b/idea/resources/META-INF/jvm.xml.191
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+ org.jetbrains.kotlin.idea.JvmPluginStartupComponent
+
+
+
+
+
+ org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager
+
+
+ org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
+
+
+ org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook
+
+
+ org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191
index 2c62d83f432..7af3e07f69b 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinAbstractUElement.kt.191
@@ -79,9 +79,14 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
parent = parent.parent
}
- if (parent is KtBlockStringTemplateEntry) {
- parent = parent.parent
- }
+ if (KotlinConverter.forceUInjectionHost) {
+ if (parent is KtBlockStringTemplateEntry) {
+ parent = parent.parent
+ }
+ } else
+ while (parent is KtStringTemplateEntryWithExpression || parent is KtStringTemplateExpression && parent.entries.size == 1) {
+ parent = parent.parent
+ }
if (parent is KtWhenConditionWithExpression) {
parent = parent.parent
@@ -109,7 +114,7 @@ abstract class KotlinAbstractUElement(private val givenParent: UElement?) : Kotl
val result = doConvertParent(this, parent)
if (result == this) {
- throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}]")
+ throw IllegalStateException("Loop in parent structure when converting a $psi of type ${psi?.javaClass} with parent $parent of type ${parent?.javaClass} text: [${parent?.text}], result = $result")
}
return result
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191
index 07ea7a0808c..d1c2a09b61c 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.191
@@ -19,9 +19,11 @@ package org.jetbrains.uast.kotlin
import com.intellij.lang.Language
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.tree.LeafPsiElement
+import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
@@ -394,6 +396,12 @@ internal object KotlinConverter {
}
}
+ var forceUInjectionHost = Registry.`is`("kotlin.uast.force.uinjectionhost", false)
+ @TestOnly
+ set(value) {
+ field = value
+ }
+
internal fun convertExpression(expression: KtExpression,
givenParent: UElement?,
requiredType: Class? = null): UExpression? {
@@ -404,7 +412,20 @@ internal object KotlinConverter {
return with (requiredType) { when (expression) {
is KtVariableDeclaration -> expr(build(::convertVariablesDeclaration))
- is KtStringTemplateExpression -> expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
+ is KtStringTemplateExpression -> {
+ when {
+ forceUInjectionHost || (requiredType != null && UInjectionHost::class.java.isAssignableFrom(requiredType)) ->
+ expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
+ expression.entries.isEmpty() -> {
+ expr { KotlinStringULiteralExpression(expression, givenParent, "") }
+ }
+
+ expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType)
+
+ else ->
+ expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) }
+ }
+ }
is KtDestructuringDeclaration -> expr {
val declarationsExpression = KotlinUDestructuringDeclarationExpression(givenParent, expression)
declarationsExpression.apply {
diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191
new file mode 100644
index 00000000000..5f4748f3f3a
--- /dev/null
+++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.kt.191
@@ -0,0 +1,17 @@
+val muchRecur = "${"${"${"abc"}"}"}"
+
+val case4 = "a ${"literal"} z"
+
+val case5 = "a ${"literal"} ${"literal"} z"
+
+val literalInLiteral = "a ${"literal$case4"} z"
+
+val literalInLiteral2 = "a ${"literal$case4".repeat(4)} z"
+
+fun simpleForTemplate(i: Int = 0) = "$i"
+
+fun foo() {
+ println("$baz")
+ val template1 = "${simpleForTemplate()}"
+ val template2 = ".${simpleForTemplate()}"
+}
diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191
new file mode 100644
index 00000000000..9458b707d90
--- /dev/null
+++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.log.txt.191
@@ -0,0 +1,80 @@
+UFile (package = )
+ UClass (name = StringTemplateComplexForUInjectionHostKt)
+ UField (name = muchRecur)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ UPolyadicExpression (operator = +)
+ UPolyadicExpression (operator = +)
+ UPolyadicExpression (operator = +)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "abc")
+ UField (name = case4)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "a ")
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "literal")
+ ULiteralExpression (value = " z")
+ UField (name = case5)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "a ")
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "literal")
+ ULiteralExpression (value = " ")
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "literal")
+ ULiteralExpression (value = " z")
+ UField (name = literalInLiteral)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "a ")
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "literal")
+ USimpleNameReferenceExpression (identifier = case4)
+ ULiteralExpression (value = " z")
+ UField (name = literalInLiteral2)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "a ")
+ UQualifiedReferenceExpression
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = "literal")
+ USimpleNameReferenceExpression (identifier = case4)
+ UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
+ UIdentifier (Identifier (repeat))
+ USimpleNameReferenceExpression (identifier = repeat)
+ ULiteralExpression (value = 4)
+ ULiteralExpression (value = " z")
+ UAnnotationMethod (name = getMuchRecur)
+ UAnnotationMethod (name = getCase4)
+ UAnnotationMethod (name = getCase5)
+ UAnnotationMethod (name = getLiteralInLiteral)
+ UAnnotationMethod (name = getLiteralInLiteral2)
+ UAnnotationMethod (name = simpleForTemplate)
+ UParameter (name = i)
+ UAnnotation (fqName = org.jetbrains.annotations.NotNull)
+ ULiteralExpression (value = 0)
+ UBlockExpression
+ UReturnExpression
+ UPolyadicExpression (operator = +)
+ USimpleNameReferenceExpression (identifier = i)
+ UAnnotationMethod (name = foo)
+ UBlockExpression
+ UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
+ UIdentifier (Identifier (println))
+ USimpleNameReferenceExpression (identifier = println)
+ UPolyadicExpression (operator = +)
+ USimpleNameReferenceExpression (identifier = baz)
+ UDeclarationsExpression
+ ULocalVariable (name = template1)
+ UPolyadicExpression (operator = +)
+ UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
+ UIdentifier (Identifier (simpleForTemplate))
+ USimpleNameReferenceExpression (identifier = simpleForTemplate)
+ UDeclarationsExpression
+ ULocalVariable (name = template2)
+ UPolyadicExpression (operator = +)
+ ULiteralExpression (value = ".")
+ UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0))
+ UIdentifier (Identifier (simpleForTemplate))
+ USimpleNameReferenceExpression (identifier = simpleForTemplate)
diff --git a/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191 b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191
new file mode 100644
index 00000000000..c6ab7798351
--- /dev/null
+++ b/plugins/uast-kotlin/testData/StringTemplateComplexForUInjectionHost.render.txt.191
@@ -0,0 +1,20 @@
+public final class StringTemplateComplexForUInjectionHostKt {
+ @org.jetbrains.annotations.NotNull private static final var muchRecur: java.lang.String = "abc"
+ @org.jetbrains.annotations.NotNull private static final var case4: java.lang.String = "a " + "literal" + " z"
+ @org.jetbrains.annotations.NotNull private static final var case5: java.lang.String = "a " + "literal" + " " + "literal" + " z"
+ @org.jetbrains.annotations.NotNull private static final var literalInLiteral: java.lang.String = "a " + "literal" + case4 + " z"
+ @org.jetbrains.annotations.NotNull private static final var literalInLiteral2: java.lang.String = "a " + "literal" + case4.repeat(4) + " z"
+ public static final fun getMuchRecur() : java.lang.String = UastEmptyExpression
+ public static final fun getCase4() : java.lang.String = UastEmptyExpression
+ public static final fun getCase5() : java.lang.String = UastEmptyExpression
+ public static final fun getLiteralInLiteral() : java.lang.String = UastEmptyExpression
+ public static final fun getLiteralInLiteral2() : java.lang.String = UastEmptyExpression
+ public static final fun simpleForTemplate(@org.jetbrains.annotations.NotNull i: int) : java.lang.String {
+ return i
+ }
+ public static final fun foo() : void {
+ println(baz)
+ var template1: java.lang.String = simpleForTemplate()
+ var template2: java.lang.String = "." + simpleForTemplate()
+ }
+}
diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191 b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191
new file mode 100644
index 00000000000..d33aa51ac19
--- /dev/null
+++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt.191
@@ -0,0 +1,103 @@
+package org.jetbrains.uast.test.kotlin
+
+import org.jetbrains.uast.kotlin.KotlinConverter
+import org.junit.Test
+
+class SimpleKotlinRenderLogTest : AbstractKotlinRenderLogTest() {
+ @Test fun testLocalDeclarations() = doTest("LocalDeclarations")
+
+ @Test fun testSimple() = doTest("Simple")
+
+ @Test fun testWhenIs() = doTest("WhenIs")
+
+ @Test fun testDefaultImpls() = doTest("DefaultImpls")
+
+ @Test fun testElvis() = doTest("Elvis")
+
+ @Test fun testPropertyAccessors() = doTest("PropertyAccessors")
+
+ @Test fun testPropertyInitializer() = doTest("PropertyInitializer")
+
+ @Test fun testPropertyInitializerWithoutSetter() = doTest("PropertyInitializerWithoutSetter")
+
+ @Test fun testAnnotationParameters() = doTest("AnnotationParameters")
+
+ @Test fun testEnumValueMembers() = doTest("EnumValueMembers")
+
+ @Test fun testStringTemplate() = doTest("StringTemplate")
+
+ @Test fun testStringTemplateComplex() = doTest("StringTemplateComplex")
+
+ @Test
+ fun testStringTemplateComplexForUInjectionHost() = withForceUInjectionHostValue {
+ doTest("StringTemplateComplexForUInjectionHost")
+ }
+
+ @Test fun testQualifiedConstructorCall() = doTest("QualifiedConstructorCall")
+
+ @Test fun testPropertyDelegate() = doTest("PropertyDelegate")
+
+ @Test fun testLocalVariableWithAnnotation() = doTest("LocalVariableWithAnnotation")
+
+ @Test fun testPropertyWithAnnotation() = doTest("PropertyWithAnnotation")
+
+ @Test fun testIfStatement() = doTest("IfStatement")
+
+ @Test fun testInnerClasses() = doTest("InnerClasses")
+
+ @Test fun testSimpleScript() = doTest("SimpleScript") { testName, file -> check(testName, file, false) }
+
+ @Test fun testDestructuringDeclaration() = doTest("DestructuringDeclaration")
+
+ @Test fun testDefaultParameterValues() = doTest("DefaultParameterValues")
+
+ @Test fun testParameterPropertyWithAnnotation() = doTest("ParameterPropertyWithAnnotation")
+
+ @Test fun testParametersWithDefaultValues() = doTest("ParametersWithDefaultValues")
+
+ @Test
+ fun testUnexpectedContainer() = doTest("UnexpectedContainerException")
+
+ @Test
+ fun testWhenStringLiteral() = doTest("WhenStringLiteral")
+
+ @Test
+ fun testWhenAndDestructing() = doTest("WhenAndDestructing") { testName, file -> check(testName, file, false) }
+
+ @Test
+ fun testSuperCalls() = doTest("SuperCalls")
+
+ @Test
+ fun testConstructors() = doTest("Constructors")
+
+ @Test
+ fun testClassAnnotation() = doTest("ClassAnnotation")
+
+ @Test
+ fun testReceiverFun() = doTest("ReceiverFun")
+
+ @Test
+ fun testAnonymous() = doTest("Anonymous")
+
+ @Test
+ fun testAnnotationComplex() = doTest("AnnotationComplex")
+
+ @Test
+ fun testParametersDisorder() = doTest("ParametersDisorder") { testName, file ->
+ // disabled due to inconsistent parents for 2-receivers call (KT-22344)
+ check(testName, file, false)
+ }
+
+ @Test
+ fun testLambdas() = doTest("Lambdas")
+}
+
+fun withForceUInjectionHostValue(call: () -> Unit) {
+ val prev = KotlinConverter.forceUInjectionHost
+ KotlinConverter.forceUInjectionHost = true
+ try {
+ call.invoke()
+ } finally {
+ KotlinConverter.forceUInjectionHost = prev
+ }
+}
\ No newline at end of file