diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-07-14 19:39:31 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-07-14 19:39:31 +0100 |
| commit | 6cb75452ad193e1e40a092478ab527513a7e2bda (patch) | |
| tree | 8ca3317162200d3bc6524a1f0f4c7b84e5064b04 | |
| parent | 514f2c0437a5ccbf44a12b894e6a42a6c780b49d (diff) | |
Add attributes to Rust structs
8 files changed, 146 insertions, 11 deletions
diff --git a/hobgoblin/src/output/lang/rust/ast.hob b/hobgoblin/src/output/lang/rust/ast.hob index 83b504c..c633b42 100644 --- a/hobgoblin/src/output/lang/rust/ast.hob +++ b/hobgoblin/src/output/lang/rust/ast.hob @@ -33,6 +33,7 @@ struct RustFunctionParam { // === Structs === struct RustStructStruct { + field attributes: List[RustOuterAttribute]; field name: RustIdentifier; field fields: List[RustStructField]; field docComment: DocComment; @@ -91,6 +92,12 @@ sum RustAssociatedItem { variant RustFunction; } +// == Attributes == + +struct RustOuterAttribute { + field path: RustTypePath; +} + // == Statements == sum RustStatement { 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 aab7284..28926a3 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 @@ -123,7 +123,7 @@ public class RustTypesGenerator implements Generator { )) .toList(); - var rustStruct = new RustStructStruct(rustStructName, rustFields, structDefinition.docComment()); + var rustStruct = new RustStructStruct(List.of(), rustStructName, rustFields, structDefinition.docComment()); return List.of(rustStruct); } 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 3d85056..581d08a 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 @@ -118,6 +118,7 @@ public class RustWriter implements AutoCloseable { private void writeStructStruct(RustStructStruct structStruct) throws IOException { this.writeDocComment(structStruct.docComment()); + this.writerOuterAttributes(structStruct.attributes()); this.writer.write("pub struct "); this.writeIdentifier(structStruct.name()); this.writer.write(" {"); @@ -248,6 +249,21 @@ public class RustWriter implements AutoCloseable { } } + // == Attributes == + + private void writerOuterAttributes(List<RustOuterAttribute> attributes) throws IOException { + for (var attribute : attributes) { + writeOuterAttribute(attribute); + } + } + + private void writeOuterAttribute(RustOuterAttribute attribute) throws IOException { + this.writer.write("#["); + this.writeTypePath(attribute.path()); + this.writer.write("]"); + this.writer.newLine(); + } + // == Statements == void writeStatement(RustStatement statement) throws IOException { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttribute.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttribute.java new file mode 100644 index 0000000..862685a --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttribute.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.RustOuterAttribute imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute imports + +public record RustOuterAttribute(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath path) { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder arbitrary() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.arbitrary().build()); + } + + public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath path) { + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute build() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute(path); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder withPath(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath path) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder(path); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder withPath(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath.Builder path) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder(path.build()); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder body + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute 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 index 4eba76a..0bb57b7 100644 --- 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 @@ -5,42 +5,58 @@ 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<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem { +public record RustStructStruct(java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute> attributes, org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment) 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(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment()); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(java.util.List.of(), org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier.arbitrary().build(), java.util.List.of(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment()); } - public record Builder(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment) implements org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustItem.Builder { + public record Builder(java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute> attributes, org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier name, java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment) 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, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct(attributes, name, fields, docComment); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withAttributes(java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute> attributes) { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder addAttribute(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute attribute) { + var attributes = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>(this.attributes); + attributes.add(attribute); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder addAttribute(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.Builder attribute) { + var attributes = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>(this.attributes); + attributes.add(attribute.build()); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } 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, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } 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, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name.build(), fields, docComment); } public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withFields(java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField> fields) { - return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder addField(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField field) { var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField>(this.fields); fields.add(field); - return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder addField(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField.Builder field) { var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructField>(this.fields); fields.add(field.build()); - return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder withDocComment(org.zwobble.hobgoblin.compiler.ast.DocComment docComment) { - return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(name, fields, docComment); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder(attributes, name, fields, docComment); } // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct.Builder body 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 33fa490..b591058 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 @@ -110,6 +110,25 @@ public class RustWriterTests { } @Test + public void structWithAttributes() throws IOException { + var rust = RustStructStruct.arbitrary() + .withName(new RustIdentifier("Rectangle")) + .withAttributes(List.of( + new RustOuterAttribute(RustTypePath.of("a", "b", "C")), + new RustOuterAttribute(RustTypePath.of("Debug")) + )) + .build(); + + var string = write(writer -> writer.writeItem(rust)); + + assertThat(string, equalTo(""" + #[a::b::C] + #[Debug] + pub struct Rectangle { + }""")); + } + + @Test public void structWithFields() throws IOException { var rust = RustStructStruct.arbitrary() .withName(new RustIdentifier("Rectangle")) diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttributeMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttributeMatcher.java new file mode 100644 index 0000000..6e1e930 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttributeMatcher.java @@ -0,0 +1,39 @@ +// Generated by hobgoblin. + +package org.zwobble.hobgoblin.compiler.output.lang.rust.ast; + +// Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher imports +// Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher imports + +public class RustOuterAttributeMatcher implements org.zwobble.precisely.Matcher<java.lang.Object> { + public static org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher isRustOuterAttribute() { + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher(java.util.List.of()); + } + + private final java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>> submatchers; + + private RustOuterAttributeMatcher(java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>> 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<java.lang.Object> toMatcher() { + return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute.class, this.submatchers); + } + + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher withPath(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePath> path) { + var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>>(this.submatchers); + submatchers.add(org.zwobble.precisely.Matchers.has("path", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute::path, path)); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher(submatchers); + } + + // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher body + // Custom area end: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttributeMatcher 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 index 0301dbb..4c4aa6a 100644 --- 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 @@ -28,6 +28,12 @@ public class RustStructStructMatcher implements org.zwobble.precisely.Matcher<ja 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 withAttributes(org.zwobble.precisely.Matcher<? super java.util.List<org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustOuterAttribute>> attributes) { + var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct>>(this.submatchers); + submatchers.add(org.zwobble.precisely.Matchers.has("attributes", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct::attributes, attributes)); + return new org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher(submatchers); + } + public org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStructMatcher withName(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustIdentifier> name) { var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct>>(this.submatchers); submatchers.add(org.zwobble.precisely.Matchers.has("name", org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustStructStruct::name, name)); |
