diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-05-23 21:27:24 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-05-23 21:42:22 +0100 |
| commit | 5c0b6c30c84067dcc36dbdc9d8e4075e94490131 (patch) | |
| tree | f1b557f3ec55cd2f0c561fe7a315b41f1927a6d0 /src/main | |
| parent | 1cc30d7d45377b98ee754e248149bf2f0cc485fb (diff) | |
Preserve existing custom areas
Diffstat (limited to 'src/main')
4 files changed, 126 insertions, 30 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 3e08c85..b8b0709 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java @@ -4,21 +4,92 @@ import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.util.*; public class CodeWriter implements AutoCloseable { - public static CodeWriter file(Path path) throws IOException { + public record CustomAreas( + Map<String, List<String>> existing, + String customAreaStart, + String customAreaEnd + ) { + public static CustomAreas read( + String existingString, + String customAreaStart, + String customAreaEnd + ) { + var existing = new HashMap<String, List<String>>(); + + Iterable<String> lines = () -> existingString.lines().iterator(); + Optional<String> name = Optional.empty(); + var customAreaLines = new ArrayList<String>(); + for (var line : lines) { + var trimmedLine = line.trim(); + if (trimmedLine.startsWith(customAreaStart)) { + name = Optional.of(trimmedLine.substring(customAreaStart.length())); + } else if (name.isPresent() && trimmedLine.startsWith(customAreaEnd + name.get())) { + existing.put(name.get(), customAreaLines); + customAreaLines = new ArrayList<>(); + name = Optional.empty(); + } else if (name.isPresent()) { + customAreaLines.add(line); + } + } + + return new CustomAreas(existing, customAreaStart, customAreaEnd); + } + + public static CustomAreas empty( + String customAreaStart, + String customAreaEnd + ) { + return new CustomAreas(Map.of(), customAreaStart, customAreaEnd); + } + + public Iterable<String> lines(String name) { + var lines = this.existing.get(name); + if (lines == null) { + return List.of(); + } else { + return lines; + } + } + } + + public static CodeWriter file( + Path path, + String customAreaStart, + String customAreaEnd + ) throws IOException { + var customAreas = readCustomAreas(path, customAreaStart, customAreaEnd); Files.createDirectories(path.getParent()); var writer = new FileWriter(path.toFile()); - return new CodeWriter(writer); + // TODO: warn if custom areas are unused? + return new CodeWriter(writer, customAreas); + } + + private static CustomAreas readCustomAreas( + Path path, + String customAreaStart, + String customAreaEnd + ) throws IOException { + try { + var contents = Files.readString(path); + return CustomAreas.read(contents, customAreaStart, customAreaEnd); + } catch (NoSuchFileException exception) { + return CustomAreas.empty(customAreaStart, customAreaEnd); + } } private final Writer writer; + private final CustomAreas customAreas; private int indent; private boolean pendingIndent; - public CodeWriter(Writer writer) { + public CodeWriter(Writer writer, CustomAreas customAreas) { this.writer = writer; + this.customAreas = customAreas; this.indent = 0; this.pendingIndent = false; } @@ -47,6 +118,21 @@ public class CodeWriter implements AutoCloseable { this.indent -= 1; } + public void writeCustomArea(String name) throws IOException { + this.write(this.customAreas.customAreaStart); + this.write(name); + + for (var line : this.customAreas.lines(name)) { + this.writer.write("\n"); + this.write(line); + } + + this.newLine(); + this.write(this.customAreas.customAreaEnd); + this.write(name); + this.newLine(); + } + @Override public void close() throws Exception { this.writer.close(); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java index 77c2ecd..9356519 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java @@ -4,7 +4,6 @@ import org.zwobble.hobgoblin.compiler.ast.DocComment; import org.zwobble.hobgoblin.compiler.ast.typed.*; import org.zwobble.hobgoblin.compiler.builtins.NativeTypes; import org.zwobble.hobgoblin.compiler.config.OutputConfig; -import org.zwobble.hobgoblin.compiler.output.CodeWriter; import org.zwobble.hobgoblin.compiler.output.generators.Generator; import org.zwobble.hobgoblin.compiler.output.lang.java.JavaWriter; import org.zwobble.hobgoblin.compiler.output.lang.java.ast.*; @@ -78,7 +77,7 @@ public class JavaTypesGenerator implements Generator { var javaCompilationUnitPath = this.sourceRootDirectory .resolve(String.join(File.separator, javaCompilationUnit.packageName())) .resolve(javaCompilationUnit.typeDeclaration().name() + ".java"); - try (var writer = new JavaWriter(CodeWriter.file(javaCompilationUnitPath))) { + try (var writer = JavaWriter.file(javaCompilationUnitPath)) { writer.writeCompilationUnit(javaCompilationUnit); } catch (Exception e) { // TODO: better handling @@ -115,7 +114,7 @@ public class JavaTypesGenerator implements Generator { sumDefinition.variants().stream() .map(variant -> generateTypeRef(variant.type(), context)) .toList(), - JavaCustomArea.EMPTY, + JavaCustomArea.type(generateTypeRef(sumDefinition.type(), context), "body"), sumDefinition.docComment() ) ); @@ -168,7 +167,7 @@ public class JavaTypesGenerator implements Generator { ), generateStructDefinitionBuilder(structDefinition, components, context) ), - JavaCustomArea.EMPTY, + JavaCustomArea.type(generateTypeRef(structDefinition.type(), context), "body"), structDefinition.docComment() ); } @@ -216,7 +215,7 @@ public class JavaTypesGenerator implements Generator { components, List.of(), body, - JavaCustomArea.EMPTY, + JavaCustomArea.type(builderJavaTypeRef, "body"), DocComment.EMPTY ); } 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 9f87e0f..82c2f9b 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 @@ -5,8 +5,18 @@ import org.zwobble.hobgoblin.compiler.output.CodeWriter; import org.zwobble.hobgoblin.compiler.output.lang.java.ast.*; import java.io.IOException; +import java.io.StringWriter; +import java.nio.file.Path; public class JavaWriter implements AutoCloseable { + public static JavaWriter file(Path path) throws IOException { + return new JavaWriter(CodeWriter.file( + path, + "// Custom area start: ", + "// Custom area end: " + )); + } + private final CodeWriter writer; public JavaWriter(CodeWriter writer) { @@ -84,7 +94,7 @@ public class JavaWriter implements AutoCloseable { } this.writer.newLine(); - this.writeCustomArea("body", classDeclaration.customArea()); + this.writeCustomArea(classDeclaration.customArea()); this.writer.dedent(); this.writer.write("}"); @@ -102,19 +112,12 @@ public class JavaWriter implements AutoCloseable { } } - private void writeCustomArea(String name, JavaCustomArea javaCustomArea) throws IOException { - this.writer.write("// Custom area start: "); - this.writer.write(name); - this.writer.newLine(); - - for (var line : javaCustomArea.lines()) { - this.writer.write(line); - this.writer.newLine(); - } - - this.writer.write("// Custom area end: "); - this.writer.write(name); - this.writer.newLine(); + private void writeCustomArea(JavaCustomArea customArea) throws IOException { + var customAreaName = new StringWriter(); + writeTypeRef(customArea.type(), customAreaName::write); + customAreaName.write(" "); + customAreaName.write(customArea.name()); + this.writer.writeCustomArea(customAreaName.toString()); } void writeExpression(JavaExpression expression) throws IOException { @@ -165,7 +168,7 @@ public class JavaWriter implements AutoCloseable { this.writer.write("{"); this.writer.indent(); this.writer.newLine(); - this.writeCustomArea("body", interfaceDeclaration.customArea()); + this.writeCustomArea(interfaceDeclaration.customArea()); this.writer.dedent(); this.writer.write("}"); } @@ -271,7 +274,7 @@ public class JavaWriter implements AutoCloseable { } this.writer.newLine(); - this.writeCustomArea("body", recordDeclaration.customArea()); + this.writeCustomArea(recordDeclaration.customArea()); this.writer.dedent(); this.writer.write("}"); @@ -301,6 +304,10 @@ public class JavaWriter implements AutoCloseable { } void writeTypeRef(JavaTypeRef type) throws IOException { + writeTypeRef(type, writer::write); + } + + private static void writeTypeRef(JavaTypeRef type, WriteString writer) throws IOException { for (var part : type.packageName()) { writer.write(part); writer.write("."); @@ -316,14 +323,14 @@ public class JavaWriter implements AutoCloseable { writer.write("<"); writeWithSeparator( type.args(), - this::writeTypeRef, + arg -> writeTypeRef(arg, writer), () -> writer.write(", ") ); writer.write(">"); } } - private <T> void writeWithSeparator( + private static <T> void writeWithSeparator( Iterable<T> iterable, WriteElement<T> writeElement, WriteSeparator writeSeparator @@ -349,4 +356,8 @@ public class JavaWriter implements AutoCloseable { interface WriteSeparator { void write() throws IOException; } + + interface WriteString { + void write(String string) throws IOException; + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaCustomArea.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaCustomArea.java index 42d38d1..51e3096 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaCustomArea.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/java/ast/JavaCustomArea.java @@ -1,7 +1,7 @@ package org.zwobble.hobgoblin.compiler.output.lang.java.ast; -import java.util.List; - -public record JavaCustomArea(List<String> lines) { - public static final JavaCustomArea EMPTY = new JavaCustomArea(List.of()); +public record JavaCustomArea(JavaTypeRef type, String name) { + public static JavaCustomArea type(JavaTypeRef type, String name) { + return new JavaCustomArea(type, name); + } } |
