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 f105129558..f24f15ae8e 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..ec8ecbe602 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesEqualTo.java @@ -0,0 +1,87 @@ +/* + * 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.ShortenFullyQualifiedTypeReferences; +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"); + + 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)})") + .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/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); - } - } - """ - ) - ); - } } 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..ce24e41b21 --- /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"); - } - } - """ - ) - ); - } }