From 8daef88f92b5298d41f2f1003b0cc869104f2c40 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Tue, 23 Dec 2025 18:59:19 +0100 Subject: [PATCH] Convert TestContainers raw types as part of upgrade --- .../testcontainers/ConvertToRawType.java | 71 +++++++ .../META-INF/rewrite/testcontainers.yml | 56 ++++++ .../testcontainers/ConvertToRawTypeTest.java | 175 ++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 src/main/java/org/openrewrite/java/testing/testcontainers/ConvertToRawType.java create mode 100644 src/test/java/org/openrewrite/java/testing/testcontainers/ConvertToRawTypeTest.java diff --git a/src/main/java/org/openrewrite/java/testing/testcontainers/ConvertToRawType.java b/src/main/java/org/openrewrite/java/testing/testcontainers/ConvertToRawType.java new file mode 100644 index 000000000..65eba5fed --- /dev/null +++ b/src/main/java/org/openrewrite/java/testing/testcontainers/ConvertToRawType.java @@ -0,0 +1,71 @@ +/* + * 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.testing.testcontainers; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.jspecify.annotations.Nullable; +import org.openrewrite.*; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.search.UsesType; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.TypeUtils; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ConvertToRawType extends Recipe { + + @Option(displayName = "Fully qualified type name", + description = "The fully qualified name of the Java class to convert to its raw type.", + example = "org.testcontainers.containers.PostgreSQLContainer") + String fullyQualifiedTypeName; + + @Override + public String getDisplayName() { + return "Remove parameterized type arguments from a Java class"; + } + + @Override + public String getDescription() { + return "Convert parameterized types of a specified Java class to their raw types."; + } + + @Override + public TreeVisitor getVisitor() { + return Preconditions.check(new UsesType<>(fullyQualifiedTypeName, false), new JavaVisitor() { + @Override + public @Nullable JavaType visitType(@Nullable JavaType javaType, ExecutionContext ctx) { + if (javaType instanceof JavaType.Parameterized) { + JavaType rawType = ((JavaType.Parameterized) javaType).getType(); + if (TypeUtils.isAssignableTo(fullyQualifiedTypeName, rawType)) { + return rawType; + } + } + return super.visitType(javaType, ctx); + } + + @Override + public J visitParameterizedType(J.ParameterizedType type, ExecutionContext ctx) { + J.ParameterizedType pt = (J.ParameterizedType) super.visitParameterizedType(type, ctx); + if (TypeUtils.isAssignableTo(fullyQualifiedTypeName, pt.getType())) { + return ((J.Identifier) pt.getClazz()).withPrefix(pt.getPrefix()).withType(pt.getType()); + } + return pt; + } + }); + } +} diff --git a/src/main/resources/META-INF/rewrite/testcontainers.yml b/src/main/resources/META-INF/rewrite/testcontainers.yml index 06a4b7212..9e679c8de 100644 --- a/src/main/resources/META-INF/rewrite/testcontainers.yml +++ b/src/main/resources/META-INF/rewrite/testcontainers.yml @@ -530,3 +530,59 @@ recipeList: - org.openrewrite.java.ChangeType: oldFullyQualifiedTypeName: org.testcontainers.containers.ToxiproxyContainer newFullyQualifiedTypeName: org.testcontainers.toxiproxy.ToxiproxyContainer + + # Convert parameterized types to raw types (e.g., PostgreSQLContainer -> PostgreSQLContainer) + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.BigQueryEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.BigtableEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.selenium.BrowserWebDriverContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.cassandra.CassandraContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.cockroachdb.CockroachContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.DatastoreEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.db2.Db2Container + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.FirestoreEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.kafka.KafkaContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.localstack.LocalStackContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.mariadb.MariaDBContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.mockserver.MockServerContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.mongodb.MongoDBContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.mssqlserver.MSSQLServerContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.mysql.MySQLContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.neo4j.Neo4jContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.nginx.NginxContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.orientdb.OrientDBContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.postgresql.PostgreSQLContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.PubSubEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.pulsar.PulsarContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.rabbitmq.RabbitMQContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.solr.SolrContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.gcloud.SpannerEmulatorContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.tidb.TiDBContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.toxiproxy.ToxiproxyContainer + - org.openrewrite.java.testing.testcontainers.ConvertToRawType: + fullyQualifiedTypeName: org.testcontainers.trino.TrinoContainer diff --git a/src/test/java/org/openrewrite/java/testing/testcontainers/ConvertToRawTypeTest.java b/src/test/java/org/openrewrite/java/testing/testcontainers/ConvertToRawTypeTest.java new file mode 100644 index 000000000..6ddc392f7 --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/testcontainers/ConvertToRawTypeTest.java @@ -0,0 +1,175 @@ +/* + * 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.testing.testcontainers; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class ConvertToRawTypeTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .recipeFromResources("org.openrewrite.java.testing.testcontainers.Testcontainers2ContainerClasses") + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "testcontainers-1", "nginx")); + } + + @DocumentExample + @Test + void variableDeclaration() { + rewriteRun( + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + + class Foo { + NginxContainer container = new NginxContainer<>(); + } + """, + """ + import org.testcontainers.nginx.NginxContainer; + + class Foo { + NginxContainer container = new NginxContainer(); + } + """ + ) + ); + } + + @Test + void variableDeclarationWithModifier() { + rewriteRun( + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + + class Foo { + private static final NginxContainer container = new NginxContainer<>(); + } + """, + """ + import org.testcontainers.nginx.NginxContainer; + + class Foo { + private static final NginxContainer container = new NginxContainer(); + } + """ + ) + ); + } + + @Test + void methodReturnType() { + rewriteRun( + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + + class Foo { + NginxContainer createContainer() { + return new NginxContainer<>(); + } + } + """, + """ + import org.testcontainers.nginx.NginxContainer; + + class Foo { + NginxContainer createContainer() { + return new NginxContainer(); + } + } + """ + ) + ); + } + + @Test + void newClassExpression() { + rewriteRun( + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + + class Foo { + void test() { + var container = new NginxContainer<>(); + } + } + """, + """ + import org.testcontainers.nginx.NginxContainer; + + class Foo { + void test() { + var container = new NginxContainer(); + } + } + """ + ) + ); + } + + @Test + void onlyChangeImportWhenAlreadyRaw() { + rewriteRun( + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + + class Foo { + NginxContainer container = new NginxContainer(); + } + """, + """ + import org.testcontainers.nginx.NginxContainer; + + class Foo { + NginxContainer container = new NginxContainer(); + } + """ + ) + ); + } + + @Test + void noChangeWhenDifferentType() { + rewriteRun( + spec -> spec.recipe(new ConvertToRawType("org.testcontainers.containers.MySQLContainer")), + //language=java + java( + """ + import org.testcontainers.containers.NginxContainer; + class Foo { + NginxContainer container = new NginxContainer<>(); + } + """ + ) + ); + } +}