diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVar.java b/src/main/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVar.java
index 2ba6a51c4b..821f9c2f94 100644
--- a/src/main/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVar.java
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVar.java
@@ -19,17 +19,19 @@
import org.openrewrite.*;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaIsoVisitor;
-import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.search.MaybeUsesImport;
import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.service.AnnotationService;
import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.Space;
import org.openrewrite.java.tree.TypeTree;
import org.openrewrite.java.tree.TypeUtils;
+import org.openrewrite.marker.Markers;
import java.time.Duration;
import java.util.Set;
+import static java.util.Collections.emptyList;
import static java.util.Collections.singleton;
public class LombokValToFinalVar extends Recipe {
@@ -79,27 +81,32 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m
(varDecls.getTypeExpression() instanceof J.Identifier && "val".equals(((J.Identifier) varDecls.getTypeExpression()).getSimpleName()))) {
maybeRemoveImport(LOMBOK_VAL);
- J.VariableDeclarations.NamedVariable nv = mv.getVariables().get(0);
+ // Manually transform to `var`, rather than using a JavaTemplate, so that the initializer
+ // is carried over untouched; reprinting it can lose type information, such as the type
+ // variable in a cast like `(T) o`.
+ J.VariableDeclarations.NamedVariable nv = varDecls.getVariables().get(0);
+ TypeTree typeExpression = varDecls.getTypeExpression();
+ J.Identifier varType = new J.Identifier(Tree.randomId(),
+ typeExpression.getPrefix(),
+ typeExpression.getMarkers(),
+ service(AnnotationService.class).getAllAnnotations(getCursor()),
+ "var",
+ nv.getType(),
+ null);
if (nv.getInitializer() == null) {
- // manually transform to var, as val in this case has no sufficient type information
- // and the java template parsing would fail, see https://github.com/openrewrite/rewrite/pull/5637
- TypeTree typeExpression = varDecls.getTypeExpression();
- J.Identifier varType = new J.Identifier(Tree.randomId(),
- typeExpression.getPrefix(),
- typeExpression.getMarkers(),
- service(AnnotationService.class).getAllAnnotations(getCursor()),
- "var",
- nv.getType(),
- null);
+ // `val` in this case has no sufficient type information, so it becomes a plain `var`,
+ // see https://github.com/openrewrite/rewrite/pull/5637
return varDecls.withTypeExpression(varType);
}
- varDecls = JavaTemplate.builder("final var #{} = #{any()};")
- .contextSensitive()
- .build()
- .apply(updateCursor(varDecls), varDecls.getCoordinates().replace(), nv.getSimpleName(), nv.getInitializer());
- varDecls = varDecls.withVariables(ListUtils.map(varDecls.getVariables(), namedVar -> namedVar
- .withInitializer(namedVar.getInitializer().withPrefix(nv.getInitializer().getPrefix()))));
+ if (varDecls.getModifiers().stream().noneMatch(m -> m.getType() == J.Modifier.Type.Final)) {
+ varDecls = varDecls.withModifiers(ListUtils.concat(
+ new J.Modifier(Tree.randomId(), typeExpression.getPrefix(), Markers.EMPTY,
+ null, J.Modifier.Type.Final, emptyList()),
+ varDecls.getModifiers()));
+ varType = varType.withPrefix(Space.SINGLE_SPACE);
+ }
+ varDecls = varDecls.withTypeExpression(varType);
}
return varDecls;
}
diff --git a/src/test/java/org/openrewrite/java/migrate/UpgradeToJava25Test.java b/src/test/java/org/openrewrite/java/migrate/UpgradeToJava25Test.java
index c48df08575..6b7fd95cd0 100644
--- a/src/test/java/org/openrewrite/java/migrate/UpgradeToJava25Test.java
+++ b/src/test/java/org/openrewrite/java/migrate/UpgradeToJava25Test.java
@@ -115,7 +115,7 @@ void upgradesMavenPluginsForJava25() {
spec -> spec.after(actual ->
assertThat(actual)
.contains("25")
- .containsPattern("maven-compiler-plugin\\s*3\\.15\\.")
+ .containsPattern("maven-compiler-plugin\\s*3\\.(1[5-9]|[2-9]\\d)\\.")
.containsPattern("maven-surefire-plugin\\s*3\\.5\\.")
.containsPattern("maven-failsafe-plugin\\s*3\\.5\\.")
.contains("-javaagent:${org.mockito:mockito-core:jar}")
diff --git a/src/test/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVarTest.java b/src/test/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVarTest.java
index bd4c93226f..2a215d0316 100755
--- a/src/test/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVarTest.java
+++ b/src/test/java/org/openrewrite/java/migrate/lombok/LombokValToFinalVarTest.java
@@ -511,4 +511,58 @@ void bar() {
)
);
}
+
+ @Test
+ void preserveCast() {
+ //language=java
+ rewriteRun(
+ version(
+ java(
+ """
+ import lombok.val;
+ class CastDemo {
+ void bar() {
+ val foo = (String) "foo";
+ }
+ }
+ """,
+ """
+ class CastDemo {
+ void bar() {
+ final var foo = (String) "foo";
+ }
+ }
+ """
+ ),
+ 17
+ )
+ );
+ }
+
+ @Test
+ void preserveGenericCast() {
+ //language=java
+ rewriteRun(
+ version(
+ java(
+ """
+ import lombok.val;
+ class GenericCastDemo {
+ void bar(Object o) {
+ val foo = (T) o;
+ }
+ }
+ """,
+ """
+ class GenericCastDemo {
+ void bar(Object o) {
+ final var foo = (T) o;
+ }
+ }
+ """
+ ),
+ 17
+ )
+ );
+ }
}