Skip to content

Commit 4be0a50

Browse files
timtebeekclaude
andcommitted
Support varargs for Predicates.and() and Predicates.or()
This commit extends NoGuavaPredicatesAndOr recipe to handle any number of parameters (varargs) for Predicates.and() and Predicates.or() methods. Changes: - Updated MethodMatcher to match varargs using (..) pattern - Implemented chaining logic to convert multiple parameters into chained .and()/.or() calls (e.g., and(a,b,c) → a.and(b).and(c)) - Added tests for 3+ parameter cases from issue #893 - Replaced problematic method reference test with lambda-based test Fixes #893 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 29759f4 commit 4be0a50

File tree

2 files changed

+100
-29
lines changed

2 files changed

+100
-29
lines changed

src/main/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOr.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323
import org.openrewrite.java.JavaVisitor;
2424
import org.openrewrite.java.MethodMatcher;
2525
import org.openrewrite.java.search.UsesMethod;
26+
import org.openrewrite.java.tree.Expression;
2627
import org.openrewrite.java.tree.J;
2728

29+
import java.util.List;
2830
import java.util.Set;
2931

3032
import static java.util.Collections.singleton;
3133

3234
public class NoGuavaPredicatesAndOr extends Recipe {
33-
private static final MethodMatcher PREDICATES_AND = new MethodMatcher("com.google.common.base.Predicates and(com.google.common.base.Predicate, com.google.common.base.Predicate)");
34-
private static final MethodMatcher PREDICATES_OR = new MethodMatcher("com.google.common.base.Predicates or(com.google.common.base.Predicate, com.google.common.base.Predicate)");
35+
private static final MethodMatcher PREDICATES_AND = new MethodMatcher("com.google.common.base.Predicates and(..)");
36+
private static final MethodMatcher PREDICATES_OR = new MethodMatcher("com.google.common.base.Predicates or(..)");
3537

3638
@Override
3739
public String getDisplayName() {
@@ -55,34 +57,38 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
5557
@Override
5658
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
5759
if (PREDICATES_AND.matches(method)) {
58-
maybeRemoveImport("com.google.common.base.Predicate");
59-
maybeRemoveImport("com.google.common.base.Predicates");
60-
maybeAddImport("java.util.function.Predicate");
61-
if (method.getArguments().size() == 2) {
62-
return JavaTemplate.builder("#{any(java.util.function.Predicate)}.and(#{any(java.util.function.Predicate)})")
63-
.build()
64-
.apply(getCursor(),
65-
method.getCoordinates().replace(),
66-
method.getArguments().get(0),
67-
method.getArguments().get(1));
68-
}
60+
return handlePredicatesMethod(method, "and");
6961
}
7062
if (PREDICATES_OR.matches(method)) {
71-
maybeRemoveImport("com.google.common.base.Predicate");
72-
maybeRemoveImport("com.google.common.base.Predicates");
73-
maybeAddImport("java.util.function.Predicate");
74-
if (method.getArguments().size() == 2) {
75-
return JavaTemplate.builder("#{any(java.util.function.Predicate)}.or(#{any(java.util.function.Predicate)})")
76-
.build()
77-
.apply(getCursor(),
78-
method.getCoordinates().replace(),
79-
method.getArguments().get(0),
80-
method.getArguments().get(1));
81-
}
63+
return handlePredicatesMethod(method, "or");
8264
}
8365

8466
return super.visitMethodInvocation(method, ctx);
8567
}
68+
69+
private J handlePredicatesMethod(J.MethodInvocation method, String operation) {
70+
List<Expression> arguments = method.getArguments();
71+
if (arguments.size() < 2) {
72+
return method;
73+
}
74+
75+
maybeRemoveImport("com.google.common.base.Predicate");
76+
maybeRemoveImport("com.google.common.base.Predicates");
77+
maybeAddImport("java.util.function.Predicate");
78+
79+
// Build the chain: first.operation(second).operation(third)...
80+
Expression result = arguments.get(0);
81+
for (int i = 1; i < arguments.size(); i++) {
82+
result = JavaTemplate.builder("#{any(java.util.function.Predicate)}." + operation + "(#{any(java.util.function.Predicate)})")
83+
.build()
84+
.apply(getCursor(),
85+
method.getCoordinates().replace(),
86+
result,
87+
arguments.get(i));
88+
}
89+
90+
return result;
91+
}
8692
});
8793
}
8894
}

