diff --git a/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java b/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java new file mode 100644 index 000000000..a9048b347 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java @@ -0,0 +1,65 @@ +/* + * 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; + +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.ChangeType; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.search.FindMethods; +import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.TypeUtils; + +public class ArrayStoreExceptionToTypeNotPresentException extends Recipe { + + private static final String ARRAY_STORE_EXCEPTION = "java.lang.ArrayStoreException"; + private static final String TYPE_NOT_PRESENT_EXCEPTION = "java.lang.TypeNotPresentException"; + + @Override + public String getDisplayName() { + return "Catch `TypeNotPresentException` thrown by `Class.getAnnotation()`"; + } + + @Override + public String getDescription() { + return "Replace catch blocks for `ArrayStoreException` around `Class.getAnnotation()` with `TypeNotPresentException` to ensure compatibility with Java 11+."; + } + + @Override + public TreeVisitor getVisitor() { + String classGetAnnotationPattern = "java.lang.Class getAnnotation(java.lang.Class)"; + return Preconditions.check(new UsesMethod<>(classGetAnnotationPattern), new JavaIsoVisitor() { + @Override + public J.Try visitTry(J.Try tryStatement, ExecutionContext ctx) { + J.Try try_ = super.visitTry(tryStatement, ctx); + if (FindMethods.find(try_, classGetAnnotationPattern).isEmpty()) { + return try_; + } + return try_.withCatches(ListUtils.map(try_.getCatches(), catch_ -> { + if (TypeUtils.isOfClassType(catch_.getParameter().getType(), ARRAY_STORE_EXCEPTION)) { + return (J.Try.Catch) new ChangeType(ARRAY_STORE_EXCEPTION, TYPE_NOT_PRESENT_EXCEPTION, true) + .getVisitor().visit(catch_, ctx); + } + return catch_; + })); + } + }); + } +} diff --git a/src/main/resources/META-INF/rewrite/java-version-11.yml b/src/main/resources/META-INF/rewrite/java-version-11.yml index ed2edac24..2ce31ac4a 100644 --- a/src/main/resources/META-INF/rewrite/java-version-11.yml +++ b/src/main/resources/META-INF/rewrite/java-version-11.yml @@ -73,6 +73,8 @@ recipeList: - org.openrewrite.scala.migrate.UpgradeScala_2_12 - org.openrewrite.java.migrate.ReplaceComSunAWTUtilitiesMethods - org.openrewrite.java.migrate.ReplaceLocalizedStreamMethods + - org.openrewrite.java.migrate.ArrayStoreExceptionToTypeNotPresentException + --- type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.java.migrate.UpgradeBuildToJava11 diff --git a/src/test/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentExceptionTest.java b/src/test/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentExceptionTest.java new file mode 100644 index 000000000..4843e8981 --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentExceptionTest.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; + +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 ArrayStoreExceptionToTypeNotPresentExceptionTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new ArrayStoreExceptionToTypeNotPresentException()); + } + + @DocumentExample + @Test + void replaceCaughtException() { + rewriteRun( + //language=java + java( + """ + import java.lang.annotation.*; + import java.util.*; + + public class Test { + public void testMethod() { + try { + Object o = "test"; + o.getClass().getAnnotation(Override.class); + } catch (ArrayStoreException e) { + System.out.println("Caught Exception"); + } + try { + Object.class.getAnnotation(Override.class); + } catch (ArrayStoreException e) { + System.out.println("Caught ArrayStoreException"); + } + } + } + """, + """ + import java.lang.annotation.*; + import java.util.*; + + public class Test { + public void testMethod() { + try { + Object o = "test"; + o.getClass().getAnnotation(Override.class); + } catch (TypeNotPresentException e) { + System.out.println("Caught Exception"); + } + try { + Object.class.getAnnotation(Override.class); + } catch (TypeNotPresentException e) { + System.out.println("Caught ArrayStoreException"); + } + } + } + """ + ) + ); + } + + @Test + void retainOtherCaughtExceptions() { + rewriteRun( + //language=java + java( + """ + public class Test { + public void testMethod() { + try { + Object o = "test"; + o.getClass().getAnnotation(Override.class); + } catch (NullPointerException e) { + System.out.println("Caught Exception"); + } + } + } + """ + ) + ); + } + + @Test + void retainArrayStoreExceptionWithoutClassGetAnnotation() { + rewriteRun( + //language=java + java( + """ + public class Test { + public void testMethod() { + try { + Object o = "test"; + } catch (ArrayStoreException e) { + System.out.println("Caught Exception"); + } + } + } + """ + ) + ); + } +}