diff --git a/src/main/java/org/openrewrite/staticanalysis/UseTryWithResources.java b/src/main/java/org/openrewrite/staticanalysis/UseTryWithResources.java index 9405fb53d..99b92d069 100644 --- a/src/main/java/org/openrewrite/staticanalysis/UseTryWithResources.java +++ b/src/main/java/org/openrewrite/staticanalysis/UseTryWithResources.java @@ -25,6 +25,7 @@ import org.openrewrite.internal.ListUtils; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.marker.JavaVersion; import org.openrewrite.java.search.SemanticallyEqual; import org.openrewrite.java.search.UsesJavaVersion; import org.openrewrite.java.tree.*; @@ -69,6 +70,10 @@ public TreeVisitor getVisitor() { public J.Block visitBlock(J.Block block, ExecutionContext ctx) { J.Block b = super.visitBlock(block, ctx); List stmts = b.getStatements(); + boolean unnamedAvailable = getCursor().firstEnclosingOrThrow(JavaSourceFile.class) + .getMarkers().findFirst(JavaVersion.class) + .filter(v -> v.getMajorVersion() >= 21) + .isPresent(); return b.withStatements(ListUtils.map(stmts, (i, stmt) -> { if (stmt instanceof J.Try) { J.Try tryStmt = (J.Try) stmt; @@ -81,7 +86,7 @@ public J.Block visitBlock(J.Block block, ExecutionContext ctx) { if (usedAfter) { return transformJava9(prevDecl, tryStmt); } - return transform(prevDecl, tryStmt); + return transform(prevDecl, tryStmt, unnamedAvailable); } } @@ -169,10 +174,22 @@ private static boolean canTransform(J.VariableDeclarations varDecl, J.Try tryStm return true; } - private static J.Try transform(J.VariableDeclarations varDecl, J.Try tryStmt) { - return addResource(varDecl.withPrefix(Space.EMPTY), - varDecl.getVariables().get(0).getSimpleName(), - tryStmt.withPrefix(varDecl.getPrefix())); + private static J.Try transform(J.VariableDeclarations varDecl, J.Try tryStmt, boolean unnamedAvailable) { + String varName = varDecl.getVariables().get(0).getSimpleName(); + J.VariableDeclarations resourceDecl = varDecl.withPrefix(Space.EMPTY); + // When the resource is never read inside the try body, name it with the unnamed variable `_` + // (JEP 443 preview in Java 21, finalized as JEP 456 in Java 22) so the rewritten code does + // not emit an unused-variable warning that would fail `-Werror` builds. + if (unnamedAvailable && !isReferenced(varName, tryStmt.getBody())) { + J.VariableDeclarations.NamedVariable namedVar = resourceDecl.getVariables().get(0); + JavaType.Variable renamedType = namedVar.getVariableType() != null ? + namedVar.getVariableType().withName("_") : null; + J.Identifier renamedName = namedVar.getName().withSimpleName("_") + .withFieldType(renamedType); + resourceDecl = resourceDecl.withVariables(singletonList( + namedVar.withName(renamedName).withVariableType(renamedType))); + } + return addResource(resourceDecl, varName, tryStmt.withPrefix(varDecl.getPrefix())); } private static J.Try transformJava9(J.VariableDeclarations varDecl, J.Try tryStmt) { diff --git a/src/test/java/org/openrewrite/staticanalysis/UseTryWithResourcesTest.java b/src/test/java/org/openrewrite/staticanalysis/UseTryWithResourcesTest.java index 77e5154c6..4c4fe023e 100644 --- a/src/test/java/org/openrewrite/staticanalysis/UseTryWithResourcesTest.java +++ b/src/test/java/org/openrewrite/staticanalysis/UseTryWithResourcesTest.java @@ -649,6 +649,109 @@ void method(String path) throws IOException { ); } + @Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/927") + @Test + void unusedResourceUsesUnnamedVariableOnJava21() { + rewriteRun( + //language=java + java( + """ + import java.io.*; + + class Test { + void method() throws IOException { + InputStream in = new FileInputStream("file.txt"); + try { + } finally { + in.close(); + } + } + } + """, + """ + import java.io.*; + + class Test { + void method() throws IOException { + try (InputStream _ = new FileInputStream("file.txt")) { + } + } + } + """, + spec -> spec.markers(javaVersion(21)) + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/927") + @Test + void unusedResourceKeepsNameBelowJava21() { + rewriteRun( + //language=java + java( + """ + import java.io.*; + + class Test { + void method() throws IOException { + InputStream in = new FileInputStream("file.txt"); + try { + } finally { + in.close(); + } + } + } + """, + """ + import java.io.*; + + class Test { + void method() throws IOException { + try (InputStream in = new FileInputStream("file.txt")) { + } + } + } + """ + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-static-analysis/issues/927") + @Test + void resourceUsedInBodyKeepsNameOnJava21() { + rewriteRun( + //language=java + java( + """ + import java.io.*; + + class Test { + void method() throws IOException { + InputStream in = new FileInputStream("file.txt"); + try { + int data = in.read(); + } finally { + in.close(); + } + } + } + """, + """ + import java.io.*; + + class Test { + void method() throws IOException { + try (InputStream in = new FileInputStream("file.txt")) { + int data = in.read(); + } + } + } + """, + spec -> spec.markers(javaVersion(21)) + ) + ); + } + @Test void doNotChangeNonConsecutiveNullInitialized() { rewriteRun(