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, }; + ); +}