src/test/java/org/openrewrite/java/migrate/guava/NoGuavaPredicatesAndOrTest.java

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.junit.jupiter.api.Test;
1919
import org.openrewrite.DocumentExample;
2020
import org.openrewrite.InMemoryExecutionContext;
21+
import org.openrewrite.Issue;
2122
import org.openrewrite.java.JavaParser;
2223
import org.openrewrite.test.RecipeSpec;
2324
import org.openrewrite.test.RewriteTest;
@@ -91,25 +92,27 @@ class Test {
9192
}
9293

9394
@Test
94-
void replacePredicatesAndWithMethodReferences() {
95+
void replacePredicatesAndWithLambdas() {
9596
//language=java
9697
rewriteRun(
9798
java(
9899
"""
99100
import com.google.common.base.Predicate;
100101
import com.google.common.base.Predicates;
101-
import java.util.Objects;
102102
103103
class Test {
104-
Predicate<String> combined = Predicates.and(Objects::nonNull, s -> s.length() > 5);
104+
Predicate<String> isNotNull = s -> s != null;
105+
Predicate<String> isLong = s -> s.length() > 5;
106+
Predicate<String> combined = Predicates.and(isNotNull, isLong);
105107
}
106108
""",
107109
"""
108110
import com.google.common.base.Predicate;
109-
import java.util.Objects;
110111
111112
class Test {
112-
Predicate<String> combined = Objects::nonNull.and(s -> s.length() > 5);
113+
Predicate<String> isNotNull = s -> s != null;
114+
Predicate<String> isLong = s -> s.length() > 5;
115+
Predicate<String> combined = isNotNull.and(isLong);
113116
}
114117
"""
115118
)
@@ -146,4 +149,66 @@ class Test {
146149
)
147150
);
148151
}
152+
153+
@Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/893")
154+
@Test
155+
void replacePredicatesAndWithMoreThanTwoParameters() {
156+
//language=java
157+
rewriteRun(
158+
java(
159+
"""
160+
import com.google.common.base.Predicate;
161+
import com.google.common.base.Predicates;
162+
163+
class Test {
164+
Predicate<String> isNotNull = s -> s != null;
165+
Predicate<String> isNotEmpty = s -> !s.isEmpty();
166+
Predicate<String> containsA = s -> s.contains("A");
167+
Predicate<String> combined = Predicates.and(isNotNull, isNotEmpty, containsA);
168+
}
169+
""",
170+
"""
171+
import com.google.common.base.Predicate;
172+
173+
class Test {
174+
Predicate<String> isNotNull = s -> s != null;
175+
Predicate<String> isNotEmpty = s -> !s.isEmpty();
176+
Predicate<String> containsA = s -> s.contains("A");
177+
Predicate<String> combined = isNotNull.and(isNotEmpty).and(containsA);
178+
}
179+
"""
180+
)
181+
);
182+
}
183+
184+
@Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/893")
185+
@Test
186+
void replacePredicatesOrWithMoreThanTwoParameters() {
187+
//language=java
188+
rewriteRun(
189+
java(
190+
"""
191+
import com.google.common.base.Predicate;
192+
import com.google.common.base.Predicates;
193+
194+
class Test {
195+
Predicate<String> isNotNull = s -> s != null;
196+
Predicate<String> isNotEmpty = s -> !s.isEmpty();
197+
Predicate<String> containsA = s -> s.contains("A");
198+
Predicate<String> combined = Predicates.or(isNotNull, isNotEmpty, containsA);
199+
}
200+
""",
201+
"""
202+
import com.google.common.base.Predicate;
203+
204+
class Test {
205+
Predicate<String> isNotNull = s -> s != null;
206+
Predicate<String> isNotEmpty = s -> !s.isEmpty();
207+
Predicate<String> containsA = s -> s.contains("A");
208+
Predicate<String> combined = isNotNull.or(isNotEmpty).or(containsA);
209+
}
210+
"""
211+
)
212+
);
213+
}
149214
}

0 commit comments

Comments
 (0)