diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-06-30 21:23:51 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-06-30 21:23:51 +0100 |
| commit | d0c6cc5511f5b953ca1a4184e6c7b903e4bb7450 (patch) | |
| tree | 5ed9f5bc8227f42fe6076779135f85794132537b | |
| parent | e69e58c00f1f7e64dc0bcfb1694564c6f4e8486a (diff) | |
Fully qualify Rust type expressions
12 files changed, 102 insertions, 15 deletions
diff --git a/examples/01-struct/output/rust/src/point.rs b/examples/01-struct/output/rust/src/point.rs index 063c3f0..467b8a8 100644 --- a/examples/01-struct/output/rust/src/point.rs +++ b/examples/01-struct/output/rust/src/point.rs @@ -1,7 +1,7 @@ /// A straight line from one point to another. pub struct Line { - pub start: Point, - pub end: Point, + pub start: crate::point::Point, + pub end: crate::point::Point, } /// A 2D point. diff --git a/examples/03-list/output/rust/src/point.rs b/examples/03-list/output/rust/src/point.rs index 25effb2..837233a 100644 --- a/examples/03-list/output/rust/src/point.rs +++ b/examples/03-list/output/rust/src/point.rs @@ -1,5 +1,5 @@ pub struct Path { - pub points: std::vec::Vec<Point>, + pub points: std::vec::Vec<crate::point::Point>, } pub struct Point { diff --git a/examples/06-imports/hobgoblin.json5 b/examples/06-imports/hobgoblin.json5 index 1ec9568..2bf59c3 100644 --- a/examples/06-imports/hobgoblin.json5 +++ b/examples/06-imports/hobgoblin.json5 @@ -5,5 +5,9 @@ path: "output/java/src/gen/java", packageName: "org.zwobble.example.types" }, + { + generator: "rust-types", + path: "output/rust/src", + }, ], } diff --git a/examples/06-imports/output/rust/.gitignore b/examples/06-imports/output/rust/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/examples/06-imports/output/rust/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/06-imports/output/rust/Cargo.lock b/examples/06-imports/output/rust/Cargo.lock new file mode 100644 index 0000000..9dc6e3e --- /dev/null +++ b/examples/06-imports/output/rust/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "example" +version = "0.1.0" diff --git a/examples/06-imports/output/rust/Cargo.toml b/examples/06-imports/output/rust/Cargo.toml new file mode 100644 index 0000000..5d4c622 --- /dev/null +++ b/examples/06-imports/output/rust/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "example" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/examples/06-imports/output/rust/rust-toolchain.toml b/examples/06-imports/output/rust/rust-toolchain.toml new file mode 100644 index 0000000..4fedb95 --- /dev/null +++ b/examples/06-imports/output/rust/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.96" diff --git a/examples/06-imports/output/rust/src/line.rs b/examples/06-imports/output/rust/src/line.rs new file mode 100644 index 0000000..c2940f5 --- /dev/null +++ b/examples/06-imports/output/rust/src/line.rs @@ -0,0 +1,5 @@ +/// A straight line from one point to another. +pub struct Line { + pub start: crate::point::Point, + pub end: crate::point::Point, +} diff --git a/examples/06-imports/output/rust/src/main.rs b/examples/06-imports/output/rust/src/main.rs new file mode 100644 index 0000000..ee3d685 --- /dev/null +++ b/examples/06-imports/output/rust/src/main.rs @@ -0,0 +1,11 @@ +mod line; +mod point; + +use line::Line; +use point::Point; + +fn main() { + let start = Point { x: 10, y: 25 }; + let end = Point { x: 10, y: 25 }; + let line = Line { start, end }; +} diff --git a/examples/06-imports/output/rust/src/point.rs b/examples/06-imports/output/rust/src/point.rs new file mode 100644 index 0000000..5fb5592 --- /dev/null +++ b/examples/06-imports/output/rust/src/point.rs @@ -0,0 +1,5 @@ +/// A 2D point. +pub struct Point { + pub x: i32, + pub y: i32, +} 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 776e401..c4af4e7 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 @@ -14,6 +14,7 @@ import org.zwobble.json5.reader.Json5ObjectReader; import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -39,7 +40,8 @@ public class RustTypesGenerator implements Generator { @Override public void generate(List<TypedNamespaceNode> namespaces, TypesInfo typesInfo) throws IOException { for (var namespace : namespaces) { - var rustModule = generateNamespace(namespace); + var context = new Context(namespace.namespaceName()); + var rustModule = generateNamespace(namespace, context); write(rustModule); } @@ -56,11 +58,11 @@ public class RustTypesGenerator implements Generator { } } - private RustModule generateNamespace(TypedNamespaceNode namespace) { + private RustModule generateNamespace(TypedNamespaceNode namespace, Context context) { var rustModuleName = generateNamespaceName(namespace.namespaceName()); var rustItems = namespace.body().stream() - .flatMap(statement -> generateNamespaceStatement(statement).stream()) + .flatMap(statement -> generateNamespaceStatement(statement, context).stream()) .toList(); return new RustModule(rustModuleName, rustItems); @@ -72,7 +74,10 @@ public class RustTypesGenerator implements Generator { .toList(); } - private List<RustItem> generateNamespaceStatement(TypedNamespaceStatementNode statement) { + private List<RustItem> generateNamespaceStatement( + TypedNamespaceStatementNode statement, + Context context + ) { return switch (statement) { case TypedEnumDefinitionNode enumDefinition -> { yield List.of(); @@ -86,7 +91,10 @@ public class RustTypesGenerator implements Generator { var rustStructName = generateTypeName(structDefinition.name()); var rustFields = structDefinition.fields().stream() - .map(field -> new RustStructField(generateFieldName(field.name()), generateRustTypeExpression(field.type()))) + .map(field -> new RustStructField( + generateFieldName(field.name()), + generateRustTypeExpression(field.type(), context) + )) .toList(); var rustStruct = new RustStructStruct(rustStructName, rustFields, structDefinition.docComment()); @@ -100,17 +108,23 @@ public class RustTypesGenerator implements Generator { }; } - private RustType generateRustTypeExpression(TypedTypeLevelExpressionNode<Type> type) { - return generateRustTypeExpression(type.value()); + private RustType generateRustTypeExpression( + TypedTypeLevelExpressionNode<Type> type, + Context context + ) { + return generateRustTypeExpression(type.value(), context); } - private RustType generateRustTypeExpression(Type type) { + private RustType generateRustTypeExpression(Type type, Context context) { return switch (type) { case ConstructedNativeType constructedNativeType -> { // TODO: avoid cast - var rustType = (RustTypePath) generateRustTypeExpression(constructedNativeType.constructor().genericType()); + var rustType = (RustTypePath) generateRustTypeExpression( + constructedNativeType.constructor().genericType(), + context + ); var rustArgs = constructedNativeType.args().stream() - .map(arg -> generateRustTypeExpression(arg)) + .map(arg -> generateRustTypeExpression(arg, context)) .toList(); yield rustType.withArgs(rustArgs); } @@ -126,8 +140,11 @@ public class RustTypesGenerator implements Generator { } case StructType structType -> { - // TODO: qualify name - yield RustTypePath.of(generateTypeName(structType.name())); + yield generateTypePath( + structType.namespaceName(), + structType.name(), + context + ); } case SumType sumType -> { @@ -144,6 +161,23 @@ public class RustTypesGenerator implements Generator { }; } + private RustType generateTypePath(NamespaceName namespaceName, String typeName, Context context) { + var segments = new ArrayList<RustTypePathSegment>(); + // TODO: use crate as a keyword, not an identifier + segments.add(RustTypePathSegment.of(new RustIdentifier("crate"))); + for (var moduleName : this.namespaceNameToRustCrateModulePath(namespaceName)) { + segments.add(RustTypePathSegment.of(moduleName)); + } + segments.add(RustTypePathSegment.of(generateTypeName(typeName))); + return new RustTypePath(segments); + } + + private List<RustIdentifier> namespaceNameToRustCrateModulePath(NamespaceName namespaceName) { + return namespaceName.parts().stream() + .map(part -> generateModuleName(part)) + .toList(); + } + private RustIdentifier generateFieldName(String fieldName) { return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(fieldName)); } @@ -155,4 +189,12 @@ public class RustTypesGenerator implements Generator { private RustIdentifier generateModuleName(String part) { return new RustIdentifier(Casing.lowerCamelCaseToSnakeCase(part)); } + + private static class Context { + private final NamespaceName currentNamespaceName; + + private Context(NamespaceName currentNamespaceName) { + this.currentNamespaceName = currentNamespaceName; + } + } } 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 index 4473aa3..78348c5 100644 --- 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 @@ -35,6 +35,10 @@ public record RustTypePathSegment(org.zwobble.hobgoblin.compiler.output.lang.rus } // Custom area start: org.zwobble.hobgoblin.compiler.output.lang.rust.ast.RustTypePathSegment body + public static RustTypePathSegment of(RustIdentifier name) { + return new RustTypePathSegment(new RustPathIdentSegmentIdentifier(name), Optional.empty()); + } + public RustTypePathSegment withArgs(List<RustType> args) { if (this.args.isPresent()) { throw new IllegalArgumentException("Type path segment already has args"); |
