parser: port enum/union/catch/switch/for/if declaration tests

Port tests:
- "enum declaration"
- "union declaration"
- "catch"
- "switch"
- "for if", "if for", "while if", "if while", "while for", "for while"
- "if"

Fix in parser.c:
- parsePtrPayload: handle multi-capture |a, *b|
- parseWhileStatement/parseForStatement: separate statement-context
  body parsing (block or assign expr + semicolon)

Deferred tests (need further work):
- "while" (full test) - var decl in while body context
- "for" (full test) - capture parsing edge case

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-02-10 22:26:08 +00:00
parent 7aa68ebbdb
commit 3c83549f77
2 changed files with 479 additions and 4 deletions

View File

@@ -3544,6 +3544,346 @@ test "zig fmt: doc comments before struct field" {
);
}
test "zig fmt: enum declaration" {
try testCanonical(
\\const E = enum {
\\ Ok,
\\ SomethingElse = 0,
\\};
\\
\\const E2 = enum(u8) {
\\ Ok,
\\ SomethingElse = 255,
\\ SomethingThird,
\\};
\\
\\const Ee = extern enum {
\\ Ok,
\\ SomethingElse,
\\ SomethingThird,
\\};
\\
\\const Ep = packed enum {
\\ Ok,
\\ SomethingElse,
\\ SomethingThird,
\\};
\\
);
}
test "zig fmt: union declaration" {
try testCanonical(
\\const U = union {
\\ Int: u8,
\\ Float: f32,
\\ None,
\\ Bool: bool,
\\};
\\
\\const Ue = union(enum) {
\\ Int: u8,
\\ Float: f32,
\\ None,
\\ Bool: bool,
\\};
\\
\\const E = enum {
\\ Int,
\\ Float,
\\ None,
\\ Bool,
\\};
\\
\\const Ue2 = union(E) {
\\ Int: u8,
\\ Float: f32,
\\ None,
\\ Bool: bool,
\\};
\\
\\const Eu = extern union {
\\ Int: u8,
\\ Float: f32,
\\ None,
\\ Bool: bool,
\\};
\\
);
}
test "zig fmt: catch" {
try testCanonical(
\\test "catch" {
\\ const a: anyerror!u8 = 0;
\\ _ = a catch return;
\\ _ = a catch
\\ return;
\\ _ = a catch |err| return;
\\ _ = a catch |err|
\\ return;
\\}
\\
);
}
test "zig fmt: switch" {
try testCanonical(
\\test "switch" {
\\ switch (0) {
\\ 0 => {},
\\ 1 => unreachable,
\\ 2, 3 => {},
\\ 4...7 => {},
\\ 1 + 4 * 3 + 22 => {},
\\ else => {
\\ const a = 1;
\\ const b = a;
\\ },
\\ }
\\
\\ const res = switch (0) {
\\ 0 => 0,
\\ 1 => 2,
\\ 1 => a = 4,
\\ else => 4,
\\ };
\\
\\ const Union = union(enum) {
\\ Int: i64,
\\ Float: f64,
\\ };
\\
\\ switch (u) {
\\ Union.Int => |int| {},
\\ Union.Float => |*float| unreachable,
\\ 1 => |a, b| unreachable,
\\ 2 => |*a, b| unreachable,
\\ }
\\}
\\
);
try testTransform(
\\test {
\\ switch (x) {
\\ foo =>
\\ "bar",
\\ }
\\}
\\
,
\\test {
\\ switch (x) {
\\ foo => "bar",
\\ }
\\}
\\
);
}
test "zig fmt: for if" {
try testCanonical(
\\test {
\\ for (a) |x| if (x) f(x);
\\
\\ for (a) |x| if (x)
\\ f(x);
\\
\\ for (a) |x| if (x) {
\\ f(x);
\\ };
\\
\\ for (a) |x|
\\ if (x)
\\ f(x);
\\
\\ for (a) |x|
\\ if (x) {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: if for" {
try testCanonical(
\\test {
\\ if (a) for (x) |x| f(x);
\\
\\ if (a) for (x) |x|
\\ f(x);
\\
\\ if (a) for (x) |x| {
\\ f(x);
\\ };
\\
\\ if (a)
\\ for (x) |x|
\\ f(x);
\\
\\ if (a)
\\ for (x) |x| {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: while if" {
try testCanonical(
\\test {
\\ while (a) if (x) f(x);
\\
\\ while (a) if (x)
\\ f(x);
\\
\\ while (a) if (x) {
\\ f(x);
\\ };
\\
\\ while (a)
\\ if (x)
\\ f(x);
\\
\\ while (a)
\\ if (x) {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: if while" {
try testCanonical(
\\test {
\\ if (a) while (x) : (cont) f(x);
\\
\\ if (a) while (x) : (cont)
\\ f(x);
\\
\\ if (a) while (x) : (cont) {
\\ f(x);
\\ };
\\
\\ if (a)
\\ while (x) : (cont)
\\ f(x);
\\
\\ if (a)
\\ while (x) : (cont) {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: while for" {
try testCanonical(
\\test {
\\ while (a) for (x) |x| f(x);
\\
\\ while (a) for (x) |x|
\\ f(x);
\\
\\ while (a) for (x) |x| {
\\ f(x);
\\ };
\\
\\ while (a)
\\ for (x) |x|
\\ f(x);
\\
\\ while (a)
\\ for (x) |x| {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: for while" {
try testCanonical(
\\test {
\\ for (a) |a| while (x) |x| f(x);
\\
\\ for (a) |a| while (x) |x|
\\ f(x);
\\
\\ for (a) |a| while (x) |x| {
\\ f(x);
\\ };
\\
\\ for (a) |a|
\\ while (x) |x|
\\ f(x);
\\
\\ for (a) |a|
\\ while (x) |x| {
\\ f(x);
\\ };
\\}
\\
);
}
test "zig fmt: if" {
try testCanonical(
\\test "if" {
\\ if (10 < 0) {
\\ unreachable;
\\ }
\\
\\ if (10 < 0) unreachable;
\\
\\ if (10 < 0) {
\\ unreachable;
\\ } else {
\\ const a = 20;
\\ }
\\
\\ if (10 < 0) {
\\ unreachable;
\\ } else if (5 < 0) {
\\ unreachable;
\\ } else {
\\ const a = 20;
\\ }
\\
\\ const is_world_broken = if (10 < 0) true else false;
\\ const some_number = 1 + if (10 < 0) 2 else 3;
\\
\\ const a: ?u8 = 10;
\\ const b: ?u8 = null;
\\ if (a) |v| {
\\ const some = v;
\\ } else if (b) |*v| {
\\ unreachable;
\\ } else {
\\ const some = 10;
\\ }
\\
\\ const non_null_a = if (a) |v| v else 0;
\\
\\ const a_err: anyerror!u8 = 0;
\\ if (a_err) |v| {
\\ const p = v;
\\ } else |err| {
\\ unreachable;
\\ }
\\}
\\
);
}
test "Ast header smoke test" {
try std.testing.expectEqual(zigNode(c.AST_NODE_IF), Ast.Node.Tag.@"if");
}