@@ -5,6 +5,7 @@ import com.tschuchort.compiletesting.KotlinCompilation
55import com.tschuchort.compiletesting.SourceFile
66import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
77import org.junit.jupiter.api.Assertions.assertEquals
8+ import org.junit.jupiter.api.Assumptions.assumeTrue
89import org.junit.jupiter.api.Test
910
1011/* *
@@ -53,14 +54,22 @@ class StormTemplatePluginTest {
5354 """ ,
5455 )
5556
56- private fun compile (vararg sources : SourceFile ): JvmCompilationResult = KotlinCompilation ().apply {
57+ private fun compile (vararg sources : SourceFile , languageVersion : String = "2.0" ): JvmCompilationResult = KotlinCompilation ().apply {
5758 this .sources = listOf (templateContextStub) + sources.toList()
5859 compilerPluginRegistrars = listOf (StormTemplatePluginRegistrar ())
5960 inheritClassPath = true
60- languageVersion = " 2.0 "
61+ this . languageVersion = languageVersion
6162 verbose = false
6263 }.compile()
6364
65+ /* * Assumes compilation succeeded; skips the test if the compiler does not support the required language features. */
66+ private fun assumeCompilationSuccess (result : JvmCompilationResult ) {
67+ assumeTrue(
68+ result.exitCode == KotlinCompilation .ExitCode .OK ,
69+ " Compilation failed (compiler may not support the required language features): ${result.messages.lines().take(5 ).joinToString(" \n " )} " ,
70+ )
71+ }
72+
6473 private fun JvmCompilationResult.runMain (): String {
6574 val output = StringBuilder ()
6675 val mainClass = classLoader.loadClass(" TestKt" )
@@ -609,4 +618,126 @@ class StormTemplatePluginTest {
609618 assertEquals(" SELECT * FROM users WHERE id IN |" , lines[0 ])
610619 assertEquals(" [1, 2, 3]" , lines[1 ])
611620 }
621+
622+ // -- Multi-dollar string interpolation ($$) tests --
623+
624+ @Test
625+ fun `multi-dollar single interpolation is auto-wrapped` () {
626+ val source = SourceFile .kotlin(
627+ " Test.kt" ,
628+ """
629+ import st.orm.template.*
630+
631+ fun main() {
632+ val id = 42
633+ val builder: TemplateBuilder = { ${' $' }${' $' } "SELECT * FROM users WHERE id = ${' $' }${' $' } id" }
634+ val result = builder.build()
635+ println(result.fragments.joinToString("|"))
636+ println(result.values.joinToString(","))
637+ }
638+ """ ,
639+ )
640+ val result = compile(source, languageVersion = " 2.2" )
641+ assumeCompilationSuccess(result)
642+ val output = result.runMain()
643+ val lines = output.lines()
644+ assertEquals(" SELECT * FROM users WHERE id = |" , lines[0 ])
645+ assertEquals(" 42" , lines[1 ])
646+ }
647+
648+ @Test
649+ fun `multi-dollar literal dollar sign is preserved as fragment` () {
650+ val source = SourceFile .kotlin(
651+ " Test.kt" ,
652+ """
653+ import st.orm.template.*
654+
655+ fun main() {
656+ val id = 42
657+ val builder: TemplateBuilder = { ${' $' }${' $' } "SELECT * FROM users WHERE cost > ${' $' } 5 AND id = ${' $' }${' $' } id" }
658+ val result = builder.build()
659+ println(result.fragments.joinToString("|"))
660+ println(result.values.joinToString(","))
661+ }
662+ """ ,
663+ )
664+ val result = compile(source, languageVersion = " 2.2" )
665+ assumeCompilationSuccess(result)
666+ val output = result.runMain()
667+ val lines = output.lines()
668+ assertEquals(" SELECT * FROM users WHERE cost > ${' $' } 5 AND id = |" , lines[0 ])
669+ assertEquals(" 42" , lines[1 ])
670+ }
671+
672+ @Test
673+ fun `multi-dollar multiple interpolations are auto-wrapped` () {
674+ val source = SourceFile .kotlin(
675+ " Test.kt" ,
676+ """
677+ import st.orm.template.*
678+
679+ fun main() {
680+ val id = 42
681+ val status = "active"
682+ val builder: TemplateBuilder = { ${' $' }${' $' } "SELECT * FROM users WHERE id = ${' $' }${' $' } id AND status = ${' $' }${' $' } status" }
683+ val result = builder.build()
684+ println(result.fragments.joinToString("|"))
685+ println(result.values.joinToString(","))
686+ }
687+ """ ,
688+ )
689+ val result = compile(source, languageVersion = " 2.2" )
690+ assumeCompilationSuccess(result)
691+ val output = result.runMain()
692+ val lines = output.lines()
693+ assertEquals(" SELECT * FROM users WHERE id = | AND status = |" , lines[0 ])
694+ assertEquals(" 42,active" , lines[1 ])
695+ }
696+
697+ @Test
698+ fun `multi-dollar inline string constant is auto-wrapped` () {
699+ val source = SourceFile .kotlin(
700+ " Test.kt" ,
701+ """
702+ import st.orm.template.*
703+
704+ fun main() {
705+ val id = 42
706+ val builder: TemplateBuilder = { ${' $' }${' $' } "SELECT * FROM users WHERE id = ${' $' }${' $' } id AND email LIKE ${' $' }${' $' } {"%@gmail.com"}" }
707+ val result = builder.build()
708+ println(result.fragments.joinToString("|"))
709+ println(result.values.joinToString(","))
710+ }
711+ """ ,
712+ )
713+ val result = compile(source, languageVersion = " 2.2" )
714+ assumeCompilationSuccess(result)
715+ val output = result.runMain()
716+ val lines = output.lines()
717+ assertEquals(" SELECT * FROM users WHERE id = | AND email LIKE |" , lines[0 ])
718+ assertEquals(" 42,%@gmail.com" , lines[1 ])
719+ }
720+
721+ @Test
722+ fun `multi-dollar plain string literal is unchanged` () {
723+ val source = SourceFile .kotlin(
724+ " Test.kt" ,
725+ """
726+ import st.orm.template.*
727+
728+ fun main() {
729+ val builder: TemplateBuilder = { ${' $' }${' $' } "SELECT COUNT(*) FROM users" }
730+ val result = builder.build()
731+ println(result.fragments.joinToString("|"))
732+ println(result.values.size)
733+ }
734+ """ ,
735+ )
736+ val result = compile(source, languageVersion = " 2.2" )
737+ assumeCompilationSuccess(result)
738+ val output = result.runMain()
739+ val lines = output.lines()
740+ assertEquals(" SELECT COUNT(*) FROM users" , lines[0 ])
741+ assertEquals(" 0" , lines[1 ])
742+ }
612743}
0 commit comments