From 62c599cdea07c2204de8c491942a6813e4a32cfd Mon Sep 17 00:00:00 2001 From: martinfrancois Date: Tue, 11 Aug 2026 20:22:23 +0200 Subject: [PATCH] JavaTemplate: add failing tests for literal #{ in template source `hashBraceInStringLiteral` pins that a raw `#{` spliced into template source throws "The parameter foo must be defined before it is referenced". `escapedHashBraceInStringLiteral` pins that the `\#{` escape supported by PropertyPlaceholderHelper is undone by the fixed-point loop in Substitutions. Both are marked @ExpectedToFail until an escape survives. --- .../java/JavaTemplateSubstitutionsTest.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java index 0805f294db5..7a0f78ffbbc 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java @@ -16,6 +16,7 @@ package org.openrewrite.java; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ExpectedToFail; import org.openrewrite.DocumentExample; import org.openrewrite.ExecutionContext; import org.openrewrite.Issue; @@ -336,6 +337,68 @@ public class Test { ); } + @ExpectedToFail("JavaTemplate has no escape for a literal #{ in template source") + @Issue("https://github.com/openrewrite/rewrite-static-analysis/pull/976") + @Test + void hashBraceInStringLiteral() { + rewriteRun( + spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { + @Override + public J visitLiteral(J.Literal literal, ExecutionContext ctx) { + if ("placeholder".equals(literal.getValue())) { + return JavaTemplate.builder("\"#{foo}\"") + .build() + .apply(getCursor(), literal.getCoordinates().replace()); + } + return super.visitLiteral(literal, ctx); + } + })), + java( + """ + public class Test { + String s = "placeholder"; + } + """, + """ + public class Test { + String s = "#{foo}"; + } + """ + ) + ); + } + + @ExpectedToFail("Substitutions loops replacePlaceholders to a fixed point, so the #{ unescaped in pass 1 is re-parsed as a placeholder in pass 2") + @Issue("https://github.com/openrewrite/rewrite-static-analysis/pull/976") + @Test + void escapedHashBraceInStringLiteral() { + rewriteRun( + spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { + @Override + public J visitLiteral(J.Literal literal, ExecutionContext ctx) { + if ("placeholder".equals(literal.getValue())) { + return JavaTemplate.builder("\"\\#{foo}\"") + .build() + .apply(getCursor(), literal.getCoordinates().replace()); + } + return super.visitLiteral(literal, ctx); + } + })), + java( + """ + public class Test { + String s = "placeholder"; + } + """, + """ + public class Test { + String s = "#{foo}"; + } + """ + ) + ); + } + @Issue("https://github.com/openrewrite/rewrite/issues/1985") @Test void newArray() {