summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-07-14 19:39:31 +0100
committerMichael Williamson <mike@zwobble.org>2026-07-14 19:39:31 +0100
commit6cb75452ad193e1e40a092478ab527513a7e2bda (patch)
tree8ca3317162200d3bc6524a1f0f4c7b84e5064b04
parent514f2c0437a5ccbf44a12b894e6a42a6c780b49d (diff)
Add attributes to Rust structs
-rw-r--r--hobgoblin/src/output/lang/rust/ast.hob7
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriter.java16
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttribute.java32
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStruct.java36
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/RustWriterTests.java19
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustOuterAttributeMatcher.java39
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/output/lang/rust/ast/RustStructStructMatcher.java6
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));