From 7699208858b8f486150f5fc99d0aa037e3a8efe5 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 27 Oct 2024 16:26:09 +0100 Subject: [PATCH] Simplify booleans when a ternary is returned (#114) * Simplify booleans when a ternary is returned * Add a test that shows SIMPLIFY_BOOLEANS is added --- .../processor/RefasterTemplateProcessor.java | 5 + .../RefasterTemplateProcessorTest.java | 1 + .../resources/refaster/NewBufferedWriter.java | 35 +++++++ .../refaster/NewBufferedWriterRecipe.java | 96 +++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 src/test/resources/refaster/NewBufferedWriter.java create mode 100644 src/test/resources/refaster/NewBufferedWriterRecipe.java 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 1a59b26..b1b67f3 100644 --- a/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java +++ b/src/main/java/org/openrewrite/java/template/processor/RefasterTemplateProcessor.java @@ -437,6 +437,11 @@ public void visitBinary(JCTree.JCBinary jcBinary) { super.visitBinary(jcBinary); } + @Override + public void visitConditional(JCTree.JCConditional jcConditional) { + found = true; + } + @Override public void visitUnary(JCTree.JCUnary jcUnary) { found |= jcUnary.type.getTag() == TypeTag.BOOLEAN; diff --git a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java index f8c65a1..d08a760 100644 --- a/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java +++ b/src/test/java/org/openrewrite/java/template/RefasterTemplateProcessorTest.java @@ -43,6 +43,7 @@ class RefasterTemplateProcessorTest { "CharacterEscapeAnnotation", "MethodThrows", "NestedPreconditions", + "NewBufferedWriter", "UseStringIsEmpty", "SimplifyBooleans", "FindListAdd", diff --git a/src/test/resources/refaster/NewBufferedWriter.java b/src/test/resources/refaster/NewBufferedWriter.java new file mode 100644 index 0000000..21be8e8 --- /dev/null +++ b/src/test/resources/refaster/NewBufferedWriter.java @@ -0,0 +1,35 @@ +/* + * 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 java.io.BufferedWriter; +import java.io.IOException; + +class NewBufferedWriter { + @BeforeTemplate + BufferedWriter before(String f, Boolean b) throws IOException { + return new BufferedWriter(new java.io.FileWriter(f, b)); + } + + @AfterTemplate + BufferedWriter after(String f, Boolean b) throws IOException { + return java.nio.file.Files.newBufferedWriter(new java.io.File(f).toPath(), b ? + java.nio.file.StandardOpenOption.APPEND : java.nio.file.StandardOpenOption.CREATE); + } +} diff --git a/src/test/resources/refaster/NewBufferedWriterRecipe.java b/src/test/resources/refaster/NewBufferedWriterRecipe.java new file mode 100644 index 0000000..419f727 --- /dev/null +++ b/src/test/resources/refaster/NewBufferedWriterRecipe.java @@ -0,0 +1,96 @@ +/* + * 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.jspecify.annotations.NullMarked; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaParser; +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.function.*; +import org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor; +import org.openrewrite.java.tree.*; + +import javax.annotation.Generated; +import java.util.*; + +import static org.openrewrite.java.template.internal.AbstractRefasterJavaVisitor.EmbeddingOption.*; + +/** + * OpenRewrite recipe created for Refaster template {@code NewBufferedWriter}. + */ +@SuppressWarnings("all") +@NullMarked +@Generated("org.openrewrite.java.template.processor.RefasterTemplateProcessor") +public class NewBufferedWriterRecipe extends Recipe { + + /** + * Instantiates a new instance. + */ + public NewBufferedWriterRecipe() {} + + @Override + public String getDisplayName() { + return "Refaster template `NewBufferedWriter`"; + } + + @Override + public String getDescription() { + return "Recipe created for the following Refaster template:\n```java\nclass NewBufferedWriter {\n \n @BeforeTemplate()\n BufferedWriter before(String f, Boolean b) throws IOException {\n return new BufferedWriter(new java.io.FileWriter(f, b));\n }\n \n @AfterTemplate()\n BufferedWriter after(String f, Boolean b) throws IOException {\n return java.nio.file.Files.newBufferedWriter(new java.io.File(f).toPath(), b ? java.nio.file.StandardOpenOption.APPEND : java.nio.file.StandardOpenOption.CREATE);\n }\n}\n```\n."; + } + + @Override + public TreeVisitor getVisitor() { + JavaVisitor javaVisitor = new AbstractRefasterJavaVisitor() { + final JavaTemplate before = JavaTemplate + .builder("new java.io.BufferedWriter(new java.io.FileWriter(#{f:any(java.lang.String)}, #{b:any(java.lang.Boolean)}))") + .build(); + final JavaTemplate after = JavaTemplate + .builder("java.nio.file.Files.newBufferedWriter(new java.io.File(#{f:any(java.lang.String)}).toPath(), #{b:any(java.lang.Boolean)} ? java.nio.file.StandardOpenOption.APPEND : java.nio.file.StandardOpenOption.CREATE)") + .build(); + + @Override + public J visitNewClass(J.NewClass elem, ExecutionContext ctx) { + JavaTemplate.Matcher matcher; + if ((matcher = before.matcher(getCursor())).find()) { + maybeRemoveImport("java.io.FileWriter"); + return embed( + after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0), matcher.parameter(1)), + getCursor(), + ctx, + SHORTEN_NAMES, SIMPLIFY_BOOLEANS + ); + } + return super.visitNewClass(elem, ctx); + } + + }; + return Preconditions.check( + Preconditions.and( + new UsesType<>("java.io.BufferedWriter", true), + new UsesType<>("java.io.FileWriter", true), + new UsesMethod<>("java.io.BufferedWriter (..)", true), + new UsesMethod<>("java.io.FileWriter (..)", true) + ), + javaVisitor + ); + } +}