From 4cbb7b0b3556bc09a817edaff70dbd8e3061c69c Mon Sep 17 00:00:00 2001 From: Michael Dowling Date: Fri, 27 Sep 2019 13:20:10 -0700 Subject: [PATCH] Add helper methods for CodeWriter#openBlock The openBlock method now takes a Runnable that is called inside of the block. The block is then automatically closed when the Runnable completes. This makes code the uses CodeWriter easier to follow since it forces indentation and doesn't require the closing "}" to be explicitly added. --- .../amazon/smithy/utils/CodeWriter.java | 130 ++++++++++++++++++ .../amazon/smithy/utils/CodeWriterTest.java | 68 +++++++++ 2 files changed, 198 insertions(+) diff --git a/smithy-utils/src/main/java/software/amazon/smithy/utils/CodeWriter.java b/smithy-utils/src/main/java/software/amazon/smithy/utils/CodeWriter.java index b77bdece2cd..1b733962926 100644 --- a/smithy-utils/src/main/java/software/amazon/smithy/utils/CodeWriter.java +++ b/smithy-utils/src/main/java/software/amazon/smithy/utils/CodeWriter.java @@ -780,6 +780,136 @@ public final CodeWriter openBlock(String textBeforeNewline, Object... args) { return write(textBeforeNewline, args).indent(); } + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + *
{@code
+     * CodeWriter writer = CodeWriter.createDefault();
+     * writer.openBlock("public final class $L {", "}", "Foo", () -> {
+     *     writer.openBlock("public void main(String[] args) {", "}", () -> {
+     *         writer.write("System.out.println(args[0]);");
+     *     })
+     * });
+     * }
+ * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param arg1 First positional argument to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, Object arg1, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{arg1}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param arg1 First positional argument to substitute into {@code textBeforeNewline}. + * @param arg2 Second positional argument to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, + Object arg1, Object arg2, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{arg1, arg2}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param arg1 First positional argument to substitute into {@code textBeforeNewline}. + * @param arg2 Second positional argument to substitute into {@code textBeforeNewline}. + * @param arg3 Third positional argument to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, + Object arg1, Object arg2, Object arg3, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{arg1, arg2, arg3}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param arg1 First positional argument to substitute into {@code textBeforeNewline}. + * @param arg2 Second positional argument to substitute into {@code textBeforeNewline}. + * @param arg3 Third positional argument to substitute into {@code textBeforeNewline}. + * @param arg4 Fourth positional argument to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, + Object arg1, Object arg2, Object arg3, Object arg4, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{arg1, arg2, arg3, arg4}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param arg1 First positional argument to substitute into {@code textBeforeNewline}. + * @param arg2 Second positional argument to substitute into {@code textBeforeNewline}. + * @param arg3 Third positional argument to substitute into {@code textBeforeNewline}. + * @param arg4 Fourth positional argument to substitute into {@code textBeforeNewline}. + * @param arg5 Fifth positional argument to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, + Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Runnable f) { + return openBlock(textBeforeNewline, textAfterNewline, new Object[]{arg1, arg2, arg3, arg4, arg5}, f); + } + + /** + * Opens a block of syntax by writing {@code textBeforeNewline}, a newline, then + * indenting, then executes the given {@code Runnable}, then closes the block of + * syntax by writing a newline, dedenting, then writing {@code textAfterNewline}. + * + * @param textBeforeNewline Text to write before writing a newline and indenting. + * @param textAfterNewline Text to write after writing a newline and indenting. + * @param args Arguments to substitute into {@code textBeforeNewline}. + * @param f Runnable function to execute inside of the block. + * @return Returns the {@code CodeWriter}. + */ + public final CodeWriter openBlock(String textBeforeNewline, String textAfterNewline, Object[] args, Runnable f) { + write(textBeforeNewline, args).indent(); + f.run(); + closeBlock(textAfterNewline); + return this; + } + /** * Closes a block of syntax by writing a newline, dedenting, then writing text. * diff --git a/smithy-utils/src/test/java/software/amazon/smithy/utils/CodeWriterTest.java b/smithy-utils/src/test/java/software/amazon/smithy/utils/CodeWriterTest.java index c7dac80c02f..5ede05a0c7f 100644 --- a/smithy-utils/src/test/java/software/amazon/smithy/utils/CodeWriterTest.java +++ b/smithy-utils/src/test/java/software/amazon/smithy/utils/CodeWriterTest.java @@ -429,4 +429,72 @@ public void canIntegrateInlineSectionsWithComplexStates() { + " * # Yes\n" + " */\n")); } + + @Test + public void hasOpenBlockRunnable0() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public {", "}", () -> { + writer.write("hi();"); + }) + .toString(); + + assertThat(result, equalTo("public {\n hi();\n}\n")); + } + + @Test + public void hasOpenBlockRunnable1() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public final class $L {", "}", "Foo", () -> { + writer.openBlock("public void main(String[] args) {", "}", () -> { + writer.write("System.out.println(args[0]);"); + }); + }) + .toString(); + + assertThat(result, equalTo("public final class Foo {\n public void main(String[] args) {\n System.out.println(args[0]);\n }\n}\n")); + } + + @Test + public void hasOpenBlockRunnable2() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public $L $L {", "}", "1", "2", () -> { + writer.write("hi();"); + }) + .toString(); + + assertThat(result, equalTo("public 1 2 {\n hi();\n}\n")); + } + + @Test + public void hasOpenBlockRunnable3() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public $L $L $L {", "}", "1", "2", "3", () -> { + writer.write("hi();"); + }) + .toString(); + + assertThat(result, equalTo("public 1 2 3 {\n hi();\n}\n")); + } + + @Test + public void hasOpenBlockRunnable4() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public $L $L $L $L {", "}", "1", "2", "3", "4", () -> { + writer.write("hi();"); + }) + .toString(); + + assertThat(result, equalTo("public 1 2 3 4 {\n hi();\n}\n")); + } + + @Test + public void hasOpenBlockRunnable5() { + CodeWriter writer = CodeWriter.createDefault(); + String result = writer.openBlock("public $L $L $L $L $L {", "}", "1", "2", "3", "4", "5", () -> { + writer.write("hi();"); + }) + .toString(); + + assertThat(result, equalTo("public 1 2 3 4 5 {\n hi();\n}\n")); + } }