From cb4be73acbbe785c1852e9dc340f04e3d862b4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Tue, 10 Feb 2026 13:03:58 +0000 Subject: [PATCH] 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) --- parser.c | 15 +++++-- parser_test.zig | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/parser.c b/parser.c index 926e50d5c2..c93e55cb77 100644 --- 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 index a9f24cc9e1..e69896e5db 100644 --- 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, }; + ); +}