From c48a656d31b684bec68fd6444e3fa86678cfe4c8 Mon Sep 17 00:00:00 2001 From: BhavanaPidapa <61456973+BhavanaPidapa@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:21:45 -0600 Subject: [PATCH] Replace `ArrayStoreException` with `TypeNotPresentException` in try/catch using `Class.getAnnotation()` (#613) * draft recipe and test case * Added the recipe to the list * Custom Recipe and test cases for changing exception type * Updated the display name * Added the copyright to the files * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Remove unnecessary trailing newline * Apply suggestions from code review * Fixed the code as mentioned in comments * Use a Precondition, ListUtils, and prevent unnecessary changes --------- Co-authored-by: bhavanapidapa Co-authored-by: Tim te Beek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Tim te Beek --- ...oreExceptionToTypeNotPresentException.java | 65 ++++++++++ .../META-INF/rewrite/java-version-11.yml | 2 + ...xceptionToTypeNotPresentExceptionTest.java | 122 ++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java create mode 100644 src/test/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentExceptionTest.java 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"); + } + } + } + """ + ) + ); + } +}