From 4327d7b42597566af2d9e4f79a903ac9918ee554 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Mon, 30 Jun 2025 16:13:37 +0300 Subject: [PATCH] [kotlin] take prefix into account when injecting into multi-dollar strings KTIJ-33031 GitOrigin-RevId: 3d5253791733df4c821c40a2659b03c591275f5b --- .../KotlinLanguageInjectionPerformerBase.kt | 5 ++-- .../k2/injection/K2KotlinInjectionTest.kt | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/plugins/kotlin/injection/base/src/org/jetbrains/kotlin/idea/base/injection/KotlinLanguageInjectionPerformerBase.kt b/plugins/kotlin/injection/base/src/org/jetbrains/kotlin/idea/base/injection/KotlinLanguageInjectionPerformerBase.kt index cb838b2718b0..e8b719b56f5c 100644 --- a/plugins/kotlin/injection/base/src/org/jetbrains/kotlin/idea/base/injection/KotlinLanguageInjectionPerformerBase.kt +++ b/plugins/kotlin/injection/base/src/org/jetbrains/kotlin/idea/base/injection/KotlinLanguageInjectionPerformerBase.kt @@ -73,7 +73,8 @@ abstract class KotlinLanguageInjectionPerformerBase : LanguageInjectionPerformer ContainerUtil.concat(listOfNotNull(child.left, child.right), tail), pendingPrefix, unparseable, collected) } child is KtStringTemplateExpression -> { - if (child.children.isEmpty()) { + val entries = child.entries + if (entries.isEmpty()) { // empty range to save injection in the empty string collected += injectionRange( child, @@ -83,7 +84,7 @@ abstract class KotlinLanguageInjectionPerformerBase : LanguageInjectionPerformer ) } return collectInjections(child, - ContainerUtil.concat(child.children.toList(), tail), pendingPrefix, unparseable, collected) + ContainerUtil.concat(entries.toList(), tail), pendingPrefix, unparseable, collected) } literal == null -> { val (prefix, myUnparseable) = makePlaceholder(child) diff --git a/plugins/kotlin/injection/k2/tests/test/org/jetbrains/kotlin/idea/k2/injection/K2KotlinInjectionTest.kt b/plugins/kotlin/injection/k2/tests/test/org/jetbrains/kotlin/idea/k2/injection/K2KotlinInjectionTest.kt index 338f0e4bf959..b6f3cf35e958 100644 --- a/plugins/kotlin/injection/k2/tests/test/org/jetbrains/kotlin/idea/k2/injection/K2KotlinInjectionTest.kt +++ b/plugins/kotlin/injection/k2/tests/test/org/jetbrains/kotlin/idea/k2/injection/K2KotlinInjectionTest.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.idea.base.injection.KotlinInjectionTestBase import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.withCustomCompilerOptions class K2KotlinInjectionTest: KotlinInjectionTestBase() { @@ -41,4 +42,30 @@ class K2KotlinInjectionTest: KotlinInjectionTestBase() { assertEquals("Wrong injection language", KotlinLanguage.INSTANCE, injectedFile?.language) } + + fun testInjectionIntoMultiDollarString() { + val file = myFixture.configureByText( + "a.kt", + """ + // COMPILER_ARGUMENTS: -Xmulti-dollar-interpolation + + import org.intellij.lang.annotations.Language + + @Language("JSON") + val json = $$$""${'"'} + { + "openapi": "3.0.2", + "info": { + "title": "REST", + "version": "1.0.0" + } + } + ""${'"'} + """.trimIndent() + ) + + withCustomCompilerOptions(file.text, project, module) { + myFixture.checkHighlighting() + } + } }