diff --git a/src/main/java/org/openrewrite/java/migrate/lang/var/DeclarationCheck.java b/src/main/java/org/openrewrite/java/migrate/lang/var/DeclarationCheck.java index 033295e02a..886b5da046 100644 --- a/src/main/java/org/openrewrite/java/migrate/lang/var/DeclarationCheck.java +++ b/src/main/java/org/openrewrite/java/migrate/lang/var/DeclarationCheck.java @@ -48,13 +48,25 @@ final class DeclarationCheck { * @return true if var is applicable in general */ public static boolean isVarApplicable(Cursor cursor, J.VariableDeclarations vd) { - if (isField(vd, cursor) || isMethodParameter(vd, cursor) || !isSingleVariableDefinition(vd) || initializedByTernary(vd)) { + if (isField(vd, cursor) || isMethodParameter(vd, cursor) || !isSingleVariableDefinition(vd) || + initializedByTernary(vd) || hasDimensionsAfterName(vd)) { return false; } return isInsideMethod(cursor) || isInsideInitializer(cursor, 0); } + /** + * Determine whether the declarator carries C-style array brackets after the variable name, as in {@code int a[]}. + * JLS 14.4.1 makes extra array dimensions on a {@code var} declarator a compile-time error. + * + * @param vd variable definition at hand + * @return true iff the variable name is followed by array dimensions + */ + private static boolean hasDimensionsAfterName(J.VariableDeclarations vd) { + return !vd.getVariables().get(0).getDimensionsAfterName().isEmpty(); + } + /** * Determine if a variable definition defines a single variable that is directly initialized with value different from null, which not make use of var. * diff --git a/src/main/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocations.java b/src/main/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocations.java index 5a38870a1d..ecdbdea889 100644 --- a/src/main/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocations.java +++ b/src/main/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocations.java @@ -87,6 +87,13 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations v return vd; } + // Only a qualified invocation can carry a type witness (JLS 15.12), so an unqualified call whose return + // type still mentions a type variable has no way to hold on to the type the declaration pinned down. + if (invocation.getSelect() == null && invocation.getTypeParameters() == null && + invocation.getMethodType() != null && containsGenericTypeVariable(invocation.getMethodType().getReturnType())) { + return vd; + } + if (vd.getType() instanceof JavaType.FullyQualified) { maybeRemoveImport((JavaType.FullyQualified) vd.getType()); } diff --git a/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocationsTest.java b/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocationsTest.java index 15f0bbe069..55193705b1 100644 --- a/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocationsTest.java +++ b/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForGenericMethodInvocationsTest.java @@ -56,6 +56,33 @@ void m() { ); } + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/1219") + @Test + void forUnqualifiedInvocationNeedingTypeWitness() { + // `var contentTypes = contentType(...)` would not parse; a type witness needs a receiver + //language=java + rewriteRun( + version( + java(""" + package com.example.app; + + import java.util.function.Predicate; + + class A { + static Predicate contentType(String... types) { + return null; + } + static Predicate binary() { + final Predicate contentTypes = contentType("application/octet-stream"); + return contentTypes; + } + } + """), + 10 + ) + ); + } + @Nested class NotSupportedByOpenRewrite { // this is possible because `myList()`s type is fixed to `List` but it is not distinguishable from diff --git a/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForPrimitiveTest.java b/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForPrimitiveTest.java index 4cd253436c..a5ad22f060 100644 --- a/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForPrimitiveTest.java +++ b/src/test/java/org/openrewrite/java/migrate/lang/var/UseVarForPrimitiveTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.openrewrite.DocumentExample; +import org.openrewrite.Issue; import org.openrewrite.test.RecipeSpec; import static org.openrewrite.java.Assertions.java; @@ -86,6 +87,25 @@ void m() { ); } + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/1218") + @Test + void forCStyleArrayDeclarator() { + //language=java + rewriteRun( + java( + """ + package com.example.app; + + class A { + void m() { + int address[] = new int[8]; + } + } + """ + ) + ); + } + @Test void forStringMethodCall() { //language=java