From 81168752fe9b588f7a8215f86a32f3154c3f593a Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 27 Jun 2026 22:28:48 +0100 Subject: Generate Rust types for structs --- examples/01-struct/hobgoblin.json5 | 4 + examples/01-struct/output/rust/src/point.rs | 9 ++ hobgoblin/src/output/lang/rust/ast.hob | 50 ++++++++ .../hobgoblin/compiler/output/CodeWriter.java | 28 +++++ .../generators/rust/RustGeneratorConfig.java | 23 ++++ .../generators/rust/RustNativeTypeConfig.java | 8 ++ .../generators/rusttypes/RustTypesGenerator.java | 117 ++++++++++++++++- .../compiler/output/lang/rust/RustWriter.java | 138 +++++++++++++++++++++ .../output/lang/rust/ast/RustIdentifier.java | 28 +++++ .../compiler/output/lang/rust/ast/RustItem.java | 18 +++ .../compiler/output/lang/rust/ast/RustModule.java | 32 +++++ .../output/lang/rust/ast/RustPathIdentSegment.java | 18 +++ .../rust/ast/RustPathIdentSegmentIdentifier.java | 32 +++++ .../output/lang/rust/ast/RustStructField.java | 40 ++++++ .../output/lang/rust/ast/RustStructStruct.java | 36 ++++++ .../compiler/output/lang/rust/ast/RustType.java | 18 +++ .../output/lang/rust/ast/RustTypePath.java | 49 ++++++++ .../output/lang/rust/ast/RustTypePathSegment.java | 32 +++++ .../compiler/output/lang/java/JavaWriterTests.java | 16 +-- .../compiler/output/lang/rust/RustWriterTests.java | 104 ++++++++++++++++ .../lang/rust/ast/RustIdentifierMatcher.java | 37 ++++++ .../output/lang/rust/ast/RustModuleMatcher.java | 41 ++++++ .../ast/RustPathIdentSegmentIdentifierMatcher.java | 37 ++++++ .../lang/rust/ast/RustStructFieldMatcher.java | 41 ++++++ .../lang/rust/ast/RustStructStructMatcher.java | 41 ++++++ .../output/lang/rust/ast/RustTypePathMatcher.java | 37 ++++++ .../lang/rust/ast/RustTypePathSegmentMatcher.java | 37 ++++++ 27 files changed, 1055 insertions(+), 16 deletions(-) create mode 100644 examples/01-struct/output/rust/src/point.rs create mode 100644 hobgoblin/src/output/lang/rust/ast.hob create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGeneratorConfig.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustNativeTypeConfig.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifier.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustItem.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModule.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegment.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifier.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructField.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStruct.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustType.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePath.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifierMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModuleMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifierMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructFieldMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStructMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathMatcher.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegmentMatcher.java diff --git a/examples/01-struct/hobgoblin.json5 b/examples/01-struct/hobgoblin.json5 index 472e586..b19ddfd 100644 --- a/examples/01-struct/hobgoblin.json5 +++ b/examples/01-struct/hobgoblin.json5 @@ -11,5 +11,9 @@ path: "output/java/src/gen/java", packageName: "org.zwobble.example.types", }, + { + generator: "rust-types", + path: "output/rust/src", + } ], } diff --git a/examples/01-struct/output/rust/src/point.rs b/examples/01-struct/output/rust/src/point.rs new file mode 100644 index 0000000..4a2b09c --- /dev/null +++ b/examples/01-struct/output/rust/src/point.rs @@ -0,0 +1,9 @@ +pub struct Line { + start: Point, + end: Point, +} + +pub struct Point { + x: i32, + y: i32, +} diff --git a/hobgoblin/src/output/lang/rust/ast.hob b/hobgoblin/src/output/lang/rust/ast.hob new file mode 100644 index 0000000..f3ff901 --- /dev/null +++ b/hobgoblin/src/output/lang/rust/ast.hob @@ -0,0 +1,50 @@ +// == Modules == + +struct RustModule { + field name: List[RustIdentifier]; + field items: List[RustItem]; +} + +// == Items == + +sum RustItem { + variant RustStructStruct; +} + +struct RustStructStruct { + field name: RustIdentifier; + field fields: List[RustStructField]; +} + +struct RustStructField { + field name: RustIdentifier; + field type: RustType; +} + +// == Types == + +sum RustType { + variant RustTypePath; +} + +struct RustTypePath { + field segments: List[RustTypePathSegment]; +} + +struct RustTypePathSegment { + field pathIdentSegment: RustPathIdentSegment; +} + +sum RustPathIdentSegment { + variant RustPathIdentSegmentIdentifier; +} + +struct RustPathIdentSegmentIdentifier { + field name: RustIdentifier; +} + +// == Identifiers == + +struct RustIdentifier { + field value: String; +} 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 dba5dbf..fe2c3b9 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/CodeWriter.java @@ -2,6 +2,7 @@ package org.zwobble.hobgoblin.compiler.output; import java.io.FileWriter; import java.io.IOException; +import java.io.StringWriter; import java.io.Writer; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -14,6 +15,33 @@ public class CodeWriter implements AutoCloseable { Writer openWriter() throws IOException; } + public static class InMemoryCodeWriterFile implements CodeWriterFile { + private final Optional originalContents; + private final StringWriter stringWriter; + + public InMemoryCodeWriterFile( + Optional originalContents, + StringWriter stringWriter + ) { + this.originalContents = originalContents; + this.stringWriter = stringWriter; + } + + @Override + public String readString() throws IOException { + if (originalContents.isPresent()) { + return originalContents.get(); + } else { + throw new NoSuchFileException(""); + } + } + + @Override + public Writer openWriter() throws IOException { + return stringWriter; + } + } + public record CustomAreas( Map> existing, String customAreaStart, diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGeneratorConfig.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGeneratorConfig.java new file mode 100644 index 0000000..db0b2fe --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustGeneratorConfig.java @@ -0,0 +1,23 @@ +package org.zwobble.hobgoblin.compiler.output.generators.rust; + +import org.zwobble.hobgoblin.compiler.builtins.NativeTypes; +import org.zwobble.hobgoblin.compiler.output.lang.java.ast.*; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath; +import org.zwobble.hobgoblin.compiler.types.SimpleNativeType; + +import java.util.Map; +import java.util.Optional; + +public class RustGeneratorConfig { + private static final Map DEFAULT_NATIVE_TYPE_CONFIGS = Map.ofEntries( + Map.entry(NativeTypes.INT_32, new RustNativeTypeConfig(RustTypePath.primitive("i32"))), + Map.entry(NativeTypes.INT_64, new RustNativeTypeConfig(RustTypePath.primitive("i64"))), + Map.entry(NativeTypes.STRING, new RustNativeTypeConfig(RustTypePath.of("std", "string", "String"))), + Map.entry(NativeTypes.LIST_INNER, new RustNativeTypeConfig(RustTypePath.of("std", "vec", "Vec"))), + Map.entry(NativeTypes.OPTION_INNER, new RustNativeTypeConfig(RustTypePath.of("std", "option", "Option"))) + ); + + public Optional nativeTypeConfig(SimpleNativeType type) { + return Optional.ofNullable(DEFAULT_NATIVE_TYPE_CONFIGS.get(type)); + } +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustNativeTypeConfig.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustNativeTypeConfig.java new file mode 100644 index 0000000..27a6dc8 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rust/RustNativeTypeConfig.java @@ -0,0 +1,8 @@ +package org.zwobble.hobgoblin.compiler.output.generators.rust; + +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType; + +public record RustNativeTypeConfig( + RustType type +) { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java index c93be76..b5cf01c 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java @@ -1,14 +1,22 @@ package org.zwobble.hobgoblin.compiler.output.generators.rusttypes; -import org.zwobble.hobgoblin.compiler.ast.typed.TypedNamespaceNode; +import org.zwobble.hobgoblin.compiler.ast.typed.*; import org.zwobble.hobgoblin.compiler.config.OutputConfig; import org.zwobble.hobgoblin.compiler.output.generators.Generator; +import org.zwobble.hobgoblin.compiler.output.generators.rust.RustGeneratorConfig; +import org.zwobble.hobgoblin.compiler.output.lang.java.JavaWriter; +import org.zwobble.hobgoblin.compiler.output.lang.rust.RustWriter; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*; import org.zwobble.hobgoblin.compiler.typechecker.TypesInfo; +import org.zwobble.hobgoblin.compiler.types.*; +import org.zwobble.hobgoblin.compiler.util.Casing; import org.zwobble.json5.reader.Json5ObjectReader; +import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.List; +import java.util.stream.Collectors; public class RustTypesGenerator implements Generator { public static final String NAME = "rust-types"; @@ -23,6 +31,7 @@ public class RustTypesGenerator implements Generator { } private final Path outputPath; + private final RustGeneratorConfig config = new RustGeneratorConfig(); private RustTypesGenerator(Path outputPath) { this.outputPath = outputPath; @@ -30,6 +39,112 @@ public class RustTypesGenerator implements Generator { @Override public void generate(List namespaces, TypesInfo typesInfo) throws IOException { + for (var namespace : namespaces) { + var rustModule = generateNamespace(namespace); + write(rustModule); + } + } + + private void write(RustModule rustModule) throws IOException { + var path = this.outputPath.resolve( + rustModule.name().stream() + .map(name -> name.value()) + .collect(Collectors.joining(File.separator)) + ".rs" + ); + try (var writer = RustWriter.file(path)) { + writer.writeModule(rustModule); + } + } + + private RustModule generateNamespace(TypedNamespaceNode namespace) { + var rustModuleName = generateNamespaceName(namespace.namespaceName()); + + var rustItems = namespace.body().stream() + .flatMap(statement -> generateNamespaceStatement(statement).stream()) + .toList(); + + return new RustModule(rustModuleName, rustItems); + } + + private List generateNamespaceName(NamespaceName namespaceName) { + return namespaceName.parts().stream() + .map(part -> generateModuleName(part)) + .toList(); + } + + private List generateNamespaceStatement(TypedNamespaceStatementNode statement) { + return switch (statement) { + case TypedEnumDefinitionNode enumDefinition -> { + yield List.of(); + } + + case TypedNativeTypeDefinitionNode nativeTypeDefinition -> { + yield List.of(); + } + + case TypedStructDefinitionNode structDefinition -> { + var rustStructName = generateTypeName(structDefinition.name()); + + var rustFields = structDefinition.fields().stream() + .map(field -> new RustStructField(generateFieldName(field.name()), generateRustTypeExpression(field.type()))) + .toList(); + + var rustStruct = new RustStructStruct(rustStructName, rustFields); + + yield List.of(rustStruct); + } + + case TypedSumDefinitionNode sumDefinition -> { + yield List.of(); + } + }; + } + + private RustType generateRustTypeExpression(TypedTypeLevelExpressionNode type) { + return switch (type.value()) { + case ConstructedNativeType constructedNativeType -> { + throw new UnsupportedOperationException("TODO"); + } + + case EnumType enumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case SimpleNativeType simpleNativeType -> { + yield this.config.nativeTypeConfig(simpleNativeType) + .orElseThrow(() -> new UnsupportedOperationException("TODO")) + .type(); + } + + case StructType structType -> { + // TODO: qualify name + yield RustTypePath.of(generateTypeName(structType.name())); + } + + case SumType sumType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeLevelValueType typeLevelValueType -> { + throw new UnsupportedOperationException("TODO"); + } + + case TypeParam typeParam -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + + private RustIdentifier generateFieldName(String fieldName) { + return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(fieldName)); + } + + private RustIdentifier generateTypeName(String typeName) { + return new RustIdentifier(typeName); + } + + private RustIdentifier generateModuleName(String part) { + return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(part)); } } 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 new file mode 100644 index 0000000..16384a4 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java @@ -0,0 +1,138 @@ +package org.zwobble.hobgoblin.compiler.output.lang.rust; + +import org.zwobble.hobgoblin.compiler.output.CodeWriter; +import org.zwobble.hobgoblin.compiler.output.lang.java.JavaWriter; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*; + +import java.io.IOException; +import java.nio.file.Path; + +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 static RustWriter file(Path path) throws IOException { + return new RustWriter(CodeWriter.file( + path, + LINE_COMMENT_START + )); + } + + private final CodeWriter writer; + + public RustWriter(CodeWriter writer) { + this.writer = writer; + } + + @Override + public void close() throws IOException { + this.writer.close(); + } + + public void writeModule(RustModule module) throws IOException { + writeWithSeparator( + module.items(), + this::writeItem, + () -> { + this.writer.newLine(); + this.writer.newLine(); + } + ); + + this.writer.newLine(); + } + + void writeIdentifier(RustIdentifier identifier) throws IOException { + // TODO: handle keywords + this.writer.write(identifier.value()); + } + + void writeItem(RustItem item) throws IOException { + switch (item) { + case RustStructStruct structStruct -> { + writeStructStruct(structStruct); + } + } + } + + private void writeStructStruct(RustStructStruct structStruct) throws IOException { + this.writer.write("pub struct "); + this.writeIdentifier(structStruct.name()); + this.writer.write(" {"); + + if (!structStruct.fields().isEmpty()) { + this.writer.indent(); + + for (var field : structStruct.fields()) { + this.writer.newLine(); + this.writeIdentifier(field.name()); + this.writer.write(": "); + this.writeType(field.type()); + this.writer.write(","); + } + + this.writer.dedent(); + } + + this.writer.newLine(); + this.writer.write("}"); + } + + void writeType(RustType type) throws IOException { + switch (type) { + case RustTypePath typePath -> { + this.writeWithSeparator( + typePath.segments(), + this::writeTypePathSegment, + () -> this.writer.write("::") + ); + } + } + } + + private void writeTypePathSegment(RustTypePathSegment segment) throws IOException { + writePathIdentSegment(segment.pathIdentSegment()); + } + + private void writePathIdentSegment(RustPathIdentSegment pathIdentSegment) throws IOException { + switch (pathIdentSegment) { + case RustPathIdentSegmentIdentifier pathIdentSegmentIdentifier -> { + this.writeIdentifier(pathIdentSegmentIdentifier.name()); + } + } + } + + // TODO: de-dupe with Java writer + private static void writeWithSeparator( + Iterable iterable, + WriteElement writeElement, + WriteSeparator writeSeparator + ) throws IOException { + var isFirst = true; + for (var element : iterable) { + if (!isFirst) { + writeSeparator.write(); + } + + writeElement.write(element); + + if (isFirst) { + isFirst = false; + } + } + } + + interface WriteElement { + void write(T element) throws IOException; + } + + interface WriteSeparator { + void write() throws IOException; + } +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifier.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifier.java new file mode 100644 index 0000000..34e0ff7 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifier.java @@ -0,0 +1,28 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier imports + +public record RustIdentifier(String value) { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder(""); + } + + public record Builder(String value) { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier(value); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder withValue(String value) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder(value); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustItem.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustItem.java new file mode 100644 index 0000000..d1fa342 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustItem.java @@ -0,0 +1,18 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem imports + +public sealed interface RustItem permits org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct { + public interface Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem build(); + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModule.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModule.java new file mode 100644 index 0000000..e40895e --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModule.java @@ -0,0 +1,32 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule imports + +public record RustModule(java.util.List name, java.util.List items) { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder(java.util.List.of(), java.util.List.of()); + } + + public record Builder(java.util.List name, java.util.List items) { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule(name, items); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder withName(java.util.List name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder(name, items); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder withItems(java.util.List items) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder(name, items); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegment.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegment.java new file mode 100644 index 0000000..325a4a4 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegment.java @@ -0,0 +1,18 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment imports + +public sealed interface RustPathIdentSegment permits org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier { + public interface Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment build(); + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifier.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifier.java new file mode 100644 index 0000000..72e6cb0 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifier.java @@ -0,0 +1,32 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier imports + +public record RustPathIdentSegmentIdentifier(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.arbitrary().build()); + } + + public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment.Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier(name); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder(name); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder(name.build()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructField.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructField.java new file mode 100644 index 0000000..dc1ddf0 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructField.java @@ -0,0 +1,40 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField imports + +public record RustStructField(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType type) { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.arbitrary().build(), org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.arbitrary().build()); + } + + public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType type) { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField(name, type); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder(name, type); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder(name.build(), type); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder withType(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType type) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder(name, type); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder withType(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType.Builder type) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder(name, type.build()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStruct.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStruct.java new file mode 100644 index 0000000..3e9c3ad --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStruct.java @@ -0,0 +1,36 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct imports + +public record RustStructStruct(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, java.util.List fields) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.arbitrary().build(), java.util.List.of()); + } + + public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, java.util.List fields) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem.Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct(name, fields); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withName(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.Builder name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name.build(), fields); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withFields(java.util.List fields) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustType.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustType.java new file mode 100644 index 0000000..e9d2283 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustType.java @@ -0,0 +1,18 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType imports + +public sealed interface RustType permits org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath { + public interface Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType build(); + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePath.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePath.java new file mode 100644 index 0000000..c55b53d --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePath.java @@ -0,0 +1,49 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath imports +import java.util.Arrays; +import java.util.List; +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath imports + +public record RustTypePath(java.util.List segments) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder(java.util.List.of()); + } + + public record Builder(java.util.List segments) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustType.Builder { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath(segments); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder withSegments(java.util.List segments) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder(segments); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath body + public static RustTypePath primitive(String name) { + return new RustTypePath(List.of( + new RustTypePathSegment(new RustPathIdentSegmentIdentifier(new RustIdentifier(name))) + )); + } + + public static RustType of(String... names) { + var segments = Arrays.stream(names) + .map(name -> new RustTypePathSegment(new RustPathIdentSegmentIdentifier(new RustIdentifier(name)))) + .toList(); + return new RustTypePath(segments); + } + + public static RustType of(RustIdentifier... names) { + var segments = Arrays.stream(names) + .map(name -> new RustTypePathSegment(new RustPathIdentSegmentIdentifier(name))) + .toList(); + return new RustTypePath(segments); + } + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath body +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java new file mode 100644 index 0000000..cbd1c69 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegment.java @@ -0,0 +1,32 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment imports + +public record RustTypePathSegment(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment pathIdentSegment) { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.arbitrary().build()); + } + + public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment pathIdentSegment) { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment(pathIdentSegment); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder withPathIdentSegment(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment pathIdentSegment) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder(pathIdentSegment); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder withPathIdentSegment(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegment.Builder pathIdentSegment) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder(pathIdentSegment.build()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment body +} 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 909300e..992d9bd 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 @@ -975,21 +975,7 @@ public class JavaWriterTests { private String write(Write write, Optional originalContents) throws IOException { var stringWriter = new StringWriter(); var javaWriter = JavaWriter.file( - new CodeWriter.CodeWriterFile() { - @Override - public String readString() throws IOException { - if (originalContents.isPresent()) { - return originalContents.get(); - } else { - throw new NoSuchFileException(""); - } - } - - @Override - public Writer openWriter() throws IOException { - return stringWriter; - } - } + new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter) ); write.write(javaWriter); return stringWriter.toString(); 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 new file mode 100644 index 0000000..bc6f55e --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java @@ -0,0 +1,104 @@ +package org.zwobble.hobgoblin.compiler.output.lang.rust; + +import org.junit.jupiter.api.Test; +import org.zwobble.hobgoblin.compiler.output.CodeWriter; +import org.zwobble.hobgoblin.compiler.output.lang.java.JavaWriter; +import org.zwobble.hobgoblin.compiler.output.lang.java.JavaWriterTests; +import org.zwobble.hobgoblin.compiler.output.lang.rust.ast.*; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.List; +import java.util.Optional; + +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.equalTo; + +public class RustWriterTests { + @Test + public void identifierNonKeywordIsWrittenVerbatim() throws IOException { + var rust = new RustIdentifier("rigs"); + + var string = write(writer -> writer.writeIdentifier(rust)); + + assertThat(string, equalTo("rigs")); + } + + @Test + public void module() throws IOException { + var rust = new RustModule(List.of(new RustIdentifier("shapes")), List.of( + new RustStructStruct(new RustIdentifier("Rectangle"), List.of()), + new RustStructStruct(new RustIdentifier("Square"), List.of()) + )); + + var string = write(writer -> writer.writeModule(rust)); + + assertThat(string, equalTo(""" + pub struct Rectangle { + } + + pub struct Square { + } + """)); + } + + @Test + public void emptyStruct() throws IOException { + var rust = new RustStructStruct(new RustIdentifier("Rectangle"), List.of()); + + var string = write(writer -> writer.writeItem(rust)); + + assertThat(string, equalTo(""" + pub struct Rectangle { + }""")); + } + + @Test + public void emptyStructWithFields() throws IOException { + var rust = new RustStructStruct( + new RustIdentifier("Rectangle"), + List.of( + new RustStructField(new RustIdentifier("width"), RustTypePath.primitive("i32")), + new RustStructField(new RustIdentifier("height"), RustTypePath.primitive("i32")) + ) + ); + + var string = write(writer -> writer.writeItem(rust)); + + assertThat(string, equalTo(""" + pub struct Rectangle { + width: i32, + height: i32, + }""")); + } + + @Test + public void typeSegmentsAreSeparatedByDoubleColons() throws IOException { + var rust = RustTypePath.of("std", "string", "String"); + + var string = write(writer -> writer.writeType(rust)); + + assertThat(string, equalTo("std::string::String")); + } + + private String write(Write write) throws IOException { + return write(write, Optional.empty()); + } + + private String write(Write write, String originalContents) throws IOException { + return write(write, Optional.of(originalContents)); + } + + private String write(Write write, Optional originalContents) throws IOException { + var stringWriter = new StringWriter(); + var rustWriter = RustWriter.file( + new CodeWriter.InMemoryCodeWriterFile(originalContents, stringWriter) + ); + write.write(rustWriter); + return stringWriter.toString(); + } + + private interface Write { + void write(RustWriter writer) throws IOException; + } +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifierMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifierMatcher.java new file mode 100644 index 0000000..3edd421 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustIdentifierMatcher.java @@ -0,0 +1,37 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher imports + +public class RustIdentifierMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher isRustIdentifier() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustIdentifierMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher withValue(org.zwobble.precisely.Matcher value) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("value", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier::value, value))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifierMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModuleMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModuleMatcher.java new file mode 100644 index 0000000..c6a1629 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustModuleMatcher.java @@ -0,0 +1,41 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher imports + +public class RustModuleMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher isRustModule() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustModuleMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher withName(org.zwobble.precisely.Matcher> name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule::name, name))).toList()); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher withItems(org.zwobble.precisely.Matcher> items) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("items", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModule::items, items))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustModuleMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifierMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifierMatcher.java new file mode 100644 index 0000000..5f79def --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustPathIdentSegmentIdentifierMatcher.java @@ -0,0 +1,37 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher imports + +public class RustPathIdentSegmentIdentifierMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher isRustPathIdentSegmentIdentifier() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustPathIdentSegmentIdentifierMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher withName(org.zwobble.precisely.Matcher name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifier::name, name))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustPathIdentSegmentIdentifierMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructFieldMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructFieldMatcher.java new file mode 100644 index 0000000..a9b0b40 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructFieldMatcher.java @@ -0,0 +1,41 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher imports + +public class RustStructFieldMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher isRustStructField() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustStructFieldMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher withName(org.zwobble.precisely.Matcher name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField::name, name))).toList()); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher withType(org.zwobble.precisely.Matcher type) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("type", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField::type, type))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructFieldMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStructMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStructMatcher.java new file mode 100644 index 0000000..e8c6c39 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStructMatcher.java @@ -0,0 +1,41 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher imports + +public class RustStructStructMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher isRustStructStruct() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustStructStructMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher withName(org.zwobble.precisely.Matcher name) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct::name, name))).toList()); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher withFields(org.zwobble.precisely.Matcher> fields) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("fields", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct::fields, fields))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathMatcher.java new file mode 100644 index 0000000..248141a --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathMatcher.java @@ -0,0 +1,37 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher imports + +public class RustTypePathMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher isRustTypePath() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustTypePathMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher withSegments(org.zwobble.precisely.Matcher> segments) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("segments", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath::segments, segments))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathMatcher body +} diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegmentMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegmentMatcher.java new file mode 100644 index 0000000..4a73997 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustTypePathSegmentMatcher.java @@ -0,0 +1,37 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher imports + +public class RustTypePathSegmentMatcher implements org.zwobble.precisely.Matcher { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher isRustTypePathSegment() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher(java.util.List.of()); + } + + private final java.util.List> submatchers; + + private RustTypePathSegmentMatcher(java.util.List> submatchers) { + this.submatchers = submatchers; + } + + public org.zwobble.precisely.MatchResult match(java.lang.Object actual) { + return this.toMatcher().match(actual); + } + + public org.zwobble.precisely.TextTree describe() { + return this.toMatcher().describe(); + } + + private org.zwobble.precisely.Matcher toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher withPathIdentSegment(org.zwobble.precisely.Matcher pathIdentSegment) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher(java.util.stream.Stream.concat(this.submatchers.stream(), java.util.stream.Stream.of(org.zwobble.precisely.Matchers.has("pathIdentSegment", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment::pathIdentSegment, pathIdentSegment))).toList()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegmentMatcher body +} -- cgit v1.2.3