From 11aa47d8b49e50d595f69f8c9f8df7e4d790b913 Mon Sep 17 00:00:00 2001 From: Laurens Westerlaken Date: Thu, 15 Aug 2024 20:20:39 +0200 Subject: [PATCH] Remove `SolrAutoConfiguration` from `@SpringBootApplication` exclusions (#577) * First WIP with tests * Add empty newline at the end of test class * Add additional test case and minor polish * Illustrate another case not yet matched * Adopt TypeUtils; minimize conditional logic --------- Co-authored-by: Laurens Westerlaken Co-authored-by: Tim te Beek --- .../RemoveSolrAutoConfigurationExclude.java | 95 +++++++++ ...emoveSolrAutoConfigurationExcludeTest.java | 194 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 src/main/java/org/openrewrite/java/spring/boot3/RemoveSolrAutoConfigurationExclude.java create mode 100644 src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/RemoveSolrAutoConfigurationExcludeTest.java diff --git a/src/main/java/org/openrewrite/java/spring/boot3/RemoveSolrAutoConfigurationExclude.java b/src/main/java/org/openrewrite/java/spring/boot3/RemoveSolrAutoConfigurationExclude.java new file mode 100644 index 00000000..847f6d47 --- /dev/null +++ b/src/main/java/org/openrewrite/java/spring/boot3/RemoveSolrAutoConfigurationExclude.java @@ -0,0 +1,95 @@ +/* + * 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.spring.boot3; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.java.AnnotationMatcher; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.search.UsesType; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.TypeUtils; + +import java.util.List; + +public class RemoveSolrAutoConfigurationExclude extends Recipe { + + @Override + public String getDisplayName() { + return "Remove `SolrAutoConfiguration`"; + } + + @Override + public String getDescription() { + return "`SolrAutoConfiguration` was removed in Spring Boot 3; remove references to it from exclusions on annotations."; + } + + private static final String SPRING_BOOT_APPLICATION = "org.springframework.boot.autoconfigure.SpringBootApplication"; + private static final String ENABLE_AUTO_CONFIGURATION = "org.springframework.boot.autoconfigure.EnableAutoConfiguration"; + private static final AnnotationMatcher SBA_MATCHER = new AnnotationMatcher(SPRING_BOOT_APPLICATION); + private static final AnnotationMatcher EAC_MATCHER = new AnnotationMatcher(ENABLE_AUTO_CONFIGURATION); + + private static final String SOLR_AUTO_CONFIGURATION = "SolrAutoConfiguration"; + private static final String SOLR_AUTOCONFIGURATION_FQN = "org.springframework.boot.autoconfigure.solr." + SOLR_AUTO_CONFIGURATION; + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check(Preconditions.or( + new UsesType<>(SPRING_BOOT_APPLICATION, true), + new UsesType<>(ENABLE_AUTO_CONFIGURATION, true)), + new JavaIsoVisitor() { + @Override + public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) { + J.Annotation a = super.visitAnnotation(annotation, ctx); + if (!SBA_MATCHER.matches(a) && !EAC_MATCHER.matches(a)) { + return a; + } + maybeRemoveImport(SOLR_AUTOCONFIGURATION_FQN); + + return a.withArguments(ListUtils.map(a.getArguments(), it -> { + if (it instanceof J.Assignment) { + J.Assignment as = (J.Assignment) it; + if (as.getAssignment() == null || !"exclude".equals(((J.Identifier) as.getVariable()).getSimpleName())) { + return it; + } + if (isSolrAutoConfigurationClassReference(as.getAssignment())) { + return null; + } else if (as.getAssignment() instanceof J.NewArray) { + J.NewArray array = (J.NewArray) as.getAssignment(); + List newInitializer = ListUtils.map(array.getInitializer(), + expr -> isSolrAutoConfigurationClassReference(expr) ? null : expr); + //noinspection DataFlowIssue + if (newInitializer.isEmpty()) { + return null; + } + return maybeAutoFormat(it, as.withAssignment(array.withInitializer(newInitializer)), ctx); + } + } + return it; + })); + } + + private boolean isSolrAutoConfigurationClassReference(Expression expr) { + return expr instanceof J.FieldAccess && + TypeUtils.isAssignableTo(SOLR_AUTOCONFIGURATION_FQN, ((J.FieldAccess) expr).getTarget().getType()); + } + }); + } +} diff --git a/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/RemoveSolrAutoConfigurationExcludeTest.java b/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/RemoveSolrAutoConfigurationExcludeTest.java new file mode 100644 index 00000000..d00f8140 --- /dev/null +++ b/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/RemoveSolrAutoConfigurationExcludeTest.java @@ -0,0 +1,194 @@ +/* + * 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.spring.boot2; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.spring.boot3.RemoveSolrAutoConfigurationExclude; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class RemoveSolrAutoConfigurationExcludeTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new RemoveSolrAutoConfigurationExclude()) + .parser(JavaParser.fromJavaVersion().classpath("spring-boot")); + } + + @Test + @DocumentExample + void removeFromArray() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; + + @SpringBootApplication(exclude = { SecurityAutoConfiguration.class, SolrAutoConfiguration.class }) + public class Application { + } + """, + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + + @SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) + public class Application { + } + """ + ) + ); + } + + @Test + void removeEntireArray() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; + + @SpringBootApplication(exclude = { SolrAutoConfiguration.class }) + class Application { + } + """, + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + + @SpringBootApplication + class Application { + } + """ + ) + ); + } + + @Test + void removeArgument() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; + + @SpringBootApplication(exclude = SolrAutoConfiguration.class) + class Application { + } + """, + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + + @SpringBootApplication + class Application { + } + """ + ) + ); + } + + @Test + void removeFullyQualifiedArgument() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + + @SpringBootApplication(exclude = org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration.class) + class Application { + } + """, + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + + @SpringBootApplication + class Application { + } + """ + ) + ); + } + + @Test + void removeFromEnableAutoConfiguration() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.EnableAutoConfiguration; + import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; + + @EnableAutoConfiguration(exclude = SolrAutoConfiguration.class) + class Application { + } + """, + """ + import org.springframework.boot.autoconfigure.EnableAutoConfiguration; + + @EnableAutoConfiguration + class Application { + } + """ + ) + ); + } + + @Nested + class NoChange { + @Test + void retainOtherAutoConfigurationClasses() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + + @SpringBootApplication(exclude = SecurityAutoConfiguration.class) + public class Application { + } + """ + ) + ); + } + + @Test + void retainOtherAutoConfigurationClassesInArray() { + rewriteRun( + //language=java + java( + """ + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + + @SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) + public class Application { + } + """ + ) + ); + } + } +}