diff --git a/build.gradle.kts b/build.gradle.kts index 99a1d51a86..8fbf549af1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -58,8 +58,11 @@ dependencies { testRuntimeOnly("com.fasterxml.jackson.core:jackson-databind") testRuntimeOnly("com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider") testRuntimeOnly("com.fasterxml.jackson.module:jackson-module-jaxb-annotations") + testRuntimeOnly("commons-logging:commons-logging:1.3.2") + testRuntimeOnly("org.apache.logging.log4j:log4j-api:2.23.1") testRuntimeOnly("org.apache.johnzon:johnzon-core:1.2.18") testRuntimeOnly("org.codehaus.groovy:groovy:latest.release") + testRuntimeOnly("org.jboss.logging:jboss-logging:3.6.0.Final") testRuntimeOnly("jakarta.annotation:jakarta.annotation-api:2.1.1") testRuntimeOnly("org.springframework:spring-core:6.1.13") testRuntimeOnly("com.google.code.findbugs:jsr305:3.0.2") diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/log/LogVisitor.java b/src/main/java/org/openrewrite/java/migrate/lombok/log/LogVisitor.java new file mode 100644 index 0000000000..9af9224231 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/LogVisitor.java @@ -0,0 +1,106 @@ +/* + * Copyright 2021 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.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 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.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 0000000000..6acec98ff3
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseJBossLog.java
@@ -0,0 +1,55 @@
+/*
+ * 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.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 0000000000..cc724222eb
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog.java
@@ -0,0 +1,60 @@
+/*
+ * 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.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 0000000000..f1539a58ae
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLog4j2.java
@@ -0,0 +1,55 @@
+/*
+ * 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.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 0000000000..37387cb3ef
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseLogRecipeTemplate.java
@@ -0,0 +1,34 @@
+/*
+ * 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.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 0000000000..239edd3601
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/UseSlf4j.java
@@ -0,0 +1,54 @@
+/*
+ * 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.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 0000000000..7ecaac351a
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/lombok/log/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2024 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/lombok.yml b/src/main/resources/META-INF/rewrite/lombok.yml
index 554b8c427b..4dd3207b52 100644
--- a/src/main/resources/META-INF/rewrite/lombok.yml
+++ b/src/main/resources/META-INF/rewrite/lombok.yml
@@ -43,3 +43,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/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 0000000000..6cbf558f3c
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertAnyLogTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.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 0000000000..1af3f43911
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/lombok/log/ConvertToLogAnnotationTest.java
@@ -0,0 +1,339 @@
+/*
+ * 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.lombok.log;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Nested;
+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 {
+ }
+ """
+ )
+ );
+ }
+
+ @Nested
+ class RenameField {
+
+ @BeforeAll
+ static void setUp() {
+ System.setProperty("rewrite.lombok", "true");
+ }
+
+ @AfterAll
+ static void tearDown() {
+ System.clearProperty("rewrite.lombok");
+ }
+
+ @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 {
+ }
+ """
+ )
+ );
+ }
+
+}