The IR transformer reads the source file from disk to split constants the compiler already folded (storm-compiler-plugin/src/main/kotlin-transformer-2.2/st/orm/kotlin/plugin/StormTemplateIrTransformer.kt:91-95, catch to null), and splitMergedConstant (:273-358) has four silent-bail paths triggered by escape sequences (:303-305, :320-322, :327-330, :346-348). When one bails, e.g. for "a\nb${"c"}d", the interpolation stays SQL text instead of becoming a bind value, and the autoInterpolation() marker is still injected, so the runtime backstop believes the template was fully processed.
No test covers any of these branches, and the classification heuristics (isFragment at :244-248, isOperatorConcatenation at :216-220) are offset arithmetic with the same silent failure mode.
A bail must be either safe (treat the unsplittable interpolation as a value, never as text) or loud (compiler warning/error naming the expression). Add tests for escape sequences inside merged constants across all transformer variants.
The IR transformer reads the source file from disk to split constants the compiler already folded (
storm-compiler-plugin/src/main/kotlin-transformer-2.2/st/orm/kotlin/plugin/StormTemplateIrTransformer.kt:91-95,catchto null), andsplitMergedConstant(:273-358) has four silent-bail paths triggered by escape sequences (:303-305,:320-322,:327-330,:346-348). When one bails, e.g. for"a\nb${"c"}d", the interpolation stays SQL text instead of becoming a bind value, and theautoInterpolation()marker is still injected, so the runtime backstop believes the template was fully processed.No test covers any of these branches, and the classification heuristics (
isFragmentat:244-248,isOperatorConcatenationat:216-220) are offset arithmetic with the same silent failure mode.A bail must be either safe (treat the unsplittable interpolation as a value, never as text) or loud (compiler warning/error naming the expression). Add tests for escape sequences inside merged constants across all transformer variants.