commit cb4be73acbbe785c1852e9dc340f04e3d862b4dc (tree)
parent b2b1d8f1882f23e79b131c5cfbc7b9e41f75534a
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Tue, 10 Feb 2026 13:03:58 +0000
parser: add enum, union, literal, struct doc comment tests
Port tests from upstream parser_test.zig:
- "empty enum decls" (with extern/packed modifiers)
- "empty union decls" (with extern/packed/enum modifiers)
- "enum literal"
- "character literal larger than u8"
- "infix operator and then multiline string literal" (2 tests)
- "correctly space struct fields with doc comments"
- "aligned struct field"
- "comment to disable/enable zig fmt first"
Implement in parser.c:
- extern/packed modifiers before struct/union/enum in
parsePrimaryTypeExpr
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | parser.c | | | 15 | ++++++++++++--- |
| M | parser_test.zig | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 120 insertions(+), 3 deletions(-)
diff --git a/parser.c b/parser.c
@@ -469,9 +469,18 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) {
exit(1);
case TOKEN_KEYWORD_EXTERN:
case TOKEN_KEYWORD_PACKED:
- fprintf(stderr, "parsePrimaryTypeExpr does not support %s\n",
- tokenizerGetTagString(tok));
- exit(1);
+ // extern/packed can precede struct/union/enum
+ switch (p->token_tags[p->tok_i + 1]) {
+ case TOKEN_KEYWORD_STRUCT:
+ case TOKEN_KEYWORD_UNION:
+ case TOKEN_KEYWORD_ENUM:
+ p->tok_i++; // consume extern/packed
+ return parseContainerDeclAuto(p);
+ default:
+ fprintf(stderr, "parsePrimaryTypeExpr does not support %s\n",
+ tokenizerGetTagString(tok));
+ exit(1);
+ }
case TOKEN_KEYWORD_STRUCT:
case TOKEN_KEYWORD_OPAQUE:
case TOKEN_KEYWORD_ENUM:
diff --git a/parser_test.zig b/parser_test.zig
@@ -1252,3 +1252,111 @@ test "zig fmt: tagged union enum tag last token" {
\\
);
}
+
+test "zig fmt: empty enum decls" {
+ try testCanonical(
+ \\const A = enum {};
+ \\const B = enum(u32) {};
+ \\const C = extern enum(c_int) {};
+ \\const D = packed enum(u8) {};
+ \\
+ );
+}
+
+test "zig fmt: empty union decls" {
+ try testCanonical(
+ \\const A = union {};
+ \\const B = union(enum) {};
+ \\const C = union(Foo) {};
+ \\const D = extern union {};
+ \\const E = packed union {};
+ \\
+ );
+}
+
+test "zig fmt: enum literal" {
+ try testCanonical(
+ \\const x = .hi;
+ \\
+ );
+}
+
+test "zig fmt: character literal larger than u8" {
+ try testCanonical(
+ \\const x = '\u{01f4a9}';
+ \\
+ );
+}
+
+test "zig fmt: infix operator and then multiline string literal" {
+ try testCanonical(
+ \\const x = "" ++
+ \\ \\ hi
+ \\;
+ \\
+ );
+}
+
+test "zig fmt: infix operator and then multiline string literal over multiple lines" {
+ try testCanonical(
+ \\const x = "" ++
+ \\ \\ hi0
+ \\ \\ hi1
+ \\ \\ hi2
+ \\;
+ \\
+ );
+}
+
+test "zig fmt: correctly space struct fields with doc comments" {
+ try testTransform(
+ \\pub const S = struct {
+ \\ /// A
+ \\ a: u8,
+ \\ /// B
+ \\ /// B (cont)
+ \\ b: u8,
+ \\
+ \\
+ \\ /// C
+ \\ c: u8,
+ \\};
+ \\
+ ,
+ \\pub const S = struct {
+ \\ /// A
+ \\ a: u8,
+ \\ /// B
+ \\ /// B (cont)
+ \\ b: u8,
+ \\
+ \\ /// C
+ \\ c: u8,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: aligned struct field" {
+ try testCanonical(
+ \\pub const S = struct {
+ \\ f: i32 align(32),
+ \\};
+ \\
+ );
+ try testCanonical(
+ \\pub const S = struct {
+ \\ f: i32 align(32) = 1,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: comment to disable/enable zig fmt first" {
+ try testCanonical(
+ \\// Test trailing comma syntax
+ \\// zig fmt: off
+ \\
+ \\const struct_trailing_comma = struct { x: i32, y: i32, };
+ );
+}