From 49ff90d2d0b2f51f2893aaab23af1d97b69f4c57 Mon Sep 17 00:00:00 2001 From: Mike Solomon Date: Sat, 20 Jan 2024 07:28:37 -0800 Subject: [PATCH] Adopt rewrite-recipe-bom and show Refaster recipes (#35) * test * Add Refaster style recipes as an example * Document what each dependency is for --------- Co-authored-by: Tim te Beek Co-authored-by: Tim te Beek --- build.gradle.kts | 17 ++- .../java/com/yourorg/SimplifyTernary.java | 61 ++++++++++ .../java/com/yourorg/SimplifyTernaryTest.java | 106 ++++++++++++++++++ 3 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/yourorg/SimplifyTernary.java create mode 100644 src/test/java/com/yourorg/SimplifyTernaryTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 05470a8..97491db 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,16 +6,27 @@ plugins { group = "com.yourorg" description = "Rewrite recipes." -// The bom version can also be set to a specific version or latest.release. -val latest = "latest.integration" dependencies { - implementation(platform("org.openrewrite:rewrite-bom:${latest}")) + // The bom version can also be set to a specific version + // https://github.com/openrewrite/rewrite-recipe-bom/releases + implementation(platform("org.openrewrite.recipe:rewrite-recipe-bom:latest.release")) implementation("org.openrewrite:rewrite-java") runtimeOnly("org.openrewrite:rewrite-java-17") + + // Refaster style recipes need the rewrite-templating annotation processor and dependency for generated recipes + // https://github.com/openrewrite/rewrite-templating/releases + annotationProcessor("org.openrewrite:rewrite-templating:latest.release") + implementation("org.openrewrite:rewrite-templating") + // The `@BeforeTemplate` and `@AfterTemplate` annotations are needed for refaster style recipes + compileOnly("com.google.errorprone:error_prone_core:2.19.1:with-dependencies") { + exclude("com.google.auto.service", "auto-service-annotations") + } + // Need to have a slf4j binding to see any output enabled from the parser. runtimeOnly("ch.qos.logback:logback-classic:1.2.+") + // Our recipe converts Guava's `Lists` type testRuntimeOnly("com.google.guava:guava:latest.release") } diff --git a/src/main/java/com/yourorg/SimplifyTernary.java b/src/main/java/com/yourorg/SimplifyTernary.java new file mode 100644 index 0000000..78e86c1 --- /dev/null +++ b/src/main/java/com/yourorg/SimplifyTernary.java @@ -0,0 +1,61 @@ +/* + * 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 com.yourorg; + +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import org.openrewrite.java.template.RecipeDescriptor; + +@RecipeDescriptor( + name = "Simplify ternary expressions", + description = "Simplifies various types of ternary expressions to improve code readability." +) +public class SimplifyTernary { + + @RecipeDescriptor( + name = "Replace `booleanExpression ? true : false` with `booleanExpression`", + description = "Replace ternary expressions like `booleanExpression ? true : false` with `booleanExpression`." + ) + public static class SimplifyTernaryTrueFalse { + + @BeforeTemplate + boolean before(boolean expr) { + return expr ? true : false; + } + + @AfterTemplate + boolean after(boolean expr) { + return expr; + } + } + + @RecipeDescriptor( + name = "Replace `booleanExpression ? false : true` with `!booleanExpression`", + description = "Replace ternary expressions like `booleanExpression ? false : true` with `!booleanExpression`." + ) + public static class SimplifyTernaryFalseTrue { + + @BeforeTemplate + boolean before(boolean expr) { + return expr ? false : true; + } + + @AfterTemplate + boolean after(boolean expr) { + return !(expr); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/yourorg/SimplifyTernaryTest.java b/src/test/java/com/yourorg/SimplifyTernaryTest.java new file mode 100644 index 0000000..dcbe7af --- /dev/null +++ b/src/test/java/com/yourorg/SimplifyTernaryTest.java @@ -0,0 +1,106 @@ +/* + * 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 com.yourorg; + +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class SimplifyTernaryTest implements RewriteTest { + @Test + void simplified() { + rewriteRun( + spec -> spec.recipe(new SimplifyTernaryRecipes()), + //language=java + java( + """ + class Test { + boolean trueCondition1 = true ? true : false; + boolean trueCondition2 = false ? false : true; + boolean trueCondition3 = booleanExpression() ? true : false; + boolean trueCondition4 = trueCondition1 && trueCondition2 ? true : false; + boolean trueCondition5 = !true ? false : true; + boolean trueCondition6 = !false ? true : false; + + boolean falseCondition1 = true ? false : true; + boolean falseCondition2 = !false ? false : true; + boolean falseCondition3 = booleanExpression() ? false : true; + boolean falseCondition4 = trueCondition1 && trueCondition2 ? false : true; + boolean falseCondition5 = !false ? false : true; + boolean falseCondition6 = !true ? true : false; + + boolean binary1 = booleanExpression() && booleanExpression() ? true : false; + boolean binary2 = booleanExpression() && booleanExpression() ? false : true; + boolean binary3 = booleanExpression() || booleanExpression() ? true : false; + boolean binary4 = booleanExpression() || booleanExpression() ? false : true; + + boolean booleanExpression() { + return true; + } + } + """, + """ + class Test { + boolean trueCondition1 = true; + boolean trueCondition2 = true; + boolean trueCondition3 = booleanExpression(); + boolean trueCondition4 = trueCondition1 && trueCondition2; + boolean trueCondition5 = true; + boolean trueCondition6 = true; + + boolean falseCondition1 = false; + boolean falseCondition2 = false; + boolean falseCondition3 = !booleanExpression(); + boolean falseCondition4 = !(trueCondition1 && trueCondition2); + boolean falseCondition5 = false; + boolean falseCondition6 = false; + + boolean binary1 = booleanExpression() && booleanExpression(); + boolean binary2 = !(booleanExpression() && booleanExpression()); + boolean binary3 = booleanExpression() || booleanExpression(); + boolean binary4 = !(booleanExpression() || booleanExpression()); + + boolean booleanExpression() { + return true; + } + } + """ + ) + ); + } + + @Test + void unchanged() { + rewriteRun( + spec -> spec.recipe(new SimplifyTernaryRecipes()), + //language=java + java( + """ + class Test { + boolean unchanged1 = booleanExpression() ? booleanExpression() : !booleanExpression(); + boolean unchanged2 = booleanExpression() ? true : !booleanExpression(); + boolean unchanged3 = booleanExpression() ? booleanExpression() : false; + + boolean booleanExpression() { + return true; + } + } + """ + ) + ); + } +} \ No newline at end of file