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 453fc76972..8bd7a9d28b 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java @@ -22,16 +22,19 @@ import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.ShortenFullyQualifiedTypeReferences; import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.Expression; import org.openrewrite.java.tree.J; +import java.util.List; import java.util.Set; import static java.util.Collections.singleton; public class NoGuavaPredicatesAndOr extends Recipe { - private static final MethodMatcher PREDICATES_AND = new MethodMatcher("com.google.common.base.Predicates and(com.google.common.base.Predicate, com.google.common.base.Predicate)"); - private static final MethodMatcher PREDICATES_OR = new MethodMatcher("com.google.common.base.Predicates or(com.google.common.base.Predicate, com.google.common.base.Predicate)"); + 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(..)"); @Override public String getDisplayName() { @@ -55,34 +58,40 @@ public TreeVisitor getVisitor() { @Override public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { if (PREDICATES_AND.matches(method)) { - maybeRemoveImport("com.google.common.base.Predicate"); - maybeRemoveImport("com.google.common.base.Predicates"); - maybeAddImport("java.util.function.Predicate"); - if (method.getArguments().size() == 2) { - return JavaTemplate.builder("#{any(java.util.function.Predicate)}.and(#{any(java.util.function.Predicate)})") - .build() - .apply(getCursor(), - method.getCoordinates().replace(), - method.getArguments().get(0), - method.getArguments().get(1)); - } + return handlePredicatesMethod(method, "and"); } if (PREDICATES_OR.matches(method)) { - maybeRemoveImport("com.google.common.base.Predicate"); - maybeRemoveImport("com.google.common.base.Predicates"); - maybeAddImport("java.util.function.Predicate"); - if (method.getArguments().size() == 2) { - return JavaTemplate.builder("#{any(java.util.function.Predicate)}.or(#{any(java.util.function.Predicate)})") - .build() - .apply(getCursor(), - method.getCoordinates().replace(), - method.getArguments().get(0), - method.getArguments().get(1)); - } + return handlePredicatesMethod(method, "or"); } return super.visitMethodInvocation(method, ctx); } + + private J handlePredicatesMethod(J.MethodInvocation method, String operation) { + List arguments = method.getArguments(); + if (arguments.size() < 2) { + return method; + } + + maybeRemoveImport("com.google.common.base.Predicates"); + + // Build the chain: first.operation(second).operation(third)... + Expression result = arguments.get(0); + + // If the first argument is a method reference, wrap it with a cast + if (result instanceof J.MemberReference && result.getType() != null) { + String typeString = result.getType().toString().replace("com.google.common.base.", ""); + result = JavaTemplate.apply("((" + typeString + ") #{any()})", getCursor(), method.getCoordinates().replace(), result); + } + for (int i = 1; i < arguments.size(); i++) { + result = JavaTemplate.apply("#{any(java.util.function.Predicate)}." + operation + "(#{any(java.util.function.Predicate)})", + getCursor(), method.getCoordinates().replace(), result, arguments.get(i)); + } + + doAfterVisit(ShortenFullyQualifiedTypeReferences.modifyOnly(result)); + return result; + } + }); } } 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 2589d40a88..116be23367 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java @@ -18,6 +18,7 @@ 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; @@ -91,7 +92,35 @@ class Test { } @Test - void replacePredicatesAndWithMethodReferences() { + void replacePredicatesAndWithLambdas() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isLong = s -> s.length() > 5; + Predicate combined = Predicates.and(isNotNull, isLong); + } + """, + """ + import com.google.common.base.Predicate; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isLong = s -> s.length() > 5; + Predicate combined = isNotNull.and(isLong); + } + """ + ) + ); + } + + @Test + void replacePredicatesAndWithMethodReference() { //language=java rewriteRun( java( @@ -109,7 +138,7 @@ class Test { import java.util.Objects; class Test { - Predicate combined = Objects::nonNull.and(s -> s.length() > 5); + Predicate combined = ((Predicate) Objects::nonNull).and(s -> s.length() > 5); } """ ) @@ -146,4 +175,66 @@ class Test { ) ); } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/893") + @Test + void replacePredicatesAndWithMoreThanTwoParameters() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isNotEmpty = s -> !s.isEmpty(); + Predicate containsA = s -> s.contains("A"); + Predicate combined = Predicates.and(isNotNull, isNotEmpty, containsA); + } + """, + """ + import com.google.common.base.Predicate; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isNotEmpty = s -> !s.isEmpty(); + Predicate containsA = s -> s.contains("A"); + Predicate combined = isNotNull.and(isNotEmpty).and(containsA); + } + """ + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/893") + @Test + void replacePredicatesOrWithMoreThanTwoParameters() { + //language=java + rewriteRun( + java( + """ + import com.google.common.base.Predicate; + import com.google.common.base.Predicates; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isNotEmpty = s -> !s.isEmpty(); + Predicate containsA = s -> s.contains("A"); + Predicate combined = Predicates.or(isNotNull, isNotEmpty, containsA); + } + """, + """ + import com.google.common.base.Predicate; + + class Test { + Predicate isNotNull = s -> s != null; + Predicate isNotEmpty = s -> !s.isEmpty(); + Predicate containsA = s -> s.contains("A"); + Predicate combined = isNotNull.or(isNotEmpty).or(containsA); + } + """ + ) + ); + } }