Skip to content

Commit 634e7d9

Browse files
Support copyOf migration for Guava (#1062)
* Add copyOf migration * recipes.csv
1 parent bb638a2 commit 634e7d9

9 files changed

Lines changed: 1170 additions & 11 deletions

File tree

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
*/
1616
package org.openrewrite.java.migrate.guava;
1717

18-
import lombok.AccessLevel;
1918
import lombok.Getter;
20-
import lombok.RequiredArgsConstructor;
2119
import org.jspecify.annotations.Nullable;
2220
import org.openrewrite.*;
2321
import org.openrewrite.internal.ListUtils;
@@ -35,11 +33,12 @@
3533

3634
import static java.util.Collections.emptyList;
3735

38-
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
3936
abstract class AbstractNoGuavaImmutableOf extends Recipe {
4037

4138
private final String guavaType;
4239
private final String javaType;
40+
private final String methodName;
41+
private final int minJavaVersion;
4342

4443
@Option(displayName = "Whether to convert return type (the default value is false).",
4544
description = "converting the return type from Guava Type to Java Type " +
@@ -49,9 +48,23 @@ abstract class AbstractNoGuavaImmutableOf extends Recipe {
4948
@Nullable
5049
Boolean convertReturnType;
5150

51+
AbstractNoGuavaImmutableOf(String guavaType, String javaType) {
52+
this(guavaType, javaType, "of", 9, null);
53+
}
54+
5255
AbstractNoGuavaImmutableOf(String guavaType, String javaType, @Nullable Boolean convertReturnType) {
56+
this(guavaType, javaType, "of", 9, convertReturnType);
57+
}
58+
59+
AbstractNoGuavaImmutableOf(String guavaType, String javaType, String methodName, int minJavaVersion) {
60+
this(guavaType, javaType, methodName, minJavaVersion, null);
61+
}
62+
63+
AbstractNoGuavaImmutableOf(String guavaType, String javaType, String methodName, int minJavaVersion, @Nullable Boolean convertReturnType) {
5364
this.guavaType = guavaType;
5465
this.javaType = javaType;
66+
this.methodName = methodName;
67+
this.minJavaVersion = minJavaVersion;
5568
this.convertReturnType = convertReturnType;
5669
}
5770

@@ -61,22 +74,22 @@ private String getShortType(String fullyQualifiedType) {
6174

6275
@Override
6376
public String getDisplayName() {
64-
return "Prefer `" + getShortType(javaType) + ".of(..)` in Java 9 or higher";
77+
return "Prefer `" + getShortType(javaType) + "." + methodName + "(..)` in Java " + minJavaVersion + " or higher";
6578
}
6679

6780
@Override
6881
public String getDescription() {
69-
return "Replaces `" + getShortType(guavaType) + ".of(..)` if the returned type is immediately down-cast.";
82+
return "Replaces `" + getShortType(guavaType) + "." + methodName + "(..)` if the returned type is immediately down-cast.";
7083
}
7184

7285
@Getter
7386
final Duration estimatedEffortPerOccurrence = Duration.ofMinutes( 10 );
7487

7588
@Override
7689
public TreeVisitor<?, ExecutionContext> getVisitor() {
77-
TreeVisitor<?, ExecutionContext> check = Preconditions.and(new UsesJavaVersion<>(9),
90+
TreeVisitor<?, ExecutionContext> check = Preconditions.and(new UsesJavaVersion<>(minJavaVersion),
7891
new UsesType<>(guavaType, false));
79-
final MethodMatcher IMMUTABLE_MATCHER = new MethodMatcher(guavaType + " of(..)");
92+
final MethodMatcher IMMUTABLE_MATCHER = new MethodMatcher(guavaType + " " + methodName + "(..)");
8093
return Preconditions.check(check, new JavaVisitor<ExecutionContext>() {
8194
@Override
8295
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
@@ -91,13 +104,13 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx)
91104
Object[] templateArguments;
92105
List<Expression> methodArguments = mi.getArguments();
93106
if (methodArguments.isEmpty() || methodArguments.get(0) instanceof J.Empty) {
94-
template = getShortType(javaType) + ".of()";
107+
template = getShortType(javaType) + "." + methodName + "()";
95108
templateArguments = new Object[]{};
96-
} else if ("com.google.common.collect.ImmutableMap".equals(guavaType)) {
97-
template = getShortType(javaType) + ".of(#{any()}, #{any()})";
109+
} else if ("of".equals(methodName) && "com.google.common.collect.ImmutableMap".equals(guavaType)) {
110+
template = getShortType(javaType) + "." + methodName + "(#{any()}, #{any()})";
98111
templateArguments = new Object[]{methodArguments.get(0), methodArguments.get(1)};
99112
} else {
100-
template = getShortType(javaType) + ".of(#{any()})";
113+
template = getShortType(javaType) + "." + methodName + "(#{any()})";
101114
templateArguments = new Object[]{methodArguments.get(0)};
102115
}
103116

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
* <p>
4+
* Licensed under the Moderne Source Available License (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://docs.moderne.io/licensing/moderne-source-available-license
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.migrate.guava;
17+
18+
import org.jspecify.annotations.Nullable;
19+
20+
public class NoGuavaImmutableListCopyOf extends AbstractNoGuavaImmutableOf {
21+
public NoGuavaImmutableListCopyOf() {
22+
super("com.google.common.collect.ImmutableList", "java.util.List", "copyOf", 10);
23+
}
24+
25+
public NoGuavaImmutableListCopyOf(@Nullable Boolean convertReturnType) {
26+
super("com.google.common.collect.ImmutableList", "java.util.List", "copyOf", 10, convertReturnType);
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
* <p>
4+
* Licensed under the Moderne Source Available License (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://docs.moderne.io/licensing/moderne-source-available-license
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.migrate.guava;
17+
18+
import org.jspecify.annotations.Nullable;
19+
20+
public class NoGuavaImmutableMapCopyOf extends AbstractNoGuavaImmutableOf {
21+
public NoGuavaImmutableMapCopyOf() {
22+
super("com.google.common.collect.ImmutableMap", "java.util.Map", "copyOf", 10);
23+
}
24+
25+
public NoGuavaImmutableMapCopyOf(@Nullable Boolean convertReturnType) {
26+
super("com.google.common.collect.ImmutableMap", "java.util.Map", "copyOf", 10, convertReturnType);
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
* <p>
4+
* Licensed under the Moderne Source Available License (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://docs.moderne.io/licensing/moderne-source-available-license
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.migrate.guava;
17+
18+
import org.jspecify.annotations.Nullable;
19+
20+
public class NoGuavaImmutableSetCopyOf extends AbstractNoGuavaImmutableOf {
21+
public NoGuavaImmutableSetCopyOf() {
22+
super("com.google.common.collect.ImmutableSet", "java.util.Set", "copyOf", 10);
23+
}
24+
25+
public NoGuavaImmutableSetCopyOf(@Nullable Boolean convertReturnType) {
26+
super("com.google.common.collect.ImmutableSet", "java.util.Set", "copyOf", 10, convertReturnType);
27+
}
28+
}

src/main/resources/META-INF/rewrite/no-guava.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ recipeList:
9999
- org.openrewrite.java.migrate.guava.NoGuavaImmutableListOf
100100
- org.openrewrite.java.migrate.guava.NoGuavaImmutableMapOf
101101
- org.openrewrite.java.migrate.guava.NoGuavaImmutableSetOf
102+
- org.openrewrite.java.migrate.guava.NoGuavaImmutableListCopyOf
103+
- org.openrewrite.java.migrate.guava.NoGuavaImmutableMapCopyOf
104+
- org.openrewrite.java.migrate.guava.NoGuavaImmutableSetCopyOf
102105
- org.openrewrite.java.migrate.guava.PreferJavaUtilObjectsRequireNonNullElse
103106
- org.openrewrite.java.dependencies.UpgradeDependencyVersion:
104107
groupId: io.springfox

src/main/resources/META-INF/rewrite/recipes.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,11 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.g
9999
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaCreateTempDir,Prefer `Files#createTempDirectory()`,Replaces Guava `Files#createTempDir()` with Java `Files#createTempDirectory(..)`. Transformations are limited to scopes throwing or catching `java.io.IOException`.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
100100
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaDirectExecutor,Prefer `Runnable::run`,"`Executor` is a SAM-compatible interface, so `Runnable::run` is just as succinct as `MoreExecutors.directExecutor()` but without the third-party library requirement.",1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
101101
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaFunctionsCompose,Prefer `Function.compose(Function)`,"Prefer `Function.compose(Function)` over `Functions.compose(Function, Function)`.",1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
102+
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableListCopyOf,Prefer `List.copyOf(..)` in Java 10 or higher,Replaces `.common.collect.ImmutableList.copyOf(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
102103
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableListOf,Prefer `List.of(..)` in Java 9 or higher,Replaces `.common.collect.ImmutableList.of(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
104+
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableMapCopyOf,Prefer `Map.copyOf(..)` in Java 10 or higher,Replaces `.common.collect.ImmutableMap.copyOf(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
103105
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableMapOf,Prefer `Map.of(..)` in Java 9 or higher,Replaces `.common.collect.ImmutableMap.of(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
106+
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableSetCopyOf,Prefer `Set.copyOf(..)` in Java 10 or higher,Replaces `.common.collect.ImmutableSet.copyOf(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
104107
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaImmutableSetOf,Prefer `Set.of(..)` in Java 9 or higher,Replaces `.common.collect.ImmutableSet.of(..)` if the returned type is immediately down-cast.,1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
105108
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaIterablesAll,Prefer `Collection.stream().allMatch(Predicate)`,"Prefer `Collection.stream().allMatch(Predicate)` over `Iterables.all(Collection, Predicate)`.",1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
106109
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.NoGuavaIterablesAnyFilter,Prefer `Collection.stream().anyMatch(Predicate)`,"Prefer `Collection.stream().anyMatch(Predicate)` over `Iterables.any(Collection, Predicate)`.",1,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,

0 commit comments

Comments
 (0)