From 587f7bd48cfd4b4c52a26adcb693a0d8ae7b4f03 Mon Sep 17 00:00:00 2001 From: Laurent Redor Date: Mon, 27 Oct 2025 18:04:11 +0100 Subject: [PATCH 1/3] Convert Guava `Predicates.equalTo` Fixes issue #903 --- .../migrate/guava/NoGuavaPredicatesAndOr.java | 3 +- .../guava/NoGuavaPredicatesEqualTo.java | 85 ++++++++++++++++ .../resources/META-INF/rewrite/no-guava.yml | 8 +- .../guava/NoGuavaPredicatesEqualToTest.java | 96 +++++++++++++++++++ .../guava/PreferJavaUtilPredicateTest.java | 28 ------ 5 files changed, 184 insertions(+), 36 deletions(-) create mode 100644 src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java create mode 100644 src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java index 61b9b9b11a..7b1335c061 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java @@ -35,6 +35,7 @@ public class NoGuavaPredicatesAndOr extends Recipe { private static final MethodMatcher PREDICATES_AND = new MethodMatcher("com.google.common.base.Predicates and(..)"); private static final MethodMatcher PREDICATES_OR = new MethodMatcher("com.google.common.base.Predicates or(..)"); + private static final MethodMatcher PREDICATES_EQUAL_TO = new MethodMatcher("com.google.common.base.Predicates equalTo(..)"); @Override public String getDisplayName() { @@ -79,7 +80,7 @@ private J handlePredicatesMethod(J.MethodInvocation method, String operation) { Expression result = arguments.get(0); // Avoid generic type issues by not making any changes just yet - if (result instanceof J.MethodInvocation) { + if (result instanceof J.MethodInvocation && !PREDICATES_EQUAL_TO.matches(result)) { return method; } diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java new file mode 100644 index 0000000000..b9a6524e21 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java @@ -0,0 +1,85 @@ +/* + * Copyright 2025 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.guava; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; + +import java.util.Set; + +import static java.util.Collections.singleton; + +public class NoGuavaPredicatesEqualTo extends Recipe { + private static final MethodMatcher PREDICATES_EQUAL_TO = new MethodMatcher("com.google.common.base.Predicates equalTo(..)"); + + @Override + public String getDisplayName() { + return "Prefer `Predicate.isEqual(Object)`"; + } + + @Override + public String getDescription() { + return "Prefer `Predicate.isEqual(Object)` over `Predicates.equalTo(Object)`."; + } + + @Override + public Set getTags() { + return singleton("guava"); + } + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check( + new UsesMethod<>(PREDICATES_EQUAL_TO), + new JavaIsoVisitor() { + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + if (PREDICATES_EQUAL_TO.matches(method)) { + maybeRemoveImport("com.google.common.base.Predicates"); + maybeAddImport("java.util.function.Predicate"); + + JavaType parameterType = method.getArguments().get(0).getType(); + if (parameterType != null) { + String typeString = parameterType.toString(); + return JavaTemplate.builder("Predicate.<" + typeString + ">isEqual(#{any(java.lang.Object)})") + .imports("java.util.function.Predicate") + .build() + .apply(getCursor(), + method.getCoordinates().replace(), + method.getArguments().get(0)); + } + // Fallback is not type is found. + return JavaTemplate.builder("Predicate.isEqual(#{any(java.lang.Object)})") + .imports("java.util.function.Predicate") + .build() + .apply(getCursor(), + method.getCoordinates().replace(), + method.getArguments().get(0)); + } + return super.visitMethodInvocation(method, ctx); + } + } + ); + } +} diff --git a/src/main/resources/META-INF/rewrite/no-guava.yml b/src/main/resources/META-INF/rewrite/no-guava.yml index 8684f621a2..aac89c1601 100644 --- a/src/main/resources/META-INF/rewrite/no-guava.yml +++ b/src/main/resources/META-INF/rewrite/no-guava.yml @@ -37,6 +37,7 @@ recipeList: - org.openrewrite.java.migrate.guava.NoGuavaListsNewLinkedList - org.openrewrite.java.migrate.guava.NoGuavaMapsNewTreeMap - org.openrewrite.java.migrate.guava.NoGuavaPredicatesAndOr + - org.openrewrite.java.migrate.guava.NoGuavaPredicatesEqualTo - org.openrewrite.java.migrate.guava.NoGuavaPrimitiveAsList - org.openrewrite.java.migrate.guava.NoGuavaRefasterRecipes - org.openrewrite.java.migrate.guava.NoGuavaMapsNewHashMap @@ -184,13 +185,6 @@ recipeList: methodPattern: com.google.common.base.Predicates not(com.google.common.base.Predicate) fullyQualifiedTargetTypeName: java.util.function.Predicate - - org.openrewrite.java.ChangeMethodName: - methodPattern: com.google.common.base.Predicates equalTo(..) - newMethodName: isEqual - - org.openrewrite.java.ChangeMethodTargetToStatic: - methodPattern: com.google.common.base.Predicates isEqual(..) - fullyQualifiedTargetTypeName: java.util.function.Predicate - - org.openrewrite.java.ChangeMethodName: methodPattern: com.google.common.base.Predicate apply(..) newMethodName: test diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java new file mode 100644 index 0000000000..d528cd1318 --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2025 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.guava; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.Issue; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class NoGuavaPredicatesEqualToTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .recipeFromResources("org.openrewrite.java.migrate.guava.NoGuava") + .parser(JavaParser.fromJavaVersion().classpathFromResources(new InMemoryExecutionContext(), "guava")); + } + + @DocumentExample + @Test + void predicatesEqualToToPredicateIsEqual() { + rewriteRun( + //language=java + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + class A { + public static Predicate isHelloPredicate() { + return Predicates.equalTo("hello"); + } + } + """, + """ + import java.util.function.Predicate; + + class A { + public static Predicate isHelloPredicate() { + return Predicate.isEqual("hello"); + } + } + """ + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/903") + @Test + void inlinedPredicatesEqualToToPredicateIsEqual() { + rewriteRun( + //language=java + java( + """ + import com.google.common.base.Predicates; + import com.google.common.base.Predicate; + + import java.util.Collection; + + class Test { + public static void test(Collection aCollection, Predicate> anotherPredicate) { + Predicate> combined = Predicates.and(Predicates.equalTo(aCollection), anotherPredicate); + } + } + """, + """ + import java.util.Collection; + import java.util.function.Predicate; + + class Test { + public static void test(Collection aCollection, Predicate> anotherPredicate) { + Predicate> combined = Predicate.>isEqual(aCollection).and(anotherPredicate); + } + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilPredicateTest.java b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilPredicateTest.java index 083d9838f0..43f5ef4685 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilPredicateTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilPredicateTest.java @@ -100,32 +100,4 @@ public static Predicate notEmptyPredicate() { ) ); } - - @Test - void predicatesEqualToToPredicateIsEqual() { - rewriteRun( - //language=java - java( - """ - import com.google.common.base.Predicate; - import com.google.common.base.Predicates; - - class A { - public static Predicate isHelloPredicate() { - return Predicates.equalTo("hello"); - } - } - """, - """ - import java.util.function.Predicate; - - class A { - public static Predicate isHelloPredicate() { - return Predicate.isEqual("hello"); - } - } - """ - ) - ); - } } From 2fd70ff16b1db87a20dd2b7ecef68c0872945b05 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Mon, 27 Oct 2025 18:54:24 +0100 Subject: [PATCH 2/3] Tweak when to add type argument to method --- .../java/migrate/guava/NoGuavaPredicatesEqualTo.java | 10 ++++++---- .../migrate/guava/NoGuavaPredicatesEqualToTest.java | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java index b9a6524e21..ec8ecbe602 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java @@ -22,6 +22,7 @@ import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.ShortenFullyQualifiedTypeReferences; import org.openrewrite.java.search.UsesMethod; import org.openrewrite.java.tree.J; import org.openrewrite.java.tree.JavaType; @@ -59,15 +60,16 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu maybeRemoveImport("com.google.common.base.Predicates"); maybeAddImport("java.util.function.Predicate"); - JavaType parameterType = method.getArguments().get(0).getType(); - if (parameterType != null) { - String typeString = parameterType.toString(); - return JavaTemplate.builder("Predicate.<" + typeString + ">isEqual(#{any(java.lang.Object)})") + if (method.getMethodType().getParameterTypes().get(0) instanceof JavaType.Parameterized) { + String typeString = method.getArguments().get(0).getType().toString(); + J.MethodInvocation genericMethod = JavaTemplate.builder("Predicate.<" + typeString + ">isEqual(#{any(java.lang.Object)})") .imports("java.util.function.Predicate") .build() .apply(getCursor(), method.getCoordinates().replace(), method.getArguments().get(0)); + doAfterVisit(ShortenFullyQualifiedTypeReferences.modifyOnly(genericMethod)); + return genericMethod; } // Fallback is not type is found. return JavaTemplate.builder("Predicate.isEqual(#{any(java.lang.Object)})") diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java index d528cd1318..ce24e41b21 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualToTest.java @@ -54,7 +54,7 @@ public static Predicate isHelloPredicate() { class A { public static Predicate isHelloPredicate() { - return Predicate.isEqual("hello"); + return Predicate.isEqual("hello"); } } """ From 7fb928820e84ded11295b74b6491660f5a17f917 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Mon, 27 Oct 2025 19:09:27 +0100 Subject: [PATCH 3/3] Remove test fixed in subsequent recipe --- .../guava/NoGuavaPredicatesAndOrTest.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java index 799a8b94ff..b4af99432d 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java @@ -257,29 +257,4 @@ class Test { ) ); } - - @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/903") - @Test - void doNotConvertPredicatesEqualToWhenUsedInMethodChain() { - // Converting Predicates.equalTo() to Predicate.isEqual() breaks type inference when chained with .and() - // The issue is that Predicate.isEqual() returns Predicate which causes compilation errors - // when chained with other methods - rewriteRun( - //language=java - java( - """ - import com.google.common.base.Predicate; - import com.google.common.base.Predicates; - import java.util.Collection; - - class A { - public static Predicate> combinedPredicate(Collection aCollection) { - Predicate> anotherPredicate = c -> !c.isEmpty(); - return Predicates.and(Predicates.equalTo(aCollection), anotherPredicate); - } - } - """ - ) - ); - } }