diff options
Diffstat (limited to 'src')
8 files changed, 167 insertions, 86 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java index a0b9005..81fd091 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java @@ -18,6 +18,7 @@ public class CodeWriter implements AutoCloseable { public static class InMemoryCodeWriterFile implements CodeWriterFile { private final Optional<String> originalContents; private final StringWriter stringWriter; + private boolean writerOpened; public InMemoryCodeWriterFile( Optional<String> originalContents, @@ -25,6 +26,7 @@ public class CodeWriter implements AutoCloseable { ) { this.originalContents = originalContents; this.stringWriter = stringWriter; + this.writerOpened = false; } @Override @@ -38,8 +40,13 @@ public class CodeWriter implements AutoCloseable { @Override public Writer openWriter() throws IOException { + this.writerOpened = true; return stringWriter; } + + public boolean isWriterOpened() { + return writerOpened; + } } public record CustomAreas( @@ -90,11 +97,16 @@ public class CodeWriter implements AutoCloseable { } } - public static CodeWriter file( + public interface Write { + void write(CodeWriter writer) throws IOException; + } + + public static void writeTo( Path path, - String lineCommentStart + String lineCommentStart, + Write write ) throws IOException { - return file( + writeTo( new CodeWriterFile() { @Override public String readString() throws IOException { @@ -107,20 +119,31 @@ public class CodeWriter implements AutoCloseable { return new FileWriter(path.toFile()); } }, - lineCommentStart + lineCommentStart, + write ); } - public static CodeWriter file( + public static void writeTo( CodeWriterFile file, - String lineCommentStart + String lineCommentStart, + Write write ) throws IOException { + var originalContents = readFile(file); + + var header = lineCommentStart + " Generated by hobgoblin.\n\n"; + if (originalContents.isPresent() && !originalContents.get().startsWith(header)) { + return; + } + var customAreaStart = lineCommentStart + " Custom area start: "; var customAreaEnd = lineCommentStart + " Custom area end: "; + var customAreas = readCustomAreas(file, customAreaStart, customAreaEnd); - var writer = file.openWriter(); - // TODO: warn if custom areas are unused? - return new CodeWriter(writer, lineCommentStart, customAreas); + try (var writer = file.openWriter()) { + // TODO: warn if custom areas are unused? + write.write(new CodeWriter(writer, header, customAreas)); + } } private static CustomAreas readCustomAreas( @@ -136,23 +159,30 @@ public class CodeWriter implements AutoCloseable { } } + private static Optional<String> readFile(CodeWriterFile file) throws IOException { + try { + return Optional.of(file.readString()); + } catch (NoSuchFileException exception) { + return Optional.empty(); + } + } + private final Writer writer; - private final String lineCommentStart; + private final String header; private final CustomAreas customAreas; private int indent; private boolean pendingIndent; - public CodeWriter(Writer writer, String lineCommentStart, CustomAreas customAreas) { + public CodeWriter(Writer writer, String header, CustomAreas customAreas) { this.writer = writer; - this.lineCommentStart = lineCommentStart; + this.header = header; this.customAreas = customAreas; this.indent = 0; this.pendingIndent = false; } public void writeHeader() throws IOException { - writer.write(lineCommentStart); - writer.write(" Generated by hobgoblin.\n\n"); + writer.write(header); } public void write(String value) throws IOException { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java index 1325149..d7f4bb0 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java @@ -29,9 +29,11 @@ public class JavaGenerator { var javaCompilationUnitPath = sourceRootDirectory .resolve(javaCompilationUnit.packageName().parts().stream().map(JavaIdentifier::value).collect(Collectors.joining(File.separator))) .resolve(javaCompilationUnit.typeDeclaration().name().value() + ".java"); - try (var writer = JavaWriter.file(javaCompilationUnitPath)) { - writer.writeCompilationUnit(javaCompilationUnit); - } + + JavaWriter.writeTo( + javaCompilationUnitPath, + writer -> writer.writeCompilationUnit(javaCompilationUnit) + ); } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java index 0a0290d..22b6d7d 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGenerator.java @@ -27,9 +27,9 @@ public class RustGenerator { .map(name -> name.value()) .collect(Collectors.joining(File.separator)) + ".rs" ); - try (var writer = RustWriter.file(path)) { + RustWriter.writeTo(path, writer -> { writer.writeModule(rustModule); - } + }); } public RustPath generateRustTypeExpression(Type type) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java index b593364..7af7e01 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriter.java @@ -15,18 +15,24 @@ import static org.zwobble.hobgoblin.compiler.output.CodeWriter.writeWithSeparato public class JavaWriter implements AutoCloseable { private static final String LINE_COMMENT_START = "//"; - public static JavaWriter file(CodeWriter.CodeWriterFile file) throws IOException { - return new JavaWriter(CodeWriter.file( - file, - LINE_COMMENT_START - )); + public interface Write { + void write(JavaWriter writer) throws IOException; } - public static JavaWriter file(Path path) throws IOException { - return new JavaWriter(CodeWriter.file( + public static void writeTo(Path path, Write write) throws IOException { + CodeWriter.writeTo( path, - LINE_COMMENT_START - )); + LINE_COMMENT_START, + writer -> write.write(new JavaWriter(writer)) + ); + } + + public static void writeTo(CodeWriter.CodeWriterFile file, Write write) throws IOException { + CodeWriter.writeTo( + file, + LINE_COMMENT_START, + writer -> write.write(new JavaWriter(writer)) + ); } private final CodeWriter writer; diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java index 2d7e9ed..d0552ad 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java @@ -15,18 +15,24 @@ import static org.zwobble.hobgoblin.compiler.output.CodeWriter.writeWithSeparato public class RustWriter implements AutoCloseable { private static final String LINE_COMMENT_START = "//"; - public static RustWriter file(CodeWriter.CodeWriterFile file) throws IOException { - return new RustWriter(CodeWriter.file( - file, - LINE_COMMENT_START - )); + public interface Write { + void write(RustWriter writer) throws IOException; } - public static RustWriter file(Path path) throws IOException { - return new RustWriter(CodeWriter.file( + public static void writeTo(Path path, Write write) throws IOException { + CodeWriter.writeTo( path, - LINE_COMMENT_START - )); + LINE_COMMENT_START, + writer -> write.write(new RustWriter(writer)) + ); + } + + public static void writeTo(CodeWriter.CodeWriterFile file, Write write) throws IOException { + CodeWriter.writeTo( + file, + LINE_COMMENT_START, + writer -> write.write(new RustWriter(writer)) + ); } private final CodeWriter writer; diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/CodeWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/CodeWriterTests.java index b0ff40c..2b3ad6d 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/CodeWriterTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/CodeWriterTests.java @@ -14,17 +14,21 @@ public class CodeWriterTests { @Test public void whenFileDoesNotExistThenCustomAreasAreEmpty() throws IOException { var stringWriter = new StringWriter(); - var codeWriter = CodeWriter.file( - new CodeWriter.InMemoryCodeWriterFile(Optional.empty(), stringWriter), - "//" + var file = new CodeWriter.InMemoryCodeWriterFile(Optional.empty(), stringWriter); + + CodeWriter.writeTo( + file, + "//", + codeWriter -> { + codeWriter.writeHeader(); + codeWriter.write("Before"); + codeWriter.newLine(); + codeWriter.writeCustomArea("body"); + codeWriter.write("After"); + codeWriter.newLine(); + } ); - codeWriter.writeHeader(); - codeWriter.write("Before"); - codeWriter.newLine(); - codeWriter.writeCustomArea("body"); - codeWriter.write("After"); - codeWriter.newLine(); assertThat(stringWriter.toString(), equalTo(""" // Generated by hobgoblin. @@ -39,21 +43,28 @@ public class CodeWriterTests { @Test public void whenExistingFileIsMissingCustomAreaThenCustomAreaIsEmpty() throws IOException { var stringWriter = new StringWriter(); - var codeWriter = CodeWriter.file( - new CodeWriter.InMemoryCodeWriterFile(Optional.of(""), stringWriter), - "//" - ); + var originalContents = """ + // Generated by hobgoblin. - codeWriter.writeHeader(); - codeWriter.write("Before"); - codeWriter.newLine(); - codeWriter.writeCustomArea("body"); - codeWriter.write("After"); - codeWriter.newLine(); + """; + var file = new CodeWriter.InMemoryCodeWriterFile(Optional.of(originalContents), stringWriter); + + CodeWriter.writeTo( + file, + "//", + codeWriter -> { + codeWriter.writeHeader(); + codeWriter.write("Before"); + codeWriter.newLine(); + codeWriter.writeCustomArea("body"); + codeWriter.write("After"); + codeWriter.newLine(); + } + ); assertThat(stringWriter.toString(), equalTo(""" // Generated by hobgoblin. - + Before // Custom area start: body // Custom area end: body @@ -65,6 +76,8 @@ public class CodeWriterTests { public void whenExistingFileHasCustomAreasThenCustomAreaContentsArePreserved() throws IOException { var stringWriter = new StringWriter(); var originalContents = """ + // Generated by hobgoblin. + // Custom area start: head Custom head. // Custom area end: head @@ -72,18 +85,21 @@ public class CodeWriterTests { Custom body. // Custom area end: body """; - var codeWriter = CodeWriter.file( - new CodeWriter.InMemoryCodeWriterFile(Optional.of(originalContents), stringWriter), - "//" - ); + var file = new CodeWriter.InMemoryCodeWriterFile(Optional.of(originalContents), stringWriter); - codeWriter.writeHeader(); - codeWriter.writeCustomArea("head"); - codeWriter.writeCustomArea("body"); + CodeWriter.writeTo( + file, + "//", + codeWriter -> { + codeWriter.writeHeader(); + codeWriter.writeCustomArea("head"); + codeWriter.writeCustomArea("body"); + } + ); assertThat(stringWriter.toString(), equalTo(""" // Generated by hobgoblin. - + // Custom area start: head Custom head. // Custom area end: head @@ -92,4 +108,31 @@ public class CodeWriterTests { // Custom area end: body """)); } + + @Test + public void whenExistingFileIsMissingHeaderThenNothingIsWritten() throws IOException { + var stringWriter = new StringWriter(); + var originalContents = """ + // Custom area start: head + Custom head. + // Custom area end: head + // Custom area start: body + Custom body. + // Custom area end: body + """; + var file = new CodeWriter.InMemoryCodeWriterFile(Optional.of(originalContents), stringWriter); + + CodeWriter.writeTo( + file, + "//", + codeWriter -> { + codeWriter.writeHeader(); + codeWriter.writeCustomArea("head"); + codeWriter.writeCustomArea("body"); + } + ); + + assertThat(stringWriter.toString(), equalTo("")); + assertThat(file.isWriterOpened(), equalTo(false)); + } } diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java index 2889032..9b16328 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/java/JavaWriterTests.java @@ -1698,7 +1698,9 @@ public class JavaWriterTests { var string = write( writer -> writer.writeTypeDeclaration(java), """ - public class Point { + // Generated by hobgoblin. + + public class Point { // Custom area start: Point body // <custom area> // Custom area end: Point body @@ -1717,24 +1719,20 @@ public class JavaWriterTests { // == Doc comments == - private String write(Write write) throws IOException { + private String write(JavaWriter.Write write) throws IOException { return write(write, Optional.empty()); } - private String write(Write write, String originalContents) throws IOException { + private String write(JavaWriter.Write write, String originalContents) throws IOException { return write(write, Optional.of(originalContents)); } - private String write(Write write, Optional<String> originalContents) throws IOException { + private String write(JavaWriter.Write write, Optional<String> originalContents) throws IOException { var stringWriter = new StringWriter(); - var javaWriter = JavaWriter.file( - new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter) + JavaWriter.writeTo( + new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter), + write ); - write.write(javaWriter); return stringWriter.toString(); } - - private interface Write { - void write(JavaWriter writer) throws IOException; - } } diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java index e9edb72..4a81031 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java @@ -1204,24 +1204,20 @@ public class RustWriterTests { assertThat(string, equalTo("r#const")); } - private String write(Write write) throws IOException { + private String write(RustWriter.Write write) throws IOException { return write(write, Optional.empty()); } - private String write(Write write, String originalContents) throws IOException { + private String write(RustWriter.Write write, String originalContents) throws IOException { return write(write, Optional.of(originalContents)); } - private String write(Write write, Optional<String> originalContents) throws IOException { + private String write(RustWriter.Write write, Optional<String> originalContents) throws IOException { var stringWriter = new StringWriter(); - var rustWriter = RustWriter.file( - new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter) + RustWriter.writeTo( + new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter), + write ); - write.write(rustWriter); return stringWriter.toString(); } - - private interface Write { - void write(RustWriter writer) throws IOException; - } } |
