diff --git a/README.md b/README.md index 698a44226..8250e37d9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,25 @@ -![Logo](https://github.com/openrewrite/rewrite/raw/main/doc/logo-oss.png) - -### Migrate to later Java versions. Automatically. - +
+
+
+
+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://docs.moderne.io/licensing/moderne-source-available-license + *
+ * 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 org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.JavaVisitor;
+import org.openrewrite.java.MethodMatcher;
+import org.openrewrite.java.search.UsesJavaVersion;
+import org.openrewrite.java.search.UsesMethod;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.JavaCoordinates;
+
+public class NoMapsAndSetsWithExpectedSize extends Recipe {
+
+ private static final MethodMatcher NEW_HASHMAP = new MethodMatcher("com.google.common.collect.Maps newHashMapWithExpectedSize(int)", false);
+ private static final MethodMatcher NEW_LINKED_HASHMAP = new MethodMatcher("com.google.common.collect.Maps newLinkedHashMapWithExpectedSize(int)", false);
+ private static final MethodMatcher NEW_HASHSET = new MethodMatcher("com.google.common.collect.Sets newHashSetWithExpectedSize(int)", false);
+ private static final MethodMatcher NEW_LINKED_HASHSET = new MethodMatcher("com.google.common.collect.Sets newLinkedHashSetWithExpectedSize(int)", false);
+
+ @Override
+ public String getDisplayName() {
+ return "Prefer JDK methods for Maps and Sets of an expected size";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Prefer Java 19+ methods to create Maps and Sets of an expected size instead of using Guava methods.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return Preconditions.check(
+ Preconditions.and(
+ new UsesJavaVersion<>(19),
+ Preconditions.or(
+ new UsesMethod<>(NEW_HASHMAP),
+ new UsesMethod<>(NEW_LINKED_HASHMAP),
+ new UsesMethod<>(NEW_HASHSET),
+ new UsesMethod<>(NEW_LINKED_HASHSET)
+ )
+ ),
+ new JavaVisitor
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok;
+
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeUtils;
+
+import static java.util.Comparator.comparing;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseNoArgsConstructor extends Recipe {
+
+ @Override
+ public String getDisplayName() {
+ //language=markdown
+ return "Use `@NoArgsConstructor` where applicable";
+ }
+
+ @Override
+ public String getDescription() {
+ //language=markdown
+ return "Prefer the Lombok `@NoArgsConstructor` annotation over explicitly written out constructors.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new JavaIsoVisitor
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.java.*;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeUtils;
+
+import static java.util.Comparator.comparing;
+
+@EqualsAndHashCode(callSuper = false)
+class LogVisitor extends JavaIsoVisitor
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Option;
+import org.openrewrite.TreeVisitor;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseCommonsLog extends UseLogRecipeTemplate {
+
+ @Override
+ public String getDisplayName() {
+ return getDisplayName("@CommonsLog");
+ }
+
+ @Override
+ public String getDescription() {
+ return getDescription("@CommonsLog", "org.apache.commons.logging.Log");
+ }
+
+ @Option(displayName = "Name of the log field",
+ description = FIELD_NAME_DESCRIPTION,
+ example = "LOGGER",
+ required = false)
+ @Nullable
+ String fieldName;
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new LogVisitor(
+ "org.apache.commons.logging.Log",
+ "org.apache.commons.logging.LogFactory getLog(..)",
+ "lombok.extern.apachecommons.CommonsLog",
+ fieldName);
+ }
+
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/UseJBossLog.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseJBossLog.java
new file mode 100644
index 000000000..5019d631e
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseJBossLog.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Option;
+import org.openrewrite.TreeVisitor;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseJBossLog extends UseLogRecipeTemplate {
+
+ @Override
+ public String getDisplayName() {
+ return getDisplayName("@JBossLog");
+ }
+
+ @Override
+ public String getDescription() {
+ return getDescription("@JBossLog", "org.jboss.logging.Logger");
+ }
+
+ @Option(displayName = "Name of the log field",
+ description = FIELD_NAME_DESCRIPTION,
+ example = "LOGGER",
+ required = false)
+ @Nullable
+ String fieldName;
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new LogVisitor(
+ "org.jboss.logging.Logger",
+ "org.jboss.logging.Logger getLogger(..)",
+ "lombok.extern.jbosslog.JBossLog",
+ fieldName);
+ }
+
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog.java
new file mode 100644
index 000000000..3078193af
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Option;
+import org.openrewrite.TreeVisitor;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseLog extends UseLogRecipeTemplate {
+
+ @Override
+ public String getDisplayName() {
+ return getDisplayName("@Log");
+ }
+
+ @Override
+ public String getDescription() {
+ return getDescription("@Log", "java.util.logging.Logger");
+ }
+
+ @Option(displayName = "Name of the log field",
+ description = FIELD_NAME_DESCRIPTION,
+ example = "LOGGER",
+ required = false)
+ @Nullable
+ String fieldName;
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new LogVisitor(
+ "java.util.logging.Logger",
+ "java.util.logging.Logger getLogger(String)",
+ "lombok.extern.java.Log",
+ fieldName) {
+
+ @Override
+ protected String getFactoryParameter(String className) {
+ return className + ".class.getName()";
+ }
+ };
+ }
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog4j2.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog4j2.java
new file mode 100644
index 000000000..479c5cd83
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog4j2.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Option;
+import org.openrewrite.TreeVisitor;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseLog4j2 extends UseLogRecipeTemplate {
+
+ @Override
+ public String getDisplayName() {
+ return getDisplayName("@Log4j2");
+ }
+
+ @Override
+ public String getDescription() {
+ return getDescription("@Log4j2", "org.apache.logging.log4j.Logger");
+ }
+
+ @Option(displayName = "Name of the log field",
+ description = FIELD_NAME_DESCRIPTION,
+ example = "LOGGER",
+ required = false)
+ @Nullable
+ String fieldName;
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new LogVisitor(
+ "org.apache.logging.log4j.Logger",
+ "org.apache.logging.log4j.LogManager getLogger(..)",
+ "lombok.extern.log4j.Log4j2",
+ fieldName);
+ }
+
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLogRecipeTemplate.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLogRecipeTemplate.java
new file mode 100644
index 000000000..4e6b8a02e
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLogRecipeTemplate.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import org.openrewrite.Recipe;
+
+abstract class UseLogRecipeTemplate extends Recipe {
+
+ protected static final String FIELD_NAME_DESCRIPTION = "Name of the log field to replace. " +
+ "If not specified, the field name is not checked and any field that satisfies the other checks is converted.";
+
+ protected String getDisplayName(String annotation) {
+ return String.format("Use `%s` instead of explicit fields", annotation);
+ }
+
+ protected String getDescription(String annotation, String pathToLogger) {
+ //language=markdown
+ return String.format("Prefer the lombok annotation `%s` over explicitly written out `%s` fields.", annotation, pathToLogger);
+ }
+
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/UseSlf4j.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseSlf4j.java
new file mode 100644
index 000000000..7dfd9e60c
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseSlf4j.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.jspecify.annotations.Nullable;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Option;
+import org.openrewrite.TreeVisitor;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class UseSlf4j extends UseLogRecipeTemplate {
+
+ @Override
+ public String getDisplayName() {
+ return getDisplayName("@Slf4");
+ }
+
+ @Override
+ public String getDescription() {
+ return getDescription("@Slf4", "org.slf4j.Logger");
+ }
+
+ @Option(displayName = "Name of the log field",
+ description = FIELD_NAME_DESCRIPTION,
+ example = "LOGGER",
+ required = false)
+ @Nullable
+ String fieldName;
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new LogVisitor("org.slf4j.Logger",
+ "org.slf4j.LoggerFactory getLogger(..)",
+ "lombok.extern.slf4j.Slf4j",
+ fieldName);
+ }
+
+}
diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/package-info.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/package-info.java
new file mode 100644
index 000000000..2a10bcbe0
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.
+ */
+@NullMarked
+@NonNullFields
+package org.openrewrite.java.migrate.lombok.log;
+
+import org.jspecify.annotations.NullMarked;
+import org.openrewrite.internal.lang.NonNullFields;
diff --git a/src/main/resources/META-INF/rewrite/jakarta-ee-9.yml b/src/main/resources/META-INF/rewrite/jakarta-ee-9.yml
index af337163f..3883b3339 100644
--- a/src/main/resources/META-INF/rewrite/jakarta-ee-9.yml
+++ b/src/main/resources/META-INF/rewrite/jakarta-ee-9.yml
@@ -918,6 +918,12 @@ recipeList:
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: com.fasterxml.jackson.datatype.jsr353.JSR353Module
newFullyQualifiedTypeName: com.fasterxml.jackson.datatype.jsonp.JSONPModule
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
+ newFullyQualifiedTypeName: com.fasterxml.jackson.jakarta.rs.json.JacksonXmlBindJsonProvider
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule
+ newFullyQualifiedTypeName: com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule
---
type: specs.openrewrite.org/v1beta/recipe
diff --git a/src/main/resources/META-INF/rewrite/java-ee-8.yml b/src/main/resources/META-INF/rewrite/java-ee-8.yml
index 98d19339a..2625b1125 100644
--- a/src/main/resources/META-INF/rewrite/java-ee-8.yml
+++ b/src/main/resources/META-INF/rewrite/java-ee-8.yml
@@ -23,6 +23,12 @@ tags:
- javaee8
- deprecated
recipeList:
+ - org.openrewrite.java.dependencies.ChangeDependency:
+ oldGroupId: javax.servlet
+ oldArtifactId: servlet-api
+ newGroupId: javax.servlet
+ newArtifactId: javax.servlet-api
+ newVersion: 3.x
- org.openrewrite.java.migrate.javaee7
- org.openrewrite.java.migrate.javaee8.ServletIsRequestedSessionIdFromURL
- org.openrewrite.java.migrate.javaee8.ApacheDefaultProvider
@@ -42,8 +48,8 @@ type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.javaee8.ApacheDefaultProvider
displayName: Flags any `org.apache.bval.jsr*` (bval 1.1) and `org.apache.bval.jsr303*` (bval 1.0) package references
description: >-
- This recipe flags any `org.apache.bval.jsr*` (bval 1.1) and `org.apache.bval.jsr303*` (bval 1.0) package references in validation.xml deployment descriptors.
- Bean Validation 2.0 and later use the Hibernate Validator implementation instead of the
+ This recipe flags any `org.apache.bval.jsr*` (bval 1.1) and `org.apache.bval.jsr303*` (bval 1.0) package references in validation.xml deployment descriptors.
+ Bean Validation 2.0 and later use the Hibernate Validator implementation instead of the
Apache BVal implementation which was used for Bean Validation 1.0 and 1.1.
recipeList:
- org.openrewrite.xml.ChangeTagValue:
@@ -60,4 +66,3 @@ recipeList:
newValue: org.hibernate.validator.engine.ConstraintValidatorFactoryImpl
- org.openrewrite.xml.RemoveXmlTag:
xPath: /validation-config/parameter-name-provider
-
\ No newline at end of file
diff --git a/src/main/resources/META-INF/rewrite/lombok.yml b/src/main/resources/META-INF/rewrite/lombok.yml
index 554b8c427..9e384f14b 100644
--- a/src/main/resources/META-INF/rewrite/lombok.yml
+++ b/src/main/resources/META-INF/rewrite/lombok.yml
@@ -13,7 +13,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
+---
+type: specs.openrewrite.org/v1beta/recipe
+name: org.openrewrite.java.migrate.lombok.LombokBestPractices
+displayName: Lombok Best Practices
+description: >-
+ Applies all recipes that enforce best practices for using Lombok.
+recipeList:
+ - org.openrewrite.java.migrate.lombok.UpdateLombokToJava11
+ - org.openrewrite.java.migrate.lombok.log.UseLombokLogAnnotations
+ - org.openrewrite.java.migrate.lombok.UseLombokGetter
+ - org.openrewrite.java.migrate.lombok.UseLombokSetter
+ - org.openrewrite.java.migrate.lombok.UseNoArgsConstructor
+ - org.openrewrite.maven.ChangeDependencyScope:
+ groupId: org.projectlombok
+ artifactId: lombok
+ newScope: provided
+ - org.openrewrite.maven.ChangeDependencyScope:
+ groupId: org.projectlombok
+ artifactId: lombok-mapstruct-binding
+ newScope: provided
+ - org.openrewrite.maven.ExcludeDependency:
+ groupId: org.projectlombok
+ artifactId: lombok
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.lombok.UpdateLombokToJava11
@@ -43,3 +65,16 @@ recipeList:
oldFullyQualifiedTypeName: lombok.experimental.val
newFullyQualifiedTypeName: lombok.val
- org.openrewrite.java.migrate.lombok.LombokValToFinalVar
+
+---
+type: specs.openrewrite.org/v1beta/recipe
+name: org.openrewrite.java.migrate.lombok.log.UseLombokLogAnnotations
+displayName: Use Lombok logger annotations instead of explicit fields
+description: >-
+ Applies all recipes that replace logger declarations with class level annotations.
+recipeList:
+ - org.openrewrite.java.migrate.lombok.log.UseCommonsLog
+ - org.openrewrite.java.migrate.lombok.log.UseJBossLog
+ - org.openrewrite.java.migrate.lombok.log.UseLog
+ - org.openrewrite.java.migrate.lombok.log.UseLog4j2
+ - org.openrewrite.java.migrate.lombok.log.UseSlf4j
diff --git a/src/main/resources/META-INF/rewrite/no-guava.yml b/src/main/resources/META-INF/rewrite/no-guava.yml
index 82f7f90a3..56e204bf7 100644
--- a/src/main/resources/META-INF/rewrite/no-guava.yml
+++ b/src/main/resources/META-INF/rewrite/no-guava.yml
@@ -25,6 +25,8 @@ description: >-
tags:
- guava
recipeList:
+ - org.openrewrite.java.migrate.guava.NoGuavaJava11
+ - org.openrewrite.java.migrate.guava.NoGuavaJava21
- org.openrewrite.java.migrate.guava.NoGuavaCreateTempDir
- org.openrewrite.java.migrate.guava.NoGuavaDirectExecutor
- org.openrewrite.java.migrate.guava.NoGuavaListsNewArrayList
@@ -62,6 +64,8 @@ recipeList:
- org.openrewrite.java.migrate.guava.PreferMathMultiplyExact
- org.openrewrite.java.migrate.guava.NoGuavaAtomicsNewReference
+ - tech.picnic.errorprone.refasterrules.InputStreamRulesRecipes
+
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.guava.NoGuavaJava11
@@ -73,8 +77,10 @@ description: >-
tags:
- guava
- java11
+preconditions:
+ - org.openrewrite.java.search.HasJavaVersion:
+ version: "[11,)"
recipeList:
- - org.openrewrite.java.migrate.guava.NoGuava
- org.openrewrite.java.migrate.guava.NoGuavaImmutableListOf
- org.openrewrite.java.migrate.guava.NoGuavaImmutableMapOf
- org.openrewrite.java.migrate.guava.NoGuavaImmutableSetOf
@@ -95,9 +101,13 @@ description: >-
tags:
- guava
- java21
+preconditions:
+ - org.openrewrite.java.search.HasJavaVersion:
+ version: "[21,)"
recipeList:
- - org.openrewrite.java.migrate.guava.NoGuavaJava11
+ - org.openrewrite.java.migrate.guava.NoMapsAndSetsWithExpectedSize
- org.openrewrite.java.migrate.guava.PreferMathClamp
+
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.guava.PreferJavaNioCharsetStandardCharsets
diff --git a/src/main/resources/sdkman-java.csv b/src/main/resources/sdkman-java.csv
index ed0b5eee7..332f5dcd5 100644
--- a/src/main/resources/sdkman-java.csv
+++ b/src/main/resources/sdkman-java.csv
@@ -76,15 +76,23 @@
24.ea.23-graal
24.ea.24-graal
24.ea.25-graal
+24.ea.26-graal
24.ea.26-open
+24.ea.27-graal
24.ea.27-open
24.ea.28-open
24.ea.29-open
+24.ea.30-open
+24.ea.31-open
25.ea.1-graal
25.ea.1-open
25.ea.2-graal
25.ea.2-open
+25.ea.3-graal
25.ea.3-open
+25.ea.4-graal
+25.ea.4-open
+25.ea.5-open
6.0.119-zulu
7.0.352-zulu
8.0.282-trava
diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaJava21Test.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaJava21Test.java
index f59f1a57d..8eed3f18d 100644
--- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaJava21Test.java
+++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaJava21Test.java
@@ -17,23 +17,17 @@
import org.junit.jupiter.api.Test;
import org.openrewrite.Issue;
-import org.openrewrite.config.Environment;
import org.openrewrite.java.JavaParser;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
-import static org.openrewrite.java.Assertions.java;
-import static org.openrewrite.java.Assertions.version;
+import static org.openrewrite.java.Assertions.*;
class NoGuavaJava21Test 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.NoGuavaJava21")
- )
+ spec
+ .recipeFromResource("/META-INF/rewrite/no-guava.yml", "org.openrewrite.java.migrate.guava.NoGuava")
.parser(JavaParser.fromJavaVersion().classpath("guava"));
}
@@ -122,32 +116,30 @@ public float testMethod() {
@Test
void noGuavaImmutableOfException() {
rewriteRun(
- version(
- //language=java
- java(
- """
- import com.google.common.collect.ImmutableSet;
- import com.google.common.collect.ImmutableMap;
+ //language=java
+ java(
+ """
+ import com.google.common.collect.ImmutableSet;
+ import com.google.common.collect.ImmutableMap;
- class A {
- public Object getMap() {
- return ImmutableMap.of("key", ImmutableSet.of("value1", "value2"));
- }
- }
- """,
- """
- import com.google.common.collect.ImmutableSet;
+ class A {
+ public Object getMap() {
+ return ImmutableMap.of("key", ImmutableSet.of("value1", "value2"));
+ }
+ }
+ """,
+ """
+ import com.google.common.collect.ImmutableSet;
- import java.util.Map;
+ import java.util.Map;
- class A {
- public Object getMap() {
- return Map.of("key", ImmutableSet.of("value1", "value2"));
- }
- }
- """
- ),
- 21
+ class A {
+ public Object getMap() {
+ return Map.of("key", ImmutableSet.of("value1", "value2"));
+ }
+ }
+ """,
+ spec -> spec.markers(javaVersion(21))
)
);
}
diff --git a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaRefasterTest.java
similarity index 85%
rename from src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java
rename to src/test/java/org/openrewrite/java/migrate/guava/NoGuavaRefasterTest.java
index f3df9d5b3..7ebd43113 100644
--- a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilObjectsTest.java
+++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaRefasterTest.java
@@ -23,7 +23,7 @@
import static org.openrewrite.java.Assertions.java;
-class PreferJavaUtilObjectsTest implements RewriteTest {
+class NoGuavaRefasterTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new NoGuavaRefasterRecipes())
@@ -184,31 +184,4 @@ Object foo(Object obj) {
)
);
}
-
- @Test
- void moreObjectsFirstNonNullToObjectsRequireNonNullElse() {
- 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;
-
- class A {
- Object foo(Object obj) {
- return MoreObjects.firstNonNull(obj, "default");
- }
- }
- """,
- """
- import java.util.Objects;
-
- class A {
- Object foo(Object obj) {
- return Objects.requireNonNullElse(obj, "default");
- }
- }
- """
- )
- );
- }
}
diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaTest.java
index 5701794a8..f53de64aa 100644
--- a/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaTest.java
+++ b/src/test/java/org/openrewrite/java/migrate/guava/NoGuavaTest.java
@@ -16,26 +16,52 @@
package org.openrewrite.java.migrate.guava;
import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
import org.openrewrite.Issue;
-import org.openrewrite.config.Environment;
import org.openrewrite.java.JavaParser;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;
import static org.openrewrite.java.Assertions.java;
+import static org.openrewrite.java.Assertions.javaVersion;
class NoGuavaTest 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("guava"));
}
+ @DocumentExample
+ @Test
+ void moreObjectsFirstNonNullToObjectsRequireNonNullElse() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import com.google.common.base.MoreObjects;
+
+ class A {
+ Object foo(Object obj) {
+ return MoreObjects.firstNonNull(obj, "default");
+ }
+ }
+ """,
+ """
+ import java.util.Objects;
+
+ class A {
+ Object foo(Object obj) {
+ return Objects.requireNonNullElse(obj, "default");
+ }
+ }
+ """,
+ spec -> spec.markers(javaVersion(11))
+ )
+ );
+ }
+
@Test
@Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/39#issuecomment-910673213")
void preferJavaUtilObjectsHashCode() {
diff --git a/src/test/java/org/openrewrite/java/migrate/guava/NoMapsAndSetsWithExpectedSizeTest.java b/src/test/java/org/openrewrite/java/migrate/guava/NoMapsAndSetsWithExpectedSizeTest.java
new file mode 100644
index 000000000..aad926d65
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/guava/NoMapsAndSetsWithExpectedSizeTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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 org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+import static org.openrewrite.java.Assertions.javaVersion;
+
+class NoMapsAndSetsWithExpectedSizeTest implements RewriteTest {
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipe(new NoMapsAndSetsWithExpectedSize());
+ }
+
+ @DocumentExample
+ @Test
+ void noMapSetWithExpectedSize() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import com.google.common.collect.Maps;
+ import com.google.common.collect.Sets;
+ import java.util.Map;
+ import java.util.Set;
+
+ class A {
+ void method() {
+ Map
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+import org.openrewrite.test.SourceSpec;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.openrewrite.java.Assertions.mavenProject;
+import static org.openrewrite.maven.Assertions.pomXml;
+
+class LombokBestPracticesTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/lombok.yml",
+ "org.openrewrite.java.migrate.lombok.LombokBestPractices");
+ }
+
+ @DocumentExample
+ @Test
+ void providedScope() {
+ rewriteRun(
+ pomXml(
+ //language=xml
+ """
+
+ * 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.lombok;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+
+class UseNoArgsConstructorTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipe(new UseNoArgsConstructor());
+ }
+
+ @DocumentExample
+ @Test
+ void replaceEmptyPublicConstructor() {
+ rewriteRun(// language=java
+ java(
+ """
+ class A {
+ public A() {}
+ }
+ """,
+ """
+ import lombok.NoArgsConstructor;
+
+ @NoArgsConstructor
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void keepNonEmptyPublicConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class A {
+
+ int foo;
+
+ public A() {
+ foo = 7;
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceEmptyProtectedConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class A {
+ protected A() {}
+ }
+ """,
+ """
+ import lombok.AccessLevel;
+ import lombok.NoArgsConstructor;
+
+ @NoArgsConstructor(access = AccessLevel.PROTECTED)
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceEmptyPrivateConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class A {
+ private A() {}
+ }
+ """,
+ """
+ import lombok.AccessLevel;
+ import lombok.NoArgsConstructor;
+
+ @NoArgsConstructor(access = AccessLevel.PRIVATE)
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceEmptyPackageConstructor() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ class A {
+ A() {}
+ }
+ """,
+ """
+ import lombok.AccessLevel;
+ import lombok.NoArgsConstructor;
+
+ @NoArgsConstructor(access = AccessLevel.PACKAGE)
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+}
diff --git a/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertAnyLogTest.java b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertAnyLogTest.java
new file mode 100644
index 000000000..3a1428633
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertAnyLogTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+
+class ConvertAnyLogTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResources("org.openrewrite.java.migrate.lombok.log.UseLombokLogAnnotations")
+ .parser(JavaParser.fromJavaVersion()
+ .classpath("slf4j-api", "log4j-api", "jboss-logging", "commons-logging"));
+ }
+
+ @DocumentExample
+ @Test
+ void replaceAllLoggers() {
+ rewriteRun(
+ // language=java
+ java(
+ """
+ class A {
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ ),
+ // language=java
+ java(
+ """
+ import org.apache.logging.log4j.Logger;
+ import org.apache.logging.log4j.LogManager;
+ class B {
+ private static final Logger log = LogManager.getLogger(B.class);
+ }
+ """,
+ """
+ import lombok.extern.log4j.Log4j2;
+
+ @Log4j2
+ class B {
+ }
+ """
+ ),
+ // language=java
+ java(
+ """
+ import java.util.logging.Logger;
+ class C {
+ private static final Logger log = Logger.getLogger(C.class.getName());
+ }
+ """,
+ """
+ import lombok.extern.java.Log;
+
+ @Log
+ class C {
+ }
+ """
+ ),
+ // language=java
+ java(
+ """
+ import org.jboss.logging.Logger;
+ class D {
+ private static final Logger log = Logger.getLogger(D.class);
+ }
+ """,
+ """
+ import lombok.extern.jbosslog.JBossLog;
+
+ @JBossLog
+ class D {
+ }
+ """
+ ),
+ // language=java
+ java(
+ """
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
+ class E {
+ private static final Log log = LogFactory.getLog(E.class);
+ }
+ """,
+ """
+ import lombok.extern.apachecommons.CommonsLog;
+
+ @CommonsLog
+ class E {
+ }
+ """
+ )
+ );
+ }
+}
diff --git a/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertToLogAnnotationTest.java b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertToLogAnnotationTest.java
new file mode 100644
index 000000000..aa2461907
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertToLogAnnotationTest.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * 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.lombok.log;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.openrewrite.DocumentExample;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+
+class ConvertToLogAnnotationTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipe(new UseSlf4j(null))
+ .parser(JavaParser.fromJavaVersion()
+ .classpath("slf4j-api"));
+ }
+
+ @DocumentExample
+ @Test
+ void replaceSlf4j() {
+ rewriteRun(// language=java
+ java(
+ """
+ class A {
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceSlf4jAndRenameFieldUsages() {
+ rewriteRun(
+ // language=java
+ java(
+ """
+ class A {
+ private static final org.slf4j.Logger renamed = org.slf4j.LoggerFactory.getLogger(A.class);
+
+ void test() {
+ renamed.info("test");
+ }
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+
+ void test() {
+ log.info("test");
+ }
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceSlf4jImportedType() {
+ rewriteRun(// language=java
+ java(
+ """
+ import org.slf4j.Logger;
+ class A {
+ private static final Logger log = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceSlf4jImportedLogger() {
+ rewriteRun(// language=java
+ java(
+ """
+ import org.slf4j.LoggerFactory;
+ class A {
+ private static final org.slf4j.Logger log = LoggerFactory.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceSlf4jStaticallyImportedLogger() {
+ rewriteRun(// language=java
+ java(
+ """
+ import static org.slf4j.LoggerFactory.*;
+ class A {
+ private static final org.slf4j.Logger log = getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void shouldNotReplaceWhenFieldNameDiffersFromSpecifiedName() {
+ rewriteRun(
+ spec -> spec.recipe(new UseSlf4j("log"))
+ .parser(JavaParser.fromJavaVersion()
+ .classpath("slf4j-api")),
+
+ // language=java
+ java(
+ """
+ class A {
+ private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "public static final",
+ "protected static final",
+ "static final",
+ "private final",
+ "private static",
+ })
+ void shouldNotReplaceWhenNotPrivateStaticFinal(String modifiers) {
+ rewriteRun(
+ spec -> spec.recipe(new UseSlf4j(null))
+ .parser(JavaParser.fromJavaVersion()
+ .classpath("slf4j-api")),
+
+ // language=java
+ java(
+ """
+ class A {
+ %s org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """.formatted(modifiers)
+ )
+ );
+ }
+
+ @Test
+ void replaceSlf4jWithPackage() {
+ rewriteRun(// language=java
+ java(
+ """
+ package com.yourorg.yourapp;
+ class A {
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(A.class);
+ }
+ """,
+ """
+ package com.yourorg.yourapp;
+
+ import lombok.extern.slf4j.Slf4j;
+
+ @Slf4j
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceLog4j() {
+ rewriteRun(
+ spec -> spec.recipe(new UseLog4j2(null))
+ .parser(JavaParser.fromJavaVersion()
+ .logCompilationWarningsAndErrors(true)
+ .classpath("log4j-api")),
+ // language=java
+ java(
+ """
+ import org.apache.logging.log4j.Logger;
+ import org.apache.logging.log4j.LogManager;
+ class A {
+ private static final Logger log = LogManager.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.log4j.Log4j2;
+
+ @Log4j2
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceLog() {
+ rewriteRun(
+ spec -> spec.recipe(new UseLog(null))
+ .parser(JavaParser.fromJavaVersion()
+ .logCompilationWarningsAndErrors(true)),
+
+ // language=java
+ java(
+ """
+ import java.util.logging.Logger;
+ class A {
+ private static final Logger log = Logger.getLogger(A.class.getName());
+ }
+ """,
+ """
+ import lombok.extern.java.Log;
+
+ @Log
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceJbossLog() {
+ rewriteRun(
+ spec -> spec.recipe(new UseJBossLog(null))
+ .parser(JavaParser.fromJavaVersion()
+ .logCompilationWarningsAndErrors(true)
+ .classpath("jboss-logging")),
+ // language=java
+ java(
+ """
+ import org.jboss.logging.Logger;
+ class A {
+ private static final Logger log = Logger.getLogger(A.class);
+ }
+ """,
+ """
+ import lombok.extern.jbosslog.JBossLog;
+
+ @JBossLog
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void replaceCommonsLog() {
+ rewriteRun(
+ spec -> spec.recipe(new UseCommonsLog(null))
+ .parser(JavaParser.fromJavaVersion()
+ .logCompilationWarningsAndErrors(true)
+ .classpath("commons-logging")),
+ // language=java
+ java(
+ """
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
+ class A {
+ private static final Log log = LogFactory.getLog(A.class);
+ }
+ """,
+ """
+ import lombok.extern.apachecommons.CommonsLog;
+
+ @CommonsLog
+ class A {
+ }
+ """
+ )
+ );
+ }
+
+}