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")); + } }