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 f24f15ae8e..fbf4df3d20 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java @@ -26,7 +26,10 @@ import org.openrewrite.java.search.UsesMethod; import org.openrewrite.java.tree.Expression; import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.TypeUtils; +import java.util.Arrays; import java.util.List; import java.util.Set; @@ -35,7 +38,8 @@ 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(..)"); + private static final List PREDICATES_METHODS_HANDLED = Arrays.asList(new MethodMatcher("com.google.common.base.Predicates equalTo(..)"), + PREDICATES_AND, PREDICATES_OR, new MethodMatcher("com.google.common.base.Predicates not(..)")); @Override public String getDisplayName() { @@ -74,17 +78,17 @@ private J handlePredicatesMethod(J.MethodInvocation method, String operation) { return method; } + // Avoid generic type issues, for method of "com.google.common.base.Predicates", by not making any changes just yet + if (atLeastOneArgumentIsMethodInvocationOfPredicates(arguments)) { + return method; + } + maybeRemoveImport("com.google.common.base.Predicates"); // Build the chain: first.operation(second).operation(third)... Expression result = arguments.get(0); - // Avoid generic type issues by not making any changes just yet - if (result instanceof J.MethodInvocation && !PREDICATES_EQUAL_TO.matches(result)) { - return method; - } - - // If the first argument is a method reference or a lambda, wrap it with a cast + // If the first argument is a method reference or a lambda, wrap it with a cast if ((result instanceof J.MemberReference || result instanceof J.Lambda) && result.getType() != null) { String typeString = result.getType().toString().replace("com.google.common.base.", ""); result = JavaTemplate.apply("((" + typeString + ") #{any()})", getCursor(), method.getCoordinates().replace(), result); @@ -100,4 +104,29 @@ private J handlePredicatesMethod(J.MethodInvocation method, String operation) { }); } + + private boolean atLeastOneArgumentIsMethodInvocationOfPredicates(List arguments) { + for (Expression expression : arguments) { + if (expression instanceof J.MethodInvocation) { + if (!isMethodHandled((J.MethodInvocation) expression)) { + JavaType.Method methodType = ((J.MethodInvocation) expression).getMethodType(); + if (methodType != null) { + if (TypeUtils.isOfClassType(methodType.getDeclaringType(), "com.google.common.base.Predicates")) { + return true; + } + } + } + } + } + return false; + } + + private boolean isMethodHandled(J.MethodInvocation methodInvocation) { + for (MethodMatcher methodMatcher : PREDICATES_METHODS_HANDLED) { + if (methodMatcher.matches(methodInvocation)) { + return true; + } + } + return false; + } } 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 b4af99432d..04dfd6205e 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java @@ -196,6 +196,37 @@ class Test { ); } + @Test + void replacePredicatesOrNestedCalls() { + //language=java + rewriteRun( + spec -> spec.expectedCyclesThatMakeChanges(2), + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + class Test { + Predicate isPositive = n -> n > 0; + Predicate isEven = n -> n % 2 == 0; + Predicate isLessThan100 = n -> n < 100; + Predicate combined = Predicates.and(isPositive, Predicates.or(isEven, isLessThan100)); + } + """, + """ + import com.google.common.base.Predicate; + + class Test { + Predicate isPositive = n -> n > 0; + Predicate isEven = n -> n % 2 == 0; + Predicate isLessThan100 = n -> n < 100; + Predicate combined = isPositive.and(isEven.or(isLessThan100)); + } + """ + ) + ); + } + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/893") @Test void replacePredicatesAndWithMoreThanTwoParameters() { @@ -257,4 +288,183 @@ class Test { ) ); } + + @Test + void replacePredicatesAndWithOtherClassMethodAsParameters() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() > 5; + } + Predicate combined = Predicates.and(getNotNullPredicate(), getMaxLengthPredicate()); + } + """, + """ + import com.google.common.base.Predicate; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() > 5; + } + Predicate combined = getNotNullPredicate().and(getMaxLengthPredicate()); + } + """ + ) + ); + } + + @Test + void replacePredicatesAndWithNotMethodAsParameters() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() > 5; + } + Predicate combined = Predicates.and(Predicates.not(getNotNullPredicate()), getMaxLengthPredicate()); + } + """, + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() > 5; + } + Predicate combined = Predicates.not(getNotNullPredicate()).and(getMaxLengthPredicate()); + } + """ + ) + ); + } + + + @Test + void replacePredicatesAndWithEqualToMethodAsParameters() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() < 10; + } + Predicate combined = Predicates.and(Predicates.equalTo("MyTest"), getMaxLengthPredicate()); + } + """, + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + import java.util.Objects; + + class Test { + Predicate getNotNullPredicate() { + return Objects::nonNull; + } + Predicate getMaxLengthPredicate() { + return s -> s.length() < 10; + } + Predicate combined = Predicates.equalTo("MyTest").and(getMaxLengthPredicate()); + } + """ + ) + ); + } + + @Test + void doNotReplacePredicatesAndWithNotHandledPredicatesMethodAsFirstParameter() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + import java.util.Collection; + import java.util.Objects; + + class Test { + Predicate getMinSizePredicate() { + return new Predicate() { + @Override + public boolean apply(String input) { + return input.length() > 5; + } + }; + } + + public void test(Collection aCollection) { + Predicate combined = Predicates.and(Predicates.in(aCollection), getMinSizePredicate()); + } + } + """ + ) + ); + } + + @Test + void doNotReplacePredicatesAndWithNotHandledPredicatesMethodAsSecondParameter() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + import java.util.Collection; + import java.util.Objects; + + class Test { + Predicate getMinSizePredicate() { + return new Predicate() { + @Override + public boolean apply(String input) { + return input.length() > 5; + } + }; + } + + public void test(Collection aCollection) { + Predicate combined = Predicates.and(getMinSizePredicate(), Predicates.in(aCollection)); + } + } + """ + ) + ); + } }