diff --git a/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java b/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java index 8e0de89c..28627840 100644 --- a/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java @@ -257,7 +257,7 @@ public void visitClassDef(JCTree.JCClassDecl classDecl) { maybeRemoveImports(staticImports, recipe, entry.getValue(), descriptor.afterTemplate); List embedOptions = new ArrayList<>(); - if (getType(descriptor.afterTemplate) == JCTree.JCParens.class) { + if (getType(descriptor.afterTemplate) == JCTree.JCParens.class || getType(descriptor.afterTemplate) == JCTree.JCUnary.class) { embedOptions.add("REMOVE_PARENS"); } // TODO check if after template contains type or member references diff --git a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java index 559e2a5c..1576b7c6 100644 --- a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java +++ b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java @@ -69,6 +69,7 @@ void skipRecipeGeneration(String recipeName) { "MultipleDereferences", "ShouldAddImports", "ShouldSupportNestedClasses", + "SimplifyTernary", }) void nestedRecipes(String recipeName) { Compilation compilation = compile("refaster/" + recipeName + ".java"); diff --git a/src/test/resources/refaster/ShouldSupportNestedClassesRecipes.java b/src/test/resources/refaster/ShouldSupportNestedClassesRecipes.java index 7b0c083e..e8290f02 100644 --- a/src/test/resources/refaster/ShouldSupportNestedClassesRecipes.java +++ b/src/test/resources/refaster/ShouldSupportNestedClassesRecipes.java @@ -86,7 +86,7 @@ public J visitBinary(J.Binary elem, ExecutionContext ctx) { after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)), getCursor(), ctx, - SHORTEN_NAMES, SIMPLIFY_BOOLEANS + REMOVE_PARENS, SHORTEN_NAMES, SIMPLIFY_BOOLEANS ); } return super.visitBinary(elem, ctx); diff --git a/src/test/resources/refaster/SimplifyTernary.java b/src/test/resources/refaster/SimplifyTernary.java new file mode 100644 index 00000000..3d72a136 --- /dev/null +++ b/src/test/resources/refaster/SimplifyTernary.java @@ -0,0 +1,57 @@ +/* + * 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 foo; + +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import org.openrewrite.java.template.RecipeDescriptor; + +public class SimplifyTernary { + + @RecipeDescriptor( + name = "Simplify ternary expressions", + description = "Simplify `expr ? true : false` to `expr`." + ) + public static class SimplifyTernaryTrueFalse { + + @BeforeTemplate + boolean before(boolean expr) { + return expr ? true : false; + } + + @AfterTemplate + boolean after(boolean expr) { + return expr; + } + } + + @RecipeDescriptor( + name = "Simplify ternary expressions", + description = "Simplify `expr ? false : true` to `!expr`." + ) + public static class SimplifyTernaryFalseTrue { + + @BeforeTemplate + boolean before(boolean expr) { + return expr ? false : true; + } + + @AfterTemplate + boolean after(boolean expr) { + return !(expr); + } + } +} diff --git a/src/test/resources/refaster/SimplifyTernaryRecipes.java b/src/test/resources/refaster/SimplifyTernaryRecipes.java new file mode 100644 index 00000000..3468514d --- /dev/null +++ b/src/test/resources/refaster/SimplifyTernaryRecipes.java @@ -0,0 +1,159 @@ +/* + * 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 foo; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.lang.NonNullApi; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.search.*; +import org.openrewrite.java.template.Primitive; +import org.openrewrite.java.template.Semantics; +import org.openrewrite.java.template.function.*; +import org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor; +import org.openrewrite.java.tree.*; + +import java.util.*; + +import static org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor.EmbeddingOption.*; + +/** + * OpenRewrite recipes created for Refaster template {@code foo.SimplifyTernary}. + */ +@SuppressWarnings("all") +public class SimplifyTernaryRecipes extends Recipe { + /** + * Instantiates a new instance. + */ + public SimplifyTernaryRecipes() {} + + @Override + public String getDisplayName() { + return "`SimplifyTernary` Refaster recipes"; + } + + @Override + public String getDescription() { + return "Refaster template recipes for `foo.SimplifyTernary`."; + } + + @Override + public List getRecipeList() { + return Arrays.asList( + new SimplifyTernaryTrueFalseRecipe(), + new SimplifyTernaryFalseTrueRecipe() + ); + } + + /** + * OpenRewrite recipe created for Refaster template {@code SimplifyTernary.SimplifyTernaryTrueFalse}. + */ + @SuppressWarnings("all") + @NonNullApi + public static class SimplifyTernaryTrueFalseRecipe extends Recipe { + + /** + * Instantiates a new instance. + */ + public SimplifyTernaryTrueFalseRecipe() {} + + @Override + public String getDisplayName() { + return "Simplify ternary expressions"; + } + + @Override + public String getDescription() { + return "Simplify `expr ? true : false` to `expr`."; + } + + @Override + public TreeVisitor getVisitor() { + JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() { + final JavaTemplate before = Semantics.expression(this, "before", (@Primitive Boolean expr) -> expr ? true : false).build(); + final JavaTemplate after = Semantics.expression(this, "after", (@Primitive Boolean expr) -> expr).build(); + + @Override + public J visitExpression(Expression elem, ExecutionContext ctx) { + JavaTemplate.Matcher matcher; + if ((matcher = before.matcher(getCursor())).find()) { + return embed( + after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)), + getCursor(), + ctx, + SHORTEN_NAMES, SIMPLIFY_BOOLEANS + ); + } + return super.visitExpression(elem, ctx); + } + + }; + return javaVisitor; + } + } + + /** + * OpenRewrite recipe created for Refaster template {@code SimplifyTernary.SimplifyTernaryFalseTrue}. + */ + @SuppressWarnings("all") + @NonNullApi + public static class SimplifyTernaryFalseTrueRecipe extends Recipe { + + /** + * Instantiates a new instance. + */ + public SimplifyTernaryFalseTrueRecipe() {} + + @Override + public String getDisplayName() { + return "Simplify ternary expressions"; + } + + @Override + public String getDescription() { + return "Simplify `expr ? false : true` to `!expr`."; + } + + @Override + public TreeVisitor getVisitor() { + JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() { + final JavaTemplate before = Semantics.expression(this, "before", (@Primitive Boolean expr) -> expr ? false : true).build(); + final JavaTemplate after = Semantics.expression(this, "after", (@Primitive Boolean expr) -> !(expr)).build(); + + @Override + public J visitExpression(Expression elem, ExecutionContext ctx) { + JavaTemplate.Matcher matcher; + if ((matcher = before.matcher(getCursor())).find()) { + return embed( + after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)), + getCursor(), + ctx, + REMOVE_PARENS, SHORTEN_NAMES, SIMPLIFY_BOOLEANS + ); + } + return super.visitExpression(elem, ctx); + } + + }; + return javaVisitor; + } + } + +} diff --git a/src/test/resources/refaster/UseStringIsEmptyRecipe.java b/src/test/resources/refaster/UseStringIsEmptyRecipe.java index 200fe612..20a43d42 100644 --- a/src/test/resources/refaster/UseStringIsEmptyRecipe.java +++ b/src/test/resources/refaster/UseStringIsEmptyRecipe.java @@ -67,7 +67,7 @@ public J visitBinary(J.Binary elem, ExecutionContext ctx) { after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)), getCursor(), ctx, - SHORTEN_NAMES, SIMPLIFY_BOOLEANS + REMOVE_PARENS, SHORTEN_NAMES, SIMPLIFY_BOOLEANS ); } return super.visitBinary(elem, ctx);