diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaRefaster.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaRefaster.java new file mode 100644 index 0000000000..5a17e43200 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaRefaster.java @@ -0,0 +1,59 @@ +/* + * Copyright 2024 the original author or authors. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://www.apache.org/licenses/LICENSE-2.0 + *
+ * 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 com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import org.openrewrite.java.template.RecipeDescriptor; + +@RecipeDescriptor( + name = "Refaster style Guava to Java migration recipes.", + description = "Recipes that migrate from Guava to Java, using Refaster style templates for cases beyond what declarative recipes can cover." +) +public class NoGuavaRefaster { + + @RecipeDescriptor( + name = "`Preconditions.checkNotNull` to `Objects.requireNonNull`", + description = "Migrate from Guava `Preconditions.checkNotNull` to Java 8 `java.util.Objects.requireNonNull`." + ) + public static class PreconditionsCheckNotNullToObjectsRequireNonNull { + @BeforeTemplate + Object before(Object object, Object message) { + return com.google.common.base.Preconditions.checkNotNull(object, message); + } + + @AfterTemplate + Object after(Object object, Object message) { + return java.util.Objects.requireNonNull(object, String.valueOf(message)); + } + } + + @RecipeDescriptor( + name = "`String.valueof(String)` to `String`", + description = "Migrate from `String.valueof(String)` to `String`, mainly as a cleanup after other recipes." + ) + public static class StringValueOfString { + @BeforeTemplate + String before(String string) { + return String.valueOf(string); + } + + @AfterTemplate + String after(String string) { + return (string); + } + } +} diff --git a/src/main/resources/META-INF/rewrite/no-guava.yml b/src/main/resources/META-INF/rewrite/no-guava.yml index 027d88f8e4..739684dcb3 100644 --- a/src/main/resources/META-INF/rewrite/no-guava.yml +++ b/src/main/resources/META-INF/rewrite/no-guava.yml @@ -29,6 +29,7 @@ recipeList: - org.openrewrite.java.migrate.guava.NoGuavaListsNewArrayList - org.openrewrite.java.migrate.guava.NoGuavaListsNewCopyOnWriteArrayList - org.openrewrite.java.migrate.guava.NoGuavaListsNewLinkedList + - org.openrewrite.java.migrate.guava.NoGuavaRefasterRecipes - org.openrewrite.java.migrate.guava.NoGuavaSetsNewHashSet - org.openrewrite.java.migrate.guava.NoGuavaSetsNewConcurrentHashSet - org.openrewrite.java.migrate.guava.NoGuavaSetsNewLinkedHashSet diff --git a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java index c323c8700d..2a340b6195 100644 --- a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java +++ b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java @@ -16,9 +16,7 @@ package org.openrewrite.java.migrate.guava; import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.ExpectedToFail; import org.openrewrite.DocumentExample; -import org.openrewrite.config.Environment; import org.openrewrite.java.JavaParser; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; @@ -28,114 +26,143 @@ class PreferJavaUtilObjectsTest implements RewriteTest { @Override public void defaults(RecipeSpec spec) { - spec.recipe( - Environment.builder() - .scanRuntimeClasspath("org.openrewrite.java.migrate.guava") - .build() - .activateRecipes("org.openrewrite.java.migrate.guava.NoGuava") - ) + spec.recipeFromResource("/META-INF/rewrite/no-guava.yml", "org.openrewrite.java.migrate.guava.NoGuava") .parser(JavaParser.fromJavaVersion().classpath("rewrite-java", "guava")); } @DocumentExample @Test void preconditionsCheckNotNullToObjectsRequireNonNull() { - //language=java - rewriteRun(java( - """ - import com.google.common.base.Preconditions; - - class A { - Object foo(Object obj) { - return Preconditions.checkNotNull(obj); + rewriteRun( + //language=java + java( + """ + import com.google.common.base.Preconditions; + + class A { + Object foo(Object obj) { + return Preconditions.checkNotNull(obj); + } } - } - """, """ - import java.util.Objects; + """, + """ + import java.util.Objects; - class A { - Object foo(Object obj) { - return Objects.requireNonNull(obj); + class A { + Object foo(Object obj) { + return Objects.requireNonNull(obj); + } } - } - """)); + """ + ) + ); } @Test - @ExpectedToFail(""" - Preconditions has both `checkNotNull(Object, Object)` and `checkNotNull(Object, String, Object...)`, - meaning we can't exactly match only the `(Object, String)` case which Objects.requireNonNull supports. - """) void preconditionsCheckNotNullToObjectsRequireNonNullTwoArguments() { - //language=java - rewriteRun(java( - """ - import com.google.common.base.Preconditions; - - class A { - Object foo(Object obj) { - return Preconditions.checkNotNull(obj, "foo"); + rewriteRun( + //language=java + java( + """ + import com.google.common.base.Preconditions; + + class A { + Object foo(Object obj) { + return Preconditions.checkNotNull(obj, "foo"); + } + } + """, + """ + import java.util.Objects; + + class A { + Object foo(Object obj) { + return Objects.requireNonNull(obj, "foo"); + } + } + """ + ) + ); + } + + @Test + void preconditionsCheckNotNullToObjectsRequireNonNullTwoArgumentsSecondObject() { + rewriteRun( + //language=java + java( + """ + import com.google.common.base.Preconditions; + + class A { + Object foo(Object obj, StringBuilder description) { + return Preconditions.checkNotNull(obj, description); + } } - } - """, """ - import java.util.Objects; + """, + """ + import java.util.Objects; - class A { - Object foo(Object obj) { - return Objects.requireNonNull(obj, "foo"); + class A { + Object foo(Object obj, StringBuilder description) { + return Objects.requireNonNull(obj, String.valueOf(description)); + } } - } - """)); + """ + ) + ); } @Test void preconditionsCheckNotNullToObjectsRequireNonNullStatic() { - //language=java - rewriteRun(java( - """ - import static com.google.common.base.Preconditions.checkNotNull; - - class A { - Object foo(Object obj) { - return checkNotNull(obj); + rewriteRun( + //language=java + java( + """ + import static com.google.common.base.Preconditions.checkNotNull; + + class A { + Object foo(Object obj) { + return checkNotNull(obj); + } } - } - """, """ - import static java.util.Objects.requireNonNull; + """, + """ + import static java.util.Objects.requireNonNull; - class A { - Object foo(Object obj) { - return requireNonNull(obj); + class A { + Object foo(Object obj) { + return requireNonNull(obj); + } } - } - """)); + """ + ) + ); } @Test void moreObjectsFirstNonNullToObjectsRequireNonNullElse() { - //language=java - rewriteRun(spec -> {spec.recipes(Environment.builder() - .scanRuntimeClasspath("org.openrewrite.java.migrate.guava") - .build() - .activateRecipes("org.openrewrite.java.migrate.guava.NoGuavaJava11")); - }, + rewriteRun(spec -> spec.recipeFromResource("/META-INF/rewrite/no-guava.yml", "org.openrewrite.java.migrate.guava.NoGuavaJava11"), + //language=java java( - """ - import com.google.common.base.MoreObjects; + """ + import com.google.common.base.MoreObjects; - class A { - Object foo(Object obj) { - return MoreObjects.firstNonNull(obj, "default"); + class A { + Object foo(Object obj) { + return MoreObjects.firstNonNull(obj, "default"); + } } - } - """, """ - import java.util.Objects; + """, + """ + import java.util.Objects; - class A { - Object foo(Object obj) { - return Objects.requireNonNullElse(obj, "default"); + class A { + Object foo(Object obj) { + return Objects.requireNonNullElse(obj, "default"); + } } - } - """)); + """ + ) + ); } }