From 7444d1c3321b487d940894afecc1200822b0d1e8 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Fri, 27 Dec 2024 13:54:35 +0100 Subject: [PATCH] JavaTemplate bug when inserting `final var` into for-each (#4806) * JavaTemplate bug when inserting `final var` into for-each * Split variable declarations when they contain stop comment --- .../openrewrite/java/JavaTemplateTest.java | 47 ++++++++++++++++++- .../BlockStatementTemplateGenerator.java | 17 ++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java index 25e1e314f6f..cc2041f7236 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java @@ -72,7 +72,7 @@ void assignmentWithinIfPredicate() { @Override public J.Assignment visitAssignment(J.Assignment assignment, ExecutionContext ctx) { if ((assignment.getAssignment() instanceof J.Literal) && - ((J.Literal) assignment.getAssignment()).getValue().equals(1)) { + ((J.Literal) assignment.getAssignment()).getValue().equals(1)) { return JavaTemplate.builder("value = 0") .contextSensitive() .build() @@ -1351,7 +1351,7 @@ void replaceMethodArgumentsInIfStatementWithoutBraces() { public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { J.MethodInvocation mi = super.visitMethodInvocation(method, ctx); if (new MethodMatcher("Foo bar(..)").matches(mi) && - mi.getArguments().get(0) instanceof J.Binary) { + mi.getArguments().get(0) instanceof J.Binary) { return JavaTemplate.builder("\"Hello, {}\", \"World!\"") .contextSensitive() .build() @@ -1382,4 +1382,47 @@ void foo(boolean condition) { ) ); } + + @Test + void replaceVariableDeclarationWithFinalVar() { + rewriteRun( + spec -> spec.recipe(toRecipe(() -> new JavaIsoVisitor<>() { + @Override + public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { + J.VariableDeclarations vd = super.visitVariableDeclarations(multiVariable, ctx); + if (TypeUtils.isString(vd.getType()) && "String".equals(((J.Identifier) vd.getTypeExpression()).getSimpleName())) { + JavaCoordinates coordinates = vd.getCoordinates().replace(); + return JavaTemplate.builder("final var #{}") + .contextSensitive() + .doBeforeParseTemplate(System.out::println) + .build() + .apply(getCursor(), coordinates, new Object[]{vd.getVariables().get(0).getSimpleName()}); + } + return vd; + } + })), + java( + """ + import java.util.List; + import java.util.ArrayList; + + class A { + void bar(List lst) { + for (String s : lst) {} + } + } + """, + """ + import java.util.List; + import java.util.ArrayList; + + class A { + void bar(List lst) { + for (final var s : lst) {} + } + } + """ + ) + ); + } } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/internal/template/BlockStatementTemplateGenerator.java b/rewrite-java/src/main/java/org/openrewrite/java/internal/template/BlockStatementTemplateGenerator.java index f0f22eceff2..1dedaf9ea3d 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/internal/template/BlockStatementTemplateGenerator.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/internal/template/BlockStatementTemplateGenerator.java @@ -25,6 +25,7 @@ import org.openrewrite.Cursor; import org.openrewrite.SourceFile; import org.openrewrite.Tree; +import org.openrewrite.internal.ListUtils; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.tree.*; @@ -409,7 +410,7 @@ private void contextTemplate(Cursor cursor, J prior, StringBuilder before, Strin } else if (j instanceof J.ForEachLoop.Control) { J.ForEachLoop.Control c = (J.ForEachLoop.Control) j; if (referToSameElement(prior, c.getVariable())) { - after.append(" = /*" + STOP_COMMENT + "/*").append(c.getIterable().printTrimmed(cursor)); + after.append(" = /*" + STOP_COMMENT + "*/").append(c.getIterable().printTrimmed(cursor)); } else if (referToSameElement(prior, c.getIterable())) { before.insert(0, "Object __b" + cursor.getPathAsStream().count() + "__ ="); after.append(";"); @@ -818,6 +819,20 @@ public J visitMethodInvocation(J.MethodInvocation method, Integer integer) { } return mi; } + + @Override + public J visitVariableDeclarations(J.VariableDeclarations multiVariable, Integer integer) { + List variables = multiVariable.getVariables(); + for (J.VariableDeclarations.NamedVariable variable : variables) { + J.VariableDeclarations.NamedVariable.Padding padding = variable.getPadding(); + if (padding.getInitializer() != null && stopCommentExists(padding.getInitializer().getBefore().getComments())) { + // Split the variable declarations at the variable with the `STOP_COMMENT` & trim off initializer + List vars = variables.subList(0, variables.indexOf(variable) + 1); + return multiVariable.withVariables(ListUtils.mapLast(vars, v -> v.withInitializer(null))); + } + } + return super.visitVariableDeclarations(multiVariable, integer); + } } } }