diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 3a0b0776907..eb76b4b2dfc 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -41752,6 +41752,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @Test + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @Test @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index b8f86096448..e6a94d26f33 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -423,6 +423,12 @@ private val foldConstantLoweringPhase = makeBodyLoweringPhase( prerequisite = setOf(propertyAccessorInlinerLoweringPhase) ) +private val computeStringTrimPhase = makeJsModulePhase( + ::StringTrimLowering, + name = "StringTrimLowering", + description = "Compute trimIndent and trimMargin operations on constant strings" +).toModuleLowering() + private val localDelegatedPropertiesLoweringPhase = makeBodyLoweringPhase( { LocalDelegatedPropertiesLowering() }, name = "LocalDelegatedPropertiesLowering", @@ -816,6 +822,7 @@ private val loweringList = listOf( copyPropertyAccessorBodiesLoweringPass, booleanPropertyInExternalLowering, foldConstantLoweringPhase, + computeStringTrimPhase, privateMembersLoweringPhase, privateMemberUsagesLoweringPhase, exportedDefaultParameterStubPhase, diff --git a/compiler/testData/codegen/box/strings/trimOptimization.kt b/compiler/testData/codegen/box/strings/trimOptimization.kt new file mode 100644 index 00000000000..6db1be7f839 --- /dev/null +++ b/compiler/testData/codegen/box/strings/trimOptimization.kt @@ -0,0 +1,147 @@ +// WITH_RUNTIME +// IGNORE_BACKEND: JS + +import kotlin.test.assertEquals + +// CHECK_CONTAINS_NO_CALLS: trimIndentConstant +fun trimIndentConstant(): String { + return """ + Hello, + World + """.trimIndent() +} + +// CHECK_CONTAINS_NO_CALLS: trimIndentInterpolatedUsingConstant +private const val HAS_INDENT = """Hello, + World""" +fun trimIndentInterpolatedUsingConstant(): String { + return """ + Hello, + $HAS_INDENT + World + """.trimIndent() +} + +// CHECK_CONTAINS_NO_CALLS: trimIndentReliesOnNestedStringBuilderFlatteningAndConstantConcatenation +private const val SPACES = " " +private const val HELLO = "Hello" +private const val WORLD = "World" +fun trimIndentReliesOnNestedStringBuilderFlatteningAndConstantConcatenation(): String { + return ("" + '\n' + SPACES + "${SPACES}Hey" + """ + ${HELLO + HELLO}, + ${WORLD + WORLD} +""" + SPACES).trimIndent() +} + +// CHECK_CALLED_IN_SCOPE: function=trimIndent scope=trimIndentNotConstant +fun trimIndentNotConstant(arg: String): String { + return arg.trimIndent() +} + +// CHECK_CALLED_IN_SCOPE: function=trimIndent scope=trimIndentInterpolated +fun trimIndentInterpolated(arg: Int): String { + return """ + Hello, + $arg + """.trimIndent() +} + +// CHECK_CONTAINS_NO_CALLS: trimMarginConstant +fun trimMarginConstant(): String { + return """ + |Hello, + |World + """.trimMargin() +} + +// CHECK_CONTAINS_NO_CALLS: trimMarginInterpolatedUsingConstant +private const val HAS_MARGIN = """Hello, + |World""" +fun trimMarginInterpolatedUsingConstant(): String { + return """ + |Hello, + |$HAS_MARGIN + |World + """.trimMargin() +} + +// CHECK_CONTAINS_NO_CALLS: trimMarginReliesOnNestedStringBuilderFlatteningAndConstantConcatenation +fun trimMarginReliesOnNestedStringBuilderFlatteningAndConstantConcatenation(): String { + return ("" + '\n' + SPACES + "${SPACES}|Hey" + """ + |${HELLO + HELLO}, + |${WORLD + WORLD} +""" + SPACES).trimMargin() +} + +// CHECK_CONTAINS_NO_CALLS: trimMarginConstantCustomPrefix +fun trimMarginConstantCustomPrefix(): String { + return """ + ###Hello, + ###World + """.trimMargin(marginPrefix = "###") +} + +// CHECK_CONTAINS_NO_CALLS: trimMarginConstantCustomPrefixInterpolatedUsingConstant +private const val OCTOTHORPE = '#' +fun trimMarginConstantCustomPrefixInterpolatedUsingConstant(): String { + return """ + #@#Hello, + #@#World + """.trimMargin(marginPrefix = "$OCTOTHORPE@$OCTOTHORPE") +} + +// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginNotConstant +fun trimMarginNotConstant(arg: String): String { + return arg.trimMargin() +} + +// CHECK_CALLED_IN_SCOPE: function=trimMargin scope=trimMarginNotConstantCustomPrefix +fun trimMarginNotConstantCustomPrefix(arg: String): String { + return arg.trimMargin("###") +} + +// CHECK_CALLED_IN_SCOPE: function=trimMargin$default scope=trimMarginInterpolated +fun trimMarginInterpolated(arg: Int): String { + return """ + |Hello, + |$arg + """.trimMargin() +} + +// CHECK_CALLED_IN_SCOPE: function=trimMargin scope=trimMarginConstantWithNonConstantCustomPrefix +fun trimMarginConstantWithNonConstantCustomPrefix(arg: String): String { + return """ + |Hello, + |World + """.trimMargin(arg) +} + +fun box(): String { + + assertEquals("Hello,\nWorld", trimIndentConstant()) + assertEquals("Hello,\nHello,\nWorld\nWorld", trimIndentInterpolatedUsingConstant()) + assertEquals("Hey\nHelloHello,\nWorldWorld", trimIndentReliesOnNestedStringBuilderFlatteningAndConstantConcatenation()) + assertEquals("Hello,\nWorld", trimIndentNotConstant(""" + Hello, + World + """)) + assertEquals("Hello,\n42", trimIndentInterpolated(42)) + + assertEquals("Hello,\nWorld", trimMarginConstant()) + assertEquals("Hello,\nHello,\nWorld\nWorld", trimMarginInterpolatedUsingConstant()) + assertEquals("Hey\nHelloHello,\nWorldWorld", trimMarginReliesOnNestedStringBuilderFlatteningAndConstantConcatenation()) + assertEquals("Hello,\nWorld", trimMarginConstantCustomPrefix()) + assertEquals("Hello,\nWorld", trimMarginConstantCustomPrefixInterpolatedUsingConstant()) + assertEquals("Hello,\nWorld", trimMarginNotConstant(""" + |Hello, + |World + """)) + assertEquals("Hello,\nWorld", trimMarginNotConstantCustomPrefix(""" + ###Hello, + ###World + """)) + assertEquals("Hello,\n42", trimMarginInterpolated(42)) + assertEquals("Hello,\nWorld", trimMarginConstantWithNonConstantCustomPrefix("|")) + + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index e38618b4a41..02852e3c896 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -41590,6 +41590,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @Test + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @Test @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 5e0c0b463a0..6b0461c4367 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -41752,6 +41752,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @Test + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @Test @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8d4101fe31d..3c4172e7f6b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -33434,6 +33434,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { runTest("compiler/testData/codegen/box/strings/twoArgumentNullableStringOperatorPlus.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 99b87203de6..8623146aa1e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -27924,6 +27924,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { runTest("compiler/testData/codegen/box/strings/twoArgumentNullableStringOperatorPlus.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 3321dd18736..eaed052c3b5 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -27330,6 +27330,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { runTest("compiler/testData/codegen/box/strings/twoArgumentNullableStringOperatorPlus.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 89b7509d1a5..7f69511507f 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -27240,6 +27240,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { runTest("compiler/testData/codegen/box/strings/twoArgumentNullableStringOperatorPlus.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 45508602005..75252979044 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -21164,6 +21164,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/strings/surrogatePair.kt"); } + @TestMetadata("trimOptimization.kt") + public void testTrimOptimization() throws Exception { + runTest("compiler/testData/codegen/box/strings/trimOptimization.kt"); + } + @TestMetadata("twoArgumentNullableStringOperatorPlus.kt") public void testTwoArgumentNullableStringOperatorPlus() throws Exception { runTest("compiler/testData/codegen/box/strings/twoArgumentNullableStringOperatorPlus.kt");