zig0

my attempts at zig bootstrapping in C
Log | Files | Refs | README | LICENSE

parser_test.zig (175222B) - Raw


      1 const std = @import("std");
      2 const mem = std.mem;
      3 const print = std.debug.print;
      4 const io = std.io;
      5 const maxInt = std.math.maxInt;
      6 
      7 test "zig fmt: remove extra whitespace at start and end of file with comment between" {
      8     try testTransform(
      9         \\
     10         \\
     11         \\// hello
     12         \\
     13         \\
     14     ,
     15         \\// hello
     16         \\
     17     );
     18 }
     19 
     20 test "zig fmt: tuple struct" {
     21     try testCanonical(
     22         \\const T = struct {
     23         \\    /// doc comment on tuple field
     24         \\    comptime comptime u32,
     25         \\    /// another doc comment on tuple field
     26         \\    *u32 = 1,
     27         \\    // needs to be wrapped in parentheses to not be parsed as a function decl
     28         \\    (fn () void) align(1),
     29         \\};
     30         \\
     31     );
     32 }
     33 
     34 test "zig fmt: preserves clobbers in inline asm with stray comma" {
     35     try testTransform(
     36         \\fn foo() void {
     37         \\    asm volatile (""
     38         \\        : [_] "" (-> type),
     39         \\        :
     40         \\        : "clobber"
     41         \\    );
     42         \\    asm volatile (""
     43         \\        :
     44         \\        : [_] "" (type),
     45         \\        : "clobber"
     46         \\    );
     47         \\}
     48         \\
     49     ,
     50         \\fn foo() void {
     51         \\    asm volatile (""
     52         \\        : [_] "" (-> type),
     53         \\        :
     54         \\        : .{ .clobber = true }
     55         \\    );
     56         \\    asm volatile (""
     57         \\        :
     58         \\        : [_] "" (type),
     59         \\        : .{ .clobber = true }
     60         \\    );
     61         \\}
     62         \\
     63     );
     64 }
     65 
     66 test "zig fmt: remove trailing comma at the end of assembly clobber" {
     67     try testTransform(
     68         \\fn foo() void {
     69         \\    asm volatile (""
     70         \\        : [_] "" (-> type),
     71         \\        :
     72         \\        : "clobber1", "clobber2",
     73         \\    );
     74         \\}
     75         \\
     76     ,
     77         \\fn foo() void {
     78         \\    asm volatile (""
     79         \\        : [_] "" (-> type),
     80         \\        :
     81         \\        : .{ .clobber1 = true, .clobber2 = true }
     82         \\    );
     83         \\}
     84         \\
     85     );
     86 }
     87 
     88 test "zig fmt: respect line breaks in struct field value declaration" {
     89     try testCanonical(
     90         \\const Foo = struct {
     91         \\    bar: u32 =
     92         \\        42,
     93         \\    bar: u32 =
     94         \\        // a comment
     95         \\        42,
     96         \\    bar: u32 =
     97         \\        42,
     98         \\    // a comment
     99         \\    bar: []const u8 =
    100         \\        \\ foo
    101         \\        \\ bar
    102         \\        \\ baz
    103         \\    ,
    104         \\    bar: u32 =
    105         \\        blk: {
    106         \\            break :blk 42;
    107         \\        },
    108         \\};
    109         \\
    110     );
    111 }
    112 
    113 test "zig fmt: respect line breaks before functions" {
    114     try testCanonical(
    115         \\const std = @import("std");
    116         \\
    117         \\inline fn foo() void {}
    118         \\
    119         \\noinline fn foo() void {}
    120         \\
    121         \\export fn foo() void {}
    122         \\
    123         \\extern fn foo() void;
    124         \\
    125         \\extern "foo" fn foo() void;
    126         \\
    127     );
    128 }
    129 
    130 test "zig fmt: rewrite callconv(.@\"inline\") to the inline keyword" {
    131     try testTransform(
    132         \\fn foo() callconv(.@"inline") void {}
    133         \\const bar: @import("std").builtin.CallingConvention = .@"inline";
    134         \\fn foo() callconv(bar) void {}
    135         \\
    136     ,
    137         \\inline fn foo() void {}
    138         \\const bar: @import("std").builtin.CallingConvention = .@"inline";
    139         \\fn foo() callconv(bar) void {}
    140         \\
    141     );
    142 }
    143 
    144 test "zig fmt: simple top level comptime block" {
    145     try testCanonical(
    146         \\// line comment
    147         \\comptime {}
    148         \\
    149     );
    150 }
    151 
    152 test "zig fmt: two spaced line comments before decl" {
    153     try testCanonical(
    154         \\// line comment
    155         \\
    156         \\// another
    157         \\comptime {}
    158         \\
    159     );
    160 }
    161 
    162 test "zig fmt: respect line breaks after var declarations" {
    163     try testCanonical(
    164         \\const crc =
    165         \\    lookup_tables[0][p[7]] ^
    166         \\    lookup_tables[1][p[6]] ^
    167         \\    lookup_tables[2][p[5]] ^
    168         \\    lookup_tables[3][p[4]] ^
    169         \\    lookup_tables[4][@as(u8, self.crc >> 24)] ^
    170         \\    lookup_tables[5][@as(u8, self.crc >> 16)] ^
    171         \\    lookup_tables[6][@as(u8, self.crc >> 8)] ^
    172         \\    lookup_tables[7][@as(u8, self.crc >> 0)];
    173         \\
    174     );
    175 }
    176 
    177 test "zig fmt: multiline string mixed with comments" {
    178     try testCanonical(
    179         \\const s1 =
    180         \\    //\\one
    181         \\    \\two)
    182         \\    \\three
    183         \\;
    184         \\const s2 =
    185         \\    \\one
    186         \\    \\two)
    187         \\    //\\three
    188         \\;
    189         \\const s3 =
    190         \\    \\one
    191         \\    //\\two)
    192         \\    \\three
    193         \\;
    194         \\const s4 =
    195         \\    \\one
    196         \\    //\\two
    197         \\    \\three
    198         \\    //\\four
    199         \\    \\five
    200         \\;
    201         \\const a =
    202         \\    1;
    203         \\
    204     );
    205 }
    206 
    207 test "zig fmt: empty file" {
    208     try testCanonical(
    209         \\
    210     );
    211 }
    212 
    213 test "zig fmt: file ends in comment" {
    214     try testTransform(
    215         \\     //foobar
    216     ,
    217         \\//foobar
    218         \\
    219     );
    220 }
    221 
    222 test "zig fmt: file ends in multi line comment" {
    223     try testTransform(
    224         \\     \\foobar
    225     ,
    226         \\\\foobar
    227         \\
    228     );
    229 }
    230 
    231 test "zig fmt: file ends in comment after var decl" {
    232     try testTransform(
    233         \\const x = 42;
    234         \\     //foobar
    235     ,
    236         \\const x = 42;
    237         \\//foobar
    238         \\
    239     );
    240 }
    241 
    242 test "zig fmt: if statement" {
    243     try testCanonical(
    244         \\test "" {
    245         \\    if (optional()) |some|
    246         \\        bar = some.foo();
    247         \\}
    248         \\
    249     );
    250 }
    251 
    252 test "zig fmt: top-level fields" {
    253     try testCanonical(
    254         \\a: did_you_know,
    255         \\b: all_files_are,
    256         \\structs: ?x,
    257         \\
    258     );
    259 }
    260 
    261 test "zig fmt: top-level tuple function call type" {
    262     try testCanonical(
    263         \\foo()
    264         \\
    265     );
    266 }
    267 
    268 test "zig fmt: top-level enum missing 'const name ='" {
    269     try testError(
    270         \\enum(u32)
    271         \\
    272     , &[_]Error{.expected_token});
    273 }
    274 
    275 test "zig fmt: top-level for/while loop" {
    276     try testCanonical(
    277         \\for (foo) |_| foo
    278         \\
    279     );
    280     try testCanonical(
    281         \\while (foo) |_| foo
    282         \\
    283     );
    284 }
    285 
    286 test "zig fmt: top-level bare asterisk+identifier" {
    287     try testCanonical(
    288         \\*x
    289         \\
    290     );
    291 }
    292 
    293 test "zig fmt: top-level bare asterisk+asterisk+identifier" {
    294     try testCanonical(
    295         \\**x
    296         \\
    297     );
    298 }
    299 
    300 test "zig fmt: C style containers" {
    301     try testError(
    302         \\struct Foo {
    303         \\    a: u32,
    304         \\};
    305     , &[_]Error{
    306         .c_style_container,
    307         .zig_style_container,
    308     });
    309     try testError(
    310         \\test {
    311         \\    struct Foo {
    312         \\        a: u32,
    313         \\    };
    314         \\}
    315     , &[_]Error{
    316         .c_style_container,
    317         .zig_style_container,
    318     });
    319 }
    320 
    321 test "zig fmt: decl between fields" {
    322     try testError(
    323         \\const S = struct {
    324         \\    const foo = 2;
    325         \\    const bar = 2;
    326         \\    const baz = 2;
    327         \\    a: usize,
    328         \\    const foo1 = 2;
    329         \\    const bar1 = 2;
    330         \\    const baz1 = 2;
    331         \\    b: usize,
    332         \\};
    333     , &[_]Error{
    334         .decl_between_fields,
    335         .previous_field,
    336         .next_field,
    337     });
    338 }
    339 
    340 test "zig fmt: errdefer with payload" {
    341     try testCanonical(
    342         \\pub fn main() anyerror!void {
    343         \\    errdefer |a| x += 1;
    344         \\    errdefer |a| {}
    345         \\    errdefer |a| {
    346         \\        x += 1;
    347         \\    }
    348         \\}
    349         \\
    350     );
    351 }
    352 
    353 test "zig fmt: nosuspend block" {
    354     try testCanonical(
    355         \\pub fn main() anyerror!void {
    356         \\    nosuspend {
    357         \\        var foo: Foo = .{ .bar = 42 };
    358         \\    }
    359         \\}
    360         \\
    361     );
    362 }
    363 
    364 test "zig fmt: container declaration, single line" {
    365     try testCanonical(
    366         \\const X = struct { foo: i32 };
    367         \\const X = struct { foo: i32, bar: i32 };
    368         \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
    369         \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
    370         \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
    371         \\
    372     );
    373 }
    374 
    375 test "zig fmt: container declaration, one item, multi line trailing comma" {
    376     try testCanonical(
    377         \\test "" {
    378         \\    comptime {
    379         \\        const X = struct {
    380         \\            x: i32,
    381         \\        };
    382         \\    }
    383         \\}
    384         \\
    385     );
    386 }
    387 
    388 test "zig fmt: container declaration, no trailing comma on separate line" {
    389     try testTransform(
    390         \\test "" {
    391         \\    comptime {
    392         \\        const X = struct {
    393         \\            x: i32
    394         \\        };
    395         \\    }
    396         \\}
    397         \\
    398     ,
    399         \\test "" {
    400         \\    comptime {
    401         \\        const X = struct { x: i32 };
    402         \\    }
    403         \\}
    404         \\
    405     );
    406 }
    407 
    408 test "zig fmt: container declaration, line break, no trailing comma" {
    409     try testTransform(
    410         \\const X = struct {
    411         \\    foo: i32, bar: i8 };
    412     ,
    413         \\const X = struct { foo: i32, bar: i8 };
    414         \\
    415     );
    416 }
    417 
    418 test "zig fmt: container declaration, transform trailing comma" {
    419     try testTransform(
    420         \\const X = struct {
    421         \\    foo: i32, bar: i8, };
    422     ,
    423         \\const X = struct {
    424         \\    foo: i32,
    425         \\    bar: i8,
    426         \\};
    427         \\
    428     );
    429 }
    430 
    431 test "zig fmt: container declaration, comment, add trailing comma" {
    432     try testTransform(
    433         \\const X = struct {
    434         \\    foo: i32, // foo
    435         \\    bar: i8
    436         \\};
    437     ,
    438         \\const X = struct {
    439         \\    foo: i32, // foo
    440         \\    bar: i8,
    441         \\};
    442         \\
    443     );
    444     try testTransform(
    445         \\const X = struct {
    446         \\    foo: i32 // foo
    447         \\};
    448     ,
    449         \\const X = struct {
    450         \\    foo: i32, // foo
    451         \\};
    452         \\
    453     );
    454 }
    455 
    456 test "zig fmt: container declaration, multiline string, add trailing comma" {
    457     try testTransform(
    458         \\const X = struct {
    459         \\    foo: []const u8 =
    460         \\        \\ foo
    461         \\    ,
    462         \\    bar: i8
    463         \\};
    464     ,
    465         \\const X = struct {
    466         \\    foo: []const u8 =
    467         \\        \\ foo
    468         \\    ,
    469         \\    bar: i8,
    470         \\};
    471         \\
    472     );
    473 }
    474 
    475 test "zig fmt: container declaration, doc comment on member, add trailing comma" {
    476     try testTransform(
    477         \\pub const Pos = struct {
    478         \\    /// X-axis.
    479         \\    x: u32,
    480         \\    /// Y-axis.
    481         \\    y: u32
    482         \\};
    483     ,
    484         \\pub const Pos = struct {
    485         \\    /// X-axis.
    486         \\    x: u32,
    487         \\    /// Y-axis.
    488         \\    y: u32,
    489         \\};
    490         \\
    491     );
    492 }
    493 
    494 test "zig fmt: remove empty lines at start/end of container decl" {
    495     try testTransform(
    496         \\const X = struct {
    497         \\
    498         \\    foo: i32,
    499         \\
    500         \\    bar: i8,
    501         \\
    502         \\};
    503         \\
    504     ,
    505         \\const X = struct {
    506         \\    foo: i32,
    507         \\
    508         \\    bar: i8,
    509         \\};
    510         \\
    511     );
    512 }
    513 
    514 test "zig fmt: remove empty lines at start/end of block" {
    515     try testTransform(
    516         \\test {
    517         \\
    518         \\    if (foo) {
    519         \\        foo();
    520         \\    }
    521         \\
    522         \\}
    523         \\
    524     ,
    525         \\test {
    526         \\    if (foo) {
    527         \\        foo();
    528         \\    }
    529         \\}
    530         \\
    531     );
    532 }
    533 
    534 test "zig fmt: allow empty line before comment at start of block" {
    535     try testCanonical(
    536         \\test {
    537         \\
    538         \\    // foo
    539         \\    const x = 42;
    540         \\}
    541         \\
    542     );
    543 }
    544 
    545 test "zig fmt: trailing comma in fn parameter list" {
    546     try testCanonical(
    547         \\pub fn f(
    548         \\    a: i32,
    549         \\    b: i32,
    550         \\) i32 {}
    551         \\pub fn f(
    552         \\    a: i32,
    553         \\    b: i32,
    554         \\) align(8) i32 {}
    555         \\pub fn f(
    556         \\    a: i32,
    557         \\    b: i32,
    558         \\) addrspace(.generic) i32 {}
    559         \\pub fn f(
    560         \\    a: i32,
    561         \\    b: i32,
    562         \\) linksection(".text") i32 {}
    563         \\pub fn f(
    564         \\    a: i32,
    565         \\    b: i32,
    566         \\) callconv(.c) i32 {}
    567         \\pub fn f(
    568         \\    a: i32,
    569         \\    b: i32,
    570         \\) align(8) linksection(".text") i32 {}
    571         \\pub fn f(
    572         \\    a: i32,
    573         \\    b: i32,
    574         \\) align(8) callconv(.c) i32 {}
    575         \\pub fn f(
    576         \\    a: i32,
    577         \\    b: i32,
    578         \\) align(8) linksection(".text") callconv(.c) i32 {}
    579         \\pub fn f(
    580         \\    a: i32,
    581         \\    b: i32,
    582         \\) linksection(".text") callconv(.c) i32 {}
    583         \\
    584     );
    585 }
    586 
    587 test "zig fmt: comptime struct field" {
    588     try testCanonical(
    589         \\const Foo = struct {
    590         \\    a: i32,
    591         \\    comptime b: i32 = 1234,
    592         \\};
    593         \\
    594     );
    595 }
    596 
    597 test "zig fmt: break from block" {
    598     try testCanonical(
    599         \\const a = blk: {
    600         \\    break :blk 42;
    601         \\};
    602         \\const b = blk: {
    603         \\    break :blk;
    604         \\};
    605         \\const c = {
    606         \\    break 42;
    607         \\};
    608         \\const d = {
    609         \\    break;
    610         \\};
    611         \\
    612     );
    613 }
    614 
    615 test "zig fmt: grouped expressions (parentheses)" {
    616     try testCanonical(
    617         \\const r = (x + y) * (a + b);
    618         \\
    619     );
    620 }
    621 
    622 test "zig fmt: c pointer type" {
    623     try testCanonical(
    624         \\pub extern fn repro() [*c]const u8;
    625         \\
    626     );
    627 }
    628 
    629 test "zig fmt: builtin call with trailing comma" {
    630     try testCanonical(
    631         \\pub fn main() void {
    632         \\    @breakpoint();
    633         \\    _ = @intFromBool(a);
    634         \\    _ = @call(
    635         \\        a,
    636         \\        b,
    637         \\        c,
    638         \\    );
    639         \\}
    640         \\
    641     );
    642 }
    643 
    644 test "zig fmt: asm expression with comptime content" {
    645     try testTransform(
    646         \\comptime {
    647         \\    asm ("foo" ++ "bar");
    648         \\}
    649         \\pub fn main() void {
    650         \\    asm volatile ("foo" ++ "bar");
    651         \\    asm volatile ("foo" ++ "bar"
    652         \\        : [_] "" (x),
    653         \\    );
    654         \\    asm volatile ("foo" ++ "bar"
    655         \\        : [_] "" (x),
    656         \\        : [_] "" (y),
    657         \\    );
    658         \\    asm volatile ("foo" ++ "bar"
    659         \\        : [_] "" (x),
    660         \\        : [_] "" (y),
    661         \\        : "h", "e", "l", "l", "o"
    662         \\    );
    663         \\}
    664         \\
    665     ,
    666         \\comptime {
    667         \\    asm ("foo" ++ "bar");
    668         \\}
    669         \\pub fn main() void {
    670         \\    asm volatile ("foo" ++ "bar");
    671         \\    asm volatile ("foo" ++ "bar"
    672         \\        : [_] "" (x),
    673         \\    );
    674         \\    asm volatile ("foo" ++ "bar"
    675         \\        : [_] "" (x),
    676         \\        : [_] "" (y),
    677         \\    );
    678         \\    asm volatile ("foo" ++ "bar"
    679         \\        : [_] "" (x),
    680         \\        : [_] "" (y),
    681         \\        : .{ .h = true, .e = true, .l = true, .l = true, .o = true }
    682         \\    );
    683         \\}
    684         \\
    685     );
    686 }
    687 
    688 test "zig fmt: array types last token" {
    689     try testCanonical(
    690         \\test {
    691         \\    const x = [40]u32;
    692         \\}
    693         \\
    694         \\test {
    695         \\    const x = [40:0]u32;
    696         \\}
    697         \\
    698     );
    699 }
    700 
    701 test "zig fmt: sentinel-terminated array type" {
    702     try testCanonical(
    703         \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
    704         \\    return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
    705         \\}
    706         \\
    707     );
    708 }
    709 
    710 test "zig fmt: sentinel-terminated slice type" {
    711     try testCanonical(
    712         \\pub fn toSlice(self: Buffer) [:0]u8 {
    713         \\    return self.list.toSlice()[0..self.len()];
    714         \\}
    715         \\
    716     );
    717 }
    718 
    719 test "zig fmt: pointer-to-one with modifiers" {
    720     try testCanonical(
    721         \\const x: *u32 = undefined;
    722         \\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    723         \\const z: *allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    724         \\
    725     );
    726 }
    727 
    728 test "zig fmt: pointer-to-many with modifiers" {
    729     try testCanonical(
    730         \\const x: [*]u32 = undefined;
    731         \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    732         \\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    733         \\
    734     );
    735 }
    736 
    737 test "zig fmt: sentinel pointer with modifiers" {
    738     try testCanonical(
    739         \\const x: [*:42]u32 = undefined;
    740         \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    741         \\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    742         \\
    743     );
    744 }
    745 
    746 test "zig fmt: c pointer with modifiers" {
    747     try testCanonical(
    748         \\const x: [*c]u32 = undefined;
    749         \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    750         \\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    751         \\
    752     );
    753 }
    754 
    755 test "zig fmt: slice with modifiers" {
    756     try testCanonical(
    757         \\const x: []u32 = undefined;
    758         \\const y: []allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    759         \\
    760     );
    761 }
    762 
    763 test "zig fmt: sentinel slice with modifiers" {
    764     try testCanonical(
    765         \\const x: [:42]u32 = undefined;
    766         \\const y: [:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    767         \\
    768     );
    769 }
    770 
    771 test "zig fmt: anon literal in array" {
    772     try testCanonical(
    773         \\var arr: [2]Foo = .{
    774         \\    .{ .a = 2 },
    775         \\    .{ .b = 3 },
    776         \\};
    777         \\
    778     );
    779 }
    780 
    781 test "zig fmt: alignment in anonymous literal" {
    782     try testTransform(
    783         \\const a = .{
    784         \\    "U",     "L",     "F",
    785         \\    "U'",
    786         \\    "L'",
    787         \\    "F'",
    788         \\};
    789         \\
    790     ,
    791         \\const a = .{
    792         \\    "U",  "L",  "F",
    793         \\    "U'", "L'", "F'",
    794         \\};
    795         \\
    796     );
    797 }
    798 
    799 test "zig fmt: anon struct literal 0 element" {
    800     try testCanonical(
    801         \\test {
    802         \\    const x = .{};
    803         \\}
    804         \\
    805     );
    806 }
    807 
    808 test "zig fmt: anon struct literal 1 element" {
    809     try testCanonical(
    810         \\test {
    811         \\    const x = .{ .a = b };
    812         \\}
    813         \\
    814     );
    815 }
    816 
    817 test "zig fmt: anon struct literal 1 element comma" {
    818     try testCanonical(
    819         \\test {
    820         \\    const x = .{
    821         \\        .a = b,
    822         \\    };
    823         \\}
    824         \\
    825     );
    826 }
    827 
    828 test "zig fmt: anon struct literal 2 element" {
    829     try testCanonical(
    830         \\test {
    831         \\    const x = .{ .a = b, .c = d };
    832         \\}
    833         \\
    834     );
    835 }
    836 
    837 test "zig fmt: anon struct literal 2 element comma" {
    838     try testCanonical(
    839         \\test {
    840         \\    const x = .{
    841         \\        .a = b,
    842         \\        .c = d,
    843         \\    };
    844         \\}
    845         \\
    846     );
    847 }
    848 
    849 test "zig fmt: anon struct literal 3 element" {
    850     try testCanonical(
    851         \\test {
    852         \\    const x = .{ .a = b, .c = d, .e = f };
    853         \\}
    854         \\
    855     );
    856 }
    857 
    858 test "zig fmt: anon struct literal 3 element comma" {
    859     try testCanonical(
    860         \\test {
    861         \\    const x = .{
    862         \\        .a = b,
    863         \\        .c = d,
    864         \\        .e = f,
    865         \\    };
    866         \\}
    867         \\
    868     );
    869 }
    870 
    871 test "zig fmt: struct literal 0 element" {
    872     try testCanonical(
    873         \\test {
    874         \\    const x = X{};
    875         \\}
    876         \\
    877     );
    878 }
    879 
    880 test "zig fmt: struct literal 1 element" {
    881     try testCanonical(
    882         \\test {
    883         \\    const x = X{ .a = b };
    884         \\}
    885         \\
    886     );
    887 }
    888 
    889 test "zig fmt: Unicode code point literal larger than u8" {
    890     try testCanonical(
    891         \\test {
    892         \\    const x = X{
    893         \\        .a = b,
    894         \\    };
    895         \\}
    896         \\
    897     );
    898 }
    899 
    900 test "zig fmt: struct literal 2 element" {
    901     try testCanonical(
    902         \\test {
    903         \\    const x = X{ .a = b, .c = d };
    904         \\}
    905         \\
    906     );
    907 }
    908 
    909 test "zig fmt: struct literal 2 element comma" {
    910     try testCanonical(
    911         \\test {
    912         \\    const x = X{
    913         \\        .a = b,
    914         \\        .c = d,
    915         \\    };
    916         \\}
    917         \\
    918     );
    919 }
    920 
    921 test "zig fmt: struct literal 3 element" {
    922     try testCanonical(
    923         \\test {
    924         \\    const x = X{ .a = b, .c = d, .e = f };
    925         \\}
    926         \\
    927     );
    928 }
    929 
    930 test "zig fmt: struct literal 3 element comma" {
    931     try testCanonical(
    932         \\test {
    933         \\    const x = X{
    934         \\        .a = b,
    935         \\        .c = d,
    936         \\        .e = f,
    937         \\    };
    938         \\}
    939         \\
    940     );
    941 }
    942 
    943 test "zig fmt: anon list literal 1 element" {
    944     try testCanonical(
    945         \\test {
    946         \\    const x = .{a};
    947         \\}
    948         \\
    949     );
    950 }
    951 
    952 test "zig fmt: anon list literal 1 element comma" {
    953     try testCanonical(
    954         \\test {
    955         \\    const x = .{
    956         \\        a,
    957         \\    };
    958         \\}
    959         \\
    960     );
    961 }
    962 
    963 test "zig fmt: anon list literal 2 element" {
    964     try testCanonical(
    965         \\test {
    966         \\    const x = .{ a, b };
    967         \\}
    968         \\
    969     );
    970 }
    971 
    972 test "zig fmt: anon list literal 2 element comma" {
    973     try testCanonical(
    974         \\test {
    975         \\    const x = .{
    976         \\        a,
    977         \\        b,
    978         \\    };
    979         \\}
    980         \\
    981     );
    982 }
    983 
    984 test "zig fmt: anon list literal 3 element" {
    985     try testCanonical(
    986         \\test {
    987         \\    const x = .{ a, b, c };
    988         \\}
    989         \\
    990     );
    991 }
    992 
    993 test "zig fmt: anon list literal 3 element comma" {
    994     try testCanonical(
    995         \\test {
    996         \\    const x = .{
    997         \\        a,
    998         \\        // foo
    999         \\        b,
   1000         \\
   1001         \\        c,
   1002         \\    };
   1003         \\}
   1004         \\
   1005     );
   1006 }
   1007 
   1008 test "zig fmt: array literal 0 element" {
   1009     try testCanonical(
   1010         \\test {
   1011         \\    const x = [_]u32{};
   1012         \\}
   1013         \\
   1014     );
   1015 }
   1016 
   1017 test "zig fmt: array literal 1 element" {
   1018     try testCanonical(
   1019         \\test {
   1020         \\    const x = [_]u32{a};
   1021         \\}
   1022         \\
   1023     );
   1024 }
   1025 
   1026 test "zig fmt: array literal 1 element comma" {
   1027     try testCanonical(
   1028         \\test {
   1029         \\    const x = [1]u32{
   1030         \\        a,
   1031         \\    };
   1032         \\}
   1033         \\
   1034     );
   1035 }
   1036 
   1037 test "zig fmt: array literal 2 element" {
   1038     try testCanonical(
   1039         \\test {
   1040         \\    const x = [_]u32{ a, b };
   1041         \\}
   1042         \\
   1043     );
   1044 }
   1045 
   1046 test "zig fmt: array literal 2 element comma" {
   1047     try testCanonical(
   1048         \\test {
   1049         \\    const x = [2]u32{
   1050         \\        a,
   1051         \\        b,
   1052         \\    };
   1053         \\}
   1054         \\
   1055     );
   1056 }
   1057 
   1058 test "zig fmt: array literal 3 element" {
   1059     try testCanonical(
   1060         \\test {
   1061         \\    const x = [_]u32{ a, b, c };
   1062         \\}
   1063         \\
   1064     );
   1065 }
   1066 
   1067 test "zig fmt: array literal 3 element comma" {
   1068     try testCanonical(
   1069         \\test {
   1070         \\    const x = [3]u32{
   1071         \\        a,
   1072         \\        b,
   1073         \\        c,
   1074         \\    };
   1075         \\}
   1076         \\
   1077     );
   1078 }
   1079 
   1080 test "zig fmt: sentinel array literal 1 element" {
   1081     try testCanonical(
   1082         \\test {
   1083         \\    const x = [_:9000]u32{a};
   1084         \\}
   1085         \\
   1086     );
   1087 }
   1088 
   1089 test "zig fmt: slices" {
   1090     try testCanonical(
   1091         \\const a = b[0..];
   1092         \\const c = d[0..1];
   1093         \\const d = f[0.. :0];
   1094         \\const e = f[0..1 :0];
   1095         \\
   1096     );
   1097 }
   1098 
   1099 test "zig fmt: slices with spaces in bounds" {
   1100     try testCanonical(
   1101         \\const a = b[0 + 0 ..];
   1102         \\const c = d[0 + 0 .. 1];
   1103         \\const c = d[0 + 0 .. :0];
   1104         \\const e = f[0 .. 1 + 1 :0];
   1105         \\
   1106     );
   1107 }
   1108 
   1109 test "zig fmt: block in slice expression" {
   1110     try testCanonical(
   1111         \\const a = b[{
   1112         \\    _ = x;
   1113         \\}..];
   1114         \\const c = d[0..{
   1115         \\    _ = x;
   1116         \\    _ = y;
   1117         \\}];
   1118         \\const e = f[0..1 :{
   1119         \\    _ = x;
   1120         \\    _ = y;
   1121         \\    _ = z;
   1122         \\}];
   1123         \\
   1124     );
   1125 }
   1126 
   1127 test "zig fmt: whitespace fixes" {
   1128     try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a  = b;}\r\n",
   1129         \\test "" {
   1130         \\    const hi = x;
   1131         \\}
   1132         \\// zig fmt: off
   1133         \\test ""{
   1134         \\    const a  = b;}
   1135         \\
   1136     );
   1137 }
   1138 
   1139 test "zig fmt: while else err prong with no block" {
   1140     try testCanonical(
   1141         \\test "" {
   1142         \\    const result = while (returnError()) |value| {
   1143         \\        break value;
   1144         \\    } else |err| @as(i32, 2);
   1145         \\    try expect(result == 2);
   1146         \\}
   1147         \\
   1148     );
   1149 }
   1150 
   1151 test "zig fmt: tagged union with enum values" {
   1152     try testCanonical(
   1153         \\const MultipleChoice2 = union(enum(u32)) {
   1154         \\    Unspecified1: i32,
   1155         \\    A: f32 = 20,
   1156         \\    Unspecified2: void,
   1157         \\    B: bool = 40,
   1158         \\    Unspecified3: i32,
   1159         \\    C: i8 = 60,
   1160         \\    Unspecified4: void,
   1161         \\    D: void = 1000,
   1162         \\    Unspecified5: i32,
   1163         \\};
   1164         \\
   1165     );
   1166 }
   1167 
   1168 test "zig fmt: tagged union enum tag last token" {
   1169     try testCanonical(
   1170         \\test {
   1171         \\    const U = union(enum(u32)) {};
   1172         \\}
   1173         \\
   1174         \\test {
   1175         \\    const U = union(enum(u32)) { foo };
   1176         \\}
   1177         \\
   1178         \\test {
   1179         \\    const U = union(enum(u32)) {
   1180         \\        foo,
   1181         \\    };
   1182         \\}
   1183         \\
   1184     );
   1185 }
   1186 
   1187 test "zig fmt: allowzero pointer" {
   1188     try testCanonical(
   1189         \\const T = [*]allowzero const u8;
   1190         \\
   1191     );
   1192 }
   1193 
   1194 test "zig fmt: empty enum decls" {
   1195     try testCanonical(
   1196         \\const A = enum {};
   1197         \\const B = enum(u32) {};
   1198         \\const C = extern enum(c_int) {};
   1199         \\const D = packed enum(u8) {};
   1200         \\
   1201     );
   1202 }
   1203 
   1204 test "zig fmt: empty union decls" {
   1205     try testCanonical(
   1206         \\const A = union {};
   1207         \\const B = union(enum) {};
   1208         \\const C = union(Foo) {};
   1209         \\const D = extern union {};
   1210         \\const E = packed union {};
   1211         \\
   1212     );
   1213 }
   1214 
   1215 test "zig fmt: enum literal" {
   1216     try testCanonical(
   1217         \\const x = .hi;
   1218         \\
   1219     );
   1220 }
   1221 
   1222 test "zig fmt: enum literal inside array literal" {
   1223     try testCanonical(
   1224         \\test "enums in arrays" {
   1225         \\    var colors = []Color{.Green};
   1226         \\    colors = []Colors{ .Green, .Cyan };
   1227         \\    colors = []Colors{
   1228         \\        .Grey,
   1229         \\        .Green,
   1230         \\        .Cyan,
   1231         \\    };
   1232         \\}
   1233         \\
   1234     );
   1235 }
   1236 
   1237 test "zig fmt: character literal larger than u8" {
   1238     try testCanonical(
   1239         \\const x = '\u{01f4a9}';
   1240         \\
   1241     );
   1242 }
   1243 
   1244 test "zig fmt: infix operator and then multiline string literal" {
   1245     try testCanonical(
   1246         \\const x = "" ++
   1247         \\    \\ hi
   1248         \\;
   1249         \\
   1250     );
   1251 }
   1252 
   1253 test "zig fmt: infix operator and then multiline string literal over multiple lines" {
   1254     try testCanonical(
   1255         \\const x = "" ++
   1256         \\    \\ hi0
   1257         \\    \\ hi1
   1258         \\    \\ hi2
   1259         \\;
   1260         \\
   1261     );
   1262 }
   1263 
   1264 test "zig fmt: C pointers" {
   1265     try testCanonical(
   1266         \\const Ptr = [*c]i32;
   1267         \\
   1268     );
   1269 }
   1270 
   1271 test "zig fmt: threadlocal" {
   1272     try testCanonical(
   1273         \\threadlocal var x: i32 = 1234;
   1274         \\
   1275     );
   1276 }
   1277 
   1278 test "zig fmt: linksection" {
   1279     try testCanonical(
   1280         \\export var aoeu: u64 linksection(".text.derp") = 1234;
   1281         \\export fn _start() linksection(".text.boot") callconv(.naked) noreturn {}
   1282         \\
   1283     );
   1284 }
   1285 
   1286 test "zig fmt: addrspace" {
   1287     try testCanonical(
   1288         \\export var python_length: u64 align(1) addrspace(.generic);
   1289         \\export var python_color: Color addrspace(.generic) = .green;
   1290         \\export var python_legs: u0 align(8) addrspace(.generic) linksection(".python") = 0;
   1291         \\export fn python_hiss() align(8) addrspace(.generic) linksection(".python") void;
   1292         \\
   1293     );
   1294 }
   1295 
   1296 test "zig fmt: correctly space struct fields with doc comments" {
   1297     try testTransform(
   1298         \\pub const S = struct {
   1299         \\    /// A
   1300         \\    a: u8,
   1301         \\    /// B
   1302         \\    /// B (cont)
   1303         \\    b: u8,
   1304         \\
   1305         \\
   1306         \\    /// C
   1307         \\    c: u8,
   1308         \\};
   1309         \\
   1310     ,
   1311         \\pub const S = struct {
   1312         \\    /// A
   1313         \\    a: u8,
   1314         \\    /// B
   1315         \\    /// B (cont)
   1316         \\    b: u8,
   1317         \\
   1318         \\    /// C
   1319         \\    c: u8,
   1320         \\};
   1321         \\
   1322     );
   1323 }
   1324 
   1325 test "zig fmt: doc comments on param decl" {
   1326     try testCanonical(
   1327         \\pub const Allocator = struct {
   1328         \\    shrinkFn: fn (
   1329         \\        self: Allocator,
   1330         \\        /// Guaranteed to be the same as what was returned from most recent call to
   1331         \\        /// `allocFn`, `reallocFn`, or `shrinkFn`.
   1332         \\        old_mem: []u8,
   1333         \\        /// Guaranteed to be the same as what was returned from most recent call to
   1334         \\        /// `allocFn`, `reallocFn`, or `shrinkFn`.
   1335         \\        old_alignment: u29,
   1336         \\        /// Guaranteed to be less than or equal to `old_mem.len`.
   1337         \\        new_byte_count: usize,
   1338         \\        /// Guaranteed to be less than or equal to `old_alignment`.
   1339         \\        new_alignment: u29,
   1340         \\    ) []u8,
   1341         \\};
   1342         \\
   1343     );
   1344 }
   1345 
   1346 test "zig fmt: aligned struct field" {
   1347     try testCanonical(
   1348         \\pub const S = struct {
   1349         \\    f: i32 align(32),
   1350         \\};
   1351         \\
   1352     );
   1353     try testCanonical(
   1354         \\pub const S = struct {
   1355         \\    f: i32 align(32) = 1,
   1356         \\};
   1357         \\
   1358     );
   1359 }
   1360 
   1361 test "zig fmt: comment to disable/enable zig fmt first" {
   1362     try testCanonical(
   1363         \\// Test trailing comma syntax
   1364         \\// zig fmt: off
   1365         \\
   1366         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1367     );
   1368 }
   1369 
   1370 test "zig fmt: 'zig fmt: (off|on)' can be surrounded by arbitrary whitespace" {
   1371     try testTransform(
   1372         \\// Test trailing comma syntax
   1373         \\//     zig fmt: off
   1374         \\
   1375         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1376         \\
   1377         \\//   zig fmt: on
   1378     ,
   1379         \\// Test trailing comma syntax
   1380         \\// zig fmt: off
   1381         \\
   1382         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1383         \\
   1384         \\// zig fmt: on
   1385         \\
   1386     );
   1387 }
   1388 
   1389 test "zig fmt: comment to disable/enable zig fmt" {
   1390     try testTransform(
   1391         \\const  a  =  b;
   1392         \\// zig fmt: off
   1393         \\const  c  =  d;
   1394         \\// zig fmt: on
   1395         \\const  e  =  f;
   1396     ,
   1397         \\const a = b;
   1398         \\// zig fmt: off
   1399         \\const  c  =  d;
   1400         \\// zig fmt: on
   1401         \\const e = f;
   1402         \\
   1403     );
   1404 }
   1405 
   1406 test "zig fmt: line comment following 'zig fmt: off'" {
   1407     try testCanonical(
   1408         \\// zig fmt: off
   1409         \\// Test
   1410         \\const  e  =  f;
   1411     );
   1412 }
   1413 
   1414 test "zig fmt: doc comment following 'zig fmt: off'" {
   1415     try testCanonical(
   1416         \\// zig fmt: off
   1417         \\/// test
   1418         \\const  e  =  f;
   1419     );
   1420 }
   1421 
   1422 test "zig fmt: line and doc comment following 'zig fmt: off'" {
   1423     try testCanonical(
   1424         \\// zig fmt: off
   1425         \\// test 1
   1426         \\/// test 2
   1427         \\const  e  =  f;
   1428     );
   1429 }
   1430 
   1431 test "zig fmt: doc and line comment following 'zig fmt: off'" {
   1432     try testCanonical(
   1433         \\// zig fmt: off
   1434         \\/// test 1
   1435         \\// test 2
   1436         \\const  e  =  f;
   1437     );
   1438 }
   1439 
   1440 test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
   1441     try testCanonical(
   1442         \\// zig fmt: off
   1443         \\// zig fmt: on
   1444         \\// zig fmt: off
   1445         \\const  e  =  f;
   1446         \\// zig fmt: off
   1447         \\// zig fmt: on
   1448         \\// zig fmt: off
   1449         \\const  a  =  b;
   1450         \\// zig fmt: on
   1451         \\const c = d;
   1452         \\// zig fmt: on
   1453         \\
   1454     );
   1455 }
   1456 
   1457 test "zig fmt: line comment following 'zig fmt: on'" {
   1458     try testCanonical(
   1459         \\// zig fmt: off
   1460         \\const  e  =  f;
   1461         \\// zig fmt: on
   1462         \\// test
   1463         \\const e = f;
   1464         \\
   1465     );
   1466 }
   1467 
   1468 test "zig fmt: doc comment following 'zig fmt: on'" {
   1469     try testCanonical(
   1470         \\// zig fmt: off
   1471         \\const  e  =  f;
   1472         \\// zig fmt: on
   1473         \\/// test
   1474         \\const e = f;
   1475         \\
   1476     );
   1477 }
   1478 
   1479 test "zig fmt: line and doc comment following 'zig fmt: on'" {
   1480     try testCanonical(
   1481         \\// zig fmt: off
   1482         \\const  e  =  f;
   1483         \\// zig fmt: on
   1484         \\// test1
   1485         \\/// test2
   1486         \\const e = f;
   1487         \\
   1488     );
   1489 }
   1490 
   1491 test "zig fmt: doc and line comment following 'zig fmt: on'" {
   1492     try testCanonical(
   1493         \\// zig fmt: off
   1494         \\const  e  =  f;
   1495         \\// zig fmt: on
   1496         \\/// test1
   1497         \\// test2
   1498         \\const e = f;
   1499         \\
   1500     );
   1501 }
   1502 
   1503 test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
   1504     try testTransform(
   1505         \\test "" {
   1506         \\    const x = 42;
   1507         \\
   1508         \\    if (foobar) |y| {
   1509         \\    // zig fmt: off
   1510         \\            }// zig fmt: on
   1511         \\
   1512         \\    const  z  = 420;
   1513         \\}
   1514         \\
   1515     ,
   1516         \\test "" {
   1517         \\    const x = 42;
   1518         \\
   1519         \\    if (foobar) |y| {
   1520         \\        // zig fmt: off
   1521         \\            }// zig fmt: on
   1522         \\
   1523         \\    const z = 420;
   1524         \\}
   1525         \\
   1526     );
   1527 }
   1528 
   1529 test "zig fmt: 'zig fmt: on' indentation is unchanged" {
   1530     try testCanonical(
   1531         \\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
   1532         \\    // zig fmt: off
   1533         \\    try output.main_amount.init(output, "main_amount"); errdefer optput.main_amount.deinit();
   1534         \\    try output.main_factor.init(output, "main_factor"); errdefer optput.main_factor.deinit();
   1535         \\    try output.view_padding.init(output, "view_padding"); errdefer optput.view_padding.deinit();
   1536         \\    try output.outer_padding.init(output, "outer_padding"); errdefer optput.outer_padding.deinit();
   1537         \\    // zig fmt: on
   1538         \\
   1539         \\    // zig fmt: off
   1540         \\    try output.top.init(output, .top); errdefer optput.top.deinit();
   1541         \\    try output.right.init(output, .right); errdefer optput.right.deinit();
   1542         \\    try output.bottom.init(output, .bottom); errdefer optput.bottom.deinit();
   1543         \\    try output.left.init(output, .left); errdefer optput.left.deinit();
   1544         \\        // zig fmt: on
   1545         \\}
   1546         \\
   1547     );
   1548 }
   1549 
   1550 test "zig fmt: pointer of unknown length" {
   1551     try testCanonical(
   1552         \\fn foo(ptr: [*]u8) void {}
   1553         \\
   1554     );
   1555 }
   1556 
   1557 test "zig fmt: spaces around slice operator" {
   1558     try testCanonical(
   1559         \\var a = b[c..d];
   1560         \\var a = b[c..d :0];
   1561         \\var a = b[c + 1 .. d];
   1562         \\var a = b[c + 1 ..];
   1563         \\var a = b[c .. d + 1];
   1564         \\var a = b[c .. d + 1 :0];
   1565         \\var a = b[c.a..d.e];
   1566         \\var a = b[c.a..d.e :0];
   1567         \\
   1568     );
   1569 }
   1570 
   1571 test "zig fmt: 2nd arg multiline string" {
   1572     try testCanonical(
   1573         \\comptime {
   1574         \\    cases.addAsm("hello world linux x86_64",
   1575         \\        \\.text
   1576         \\    , "Hello, world!\n");
   1577         \\}
   1578         \\
   1579     );
   1580     try testTransform(
   1581         \\comptime {
   1582         \\    cases.addAsm("hello world linux x86_64",
   1583         \\        \\.text
   1584         \\    , "Hello, world!\n",);
   1585         \\}
   1586     ,
   1587         \\comptime {
   1588         \\    cases.addAsm(
   1589         \\        "hello world linux x86_64",
   1590         \\        \\.text
   1591         \\    ,
   1592         \\        "Hello, world!\n",
   1593         \\    );
   1594         \\}
   1595         \\
   1596     );
   1597 }
   1598 
   1599 test "zig fmt: 2nd arg multiline string many args" {
   1600     try testCanonical(
   1601         \\comptime {
   1602         \\    cases.addAsm("hello world linux x86_64",
   1603         \\        \\.text
   1604         \\    , "Hello, world!\n", "Hello, world!\n");
   1605         \\}
   1606         \\
   1607     );
   1608 }
   1609 
   1610 test "zig fmt: final arg multiline string" {
   1611     try testCanonical(
   1612         \\comptime {
   1613         \\    cases.addAsm("hello world linux x86_64", "Hello, world!\n",
   1614         \\        \\.text
   1615         \\    );
   1616         \\}
   1617         \\
   1618     );
   1619 }
   1620 
   1621 test "zig fmt: if condition wraps" {
   1622     try testTransform(
   1623         \\comptime {
   1624         \\    if (cond and
   1625         \\        cond) {
   1626         \\        return x;
   1627         \\    }
   1628         \\    while (cond and
   1629         \\        cond) {
   1630         \\        return x;
   1631         \\    }
   1632         \\    if (a == b and
   1633         \\        c) {
   1634         \\        a = b;
   1635         \\    }
   1636         \\    while (a == b and
   1637         \\        c) {
   1638         \\        a = b;
   1639         \\    }
   1640         \\    if ((cond and
   1641         \\        cond)) {
   1642         \\        return x;
   1643         \\    }
   1644         \\    while ((cond and
   1645         \\        cond)) {
   1646         \\        return x;
   1647         \\    }
   1648         \\    var a = if (a) |*f| x: {
   1649         \\        break :x &a.b;
   1650         \\    } else |err| err;
   1651         \\    var a = if (cond and
   1652         \\                cond) |*f|
   1653         \\    x: {
   1654         \\        break :x &a.b;
   1655         \\    } else |err| err;
   1656         \\}
   1657     ,
   1658         \\comptime {
   1659         \\    if (cond and
   1660         \\        cond)
   1661         \\    {
   1662         \\        return x;
   1663         \\    }
   1664         \\    while (cond and
   1665         \\        cond)
   1666         \\    {
   1667         \\        return x;
   1668         \\    }
   1669         \\    if (a == b and
   1670         \\        c)
   1671         \\    {
   1672         \\        a = b;
   1673         \\    }
   1674         \\    while (a == b and
   1675         \\        c)
   1676         \\    {
   1677         \\        a = b;
   1678         \\    }
   1679         \\    if ((cond and
   1680         \\        cond))
   1681         \\    {
   1682         \\        return x;
   1683         \\    }
   1684         \\    while ((cond and
   1685         \\        cond))
   1686         \\    {
   1687         \\        return x;
   1688         \\    }
   1689         \\    var a = if (a) |*f| x: {
   1690         \\        break :x &a.b;
   1691         \\    } else |err| err;
   1692         \\    var a = if (cond and
   1693         \\        cond) |*f|
   1694         \\    x: {
   1695         \\        break :x &a.b;
   1696         \\    } else |err| err;
   1697         \\}
   1698         \\
   1699     );
   1700 }
   1701 
   1702 test "zig fmt: if condition has line break but must not wrap" {
   1703     try testCanonical(
   1704         \\comptime {
   1705         \\    if (self.user_input_options.put(
   1706         \\        name,
   1707         \\        UserInputOption{
   1708         \\            .name = name,
   1709         \\            .used = false,
   1710         \\        },
   1711         \\    ) catch unreachable) |*prev_value| {
   1712         \\        foo();
   1713         \\        bar();
   1714         \\    }
   1715         \\    if (put(
   1716         \\        a,
   1717         \\        b,
   1718         \\    )) {
   1719         \\        foo();
   1720         \\    }
   1721         \\}
   1722         \\
   1723     );
   1724 }
   1725 
   1726 test "zig fmt: if condition has line break but must not wrap (no fn call comma)" {
   1727     try testCanonical(
   1728         \\comptime {
   1729         \\    if (self.user_input_options.put(name, UserInputOption{
   1730         \\        .name = name,
   1731         \\        .used = false,
   1732         \\    }) catch unreachable) |*prev_value| {
   1733         \\        foo();
   1734         \\        bar();
   1735         \\    }
   1736         \\    if (put(
   1737         \\        a,
   1738         \\        b,
   1739         \\    )) {
   1740         \\        foo();
   1741         \\    }
   1742         \\}
   1743         \\
   1744     );
   1745 }
   1746 
   1747 test "zig fmt: function call with multiline argument" {
   1748     try testCanonical(
   1749         \\comptime {
   1750         \\    self.user_input_options.put(name, UserInputOption{
   1751         \\        .name = name,
   1752         \\        .used = false,
   1753         \\    });
   1754         \\}
   1755         \\
   1756     );
   1757 }
   1758 
   1759 test "zig fmt: if-else with comment before else" {
   1760     try testCanonical(
   1761         \\comptime {
   1762         \\    // cexp(finite|nan +- i inf|nan) = nan + i nan
   1763         \\    if ((hx & 0x7fffffff) != 0x7f800000) {
   1764         \\        return Complex(f32).init(y - y, y - y);
   1765         \\    } // cexp(-inf +- i inf|nan) = 0 + i0
   1766         \\    else if (hx & 0x80000000 != 0) {
   1767         \\        return Complex(f32).init(0, 0);
   1768         \\    } // cexp(+inf +- i inf|nan) = inf + i nan
   1769         \\    else {
   1770         \\        return Complex(f32).init(x, y - y);
   1771         \\    }
   1772         \\}
   1773         \\
   1774     );
   1775 }
   1776 
   1777 test "zig fmt: if nested" {
   1778     try testCanonical(
   1779         \\pub fn foo() void {
   1780         \\    return if ((aInt & bInt) >= 0)
   1781         \\        if (aInt < bInt)
   1782         \\            GE_LESS
   1783         \\        else if (aInt == bInt)
   1784         \\            GE_EQUAL
   1785         \\        else
   1786         \\            GE_GREATER
   1787         \\            // comment
   1788         \\    else if (aInt > bInt)
   1789         \\        GE_LESS
   1790         \\    else if (aInt == bInt)
   1791         \\        GE_EQUAL
   1792         \\    else
   1793         \\        GE_GREATER;
   1794         \\    // comment
   1795         \\}
   1796         \\
   1797     );
   1798 }
   1799 
   1800 test "zig fmt: respect line breaks in if-else" {
   1801     try testCanonical(
   1802         \\comptime {
   1803         \\    return if (cond) a else b;
   1804         \\    return if (cond)
   1805         \\        a
   1806         \\    else
   1807         \\        b;
   1808         \\    return if (cond)
   1809         \\        a
   1810         \\    else if (cond)
   1811         \\        b
   1812         \\    else
   1813         \\        c;
   1814         \\}
   1815         \\
   1816     );
   1817 }
   1818 
   1819 test "zig fmt: respect line breaks after infix operators" {
   1820     try testCanonical(
   1821         \\comptime {
   1822         \\    self.crc =
   1823         \\        lookup_tables[0][p[7]] ^
   1824         \\        lookup_tables[1][p[6]] ^
   1825         \\        lookup_tables[2][p[5]] ^
   1826         \\        lookup_tables[3][p[4]] ^
   1827         \\        lookup_tables[4][@as(u8, self.crc >> 24)] ^
   1828         \\        lookup_tables[5][@as(u8, self.crc >> 16)] ^
   1829         \\        lookup_tables[6][@as(u8, self.crc >> 8)] ^
   1830         \\        lookup_tables[7][@as(u8, self.crc >> 0)];
   1831         \\}
   1832         \\
   1833     );
   1834 }
   1835 
   1836 test "zig fmt: fn decl with trailing comma" {
   1837     try testTransform(
   1838         \\fn foo(a: i32, b: i32,) void {}
   1839     ,
   1840         \\fn foo(
   1841         \\    a: i32,
   1842         \\    b: i32,
   1843         \\) void {}
   1844         \\
   1845     );
   1846 }
   1847 
   1848 test "zig fmt: enum decl with no trailing comma" {
   1849     try testTransform(
   1850         \\const StrLitKind = enum {Normal, C};
   1851     ,
   1852         \\const StrLitKind = enum { Normal, C };
   1853         \\
   1854     );
   1855 }
   1856 
   1857 test "zig fmt: switch comment before prong" {
   1858     try testCanonical(
   1859         \\comptime {
   1860         \\    switch (a) {
   1861         \\        // hi
   1862         \\        0 => {},
   1863         \\    }
   1864         \\}
   1865         \\
   1866     );
   1867 }
   1868 
   1869 test "zig fmt: switch comment after prong" {
   1870     try testCanonical(
   1871         \\comptime {
   1872         \\    switch (a) {
   1873         \\        0,
   1874         \\        // hi
   1875         \\        => {},
   1876         \\    }
   1877         \\}
   1878         \\
   1879     );
   1880 }
   1881 
   1882 test "zig fmt: struct literal no trailing comma" {
   1883     try testTransform(
   1884         \\const a = foo{ .x = 1, .y = 2 };
   1885         \\const a = foo{ .x = 1,
   1886         \\    .y = 2 };
   1887         \\const a = foo{ .x = 1,
   1888         \\    .y = 2, };
   1889     ,
   1890         \\const a = foo{ .x = 1, .y = 2 };
   1891         \\const a = foo{ .x = 1, .y = 2 };
   1892         \\const a = foo{
   1893         \\    .x = 1,
   1894         \\    .y = 2,
   1895         \\};
   1896         \\
   1897     );
   1898 }
   1899 
   1900 test "zig fmt: struct literal containing a multiline expression" {
   1901     try testTransform(
   1902         \\const a = A{ .x = if (f1()) 10 else 20 };
   1903         \\const a = A{ .x = if (f1()) 10 else 20, };
   1904         \\const a = A{ .x = if (f1())
   1905         \\    10 else 20 };
   1906         \\const a = A{ .x = if (f1())
   1907         \\    10 else 20,};
   1908         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
   1909         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };
   1910         \\const a = A{ .x = if (f1())
   1911         \\    10 else 20};
   1912         \\const a = A{ .x = if (f1())
   1913         \\    10 else 20,};
   1914         \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };
   1915         \\const a = A{ .x = switch(g) {0 => "ok", else => "no"}, };
   1916         \\
   1917     ,
   1918         \\const a = A{ .x = if (f1()) 10 else 20 };
   1919         \\const a = A{
   1920         \\    .x = if (f1()) 10 else 20,
   1921         \\};
   1922         \\const a = A{ .x = if (f1())
   1923         \\    10
   1924         \\else
   1925         \\    20 };
   1926         \\const a = A{
   1927         \\    .x = if (f1())
   1928         \\        10
   1929         \\    else
   1930         \\        20,
   1931         \\};
   1932         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
   1933         \\const a = A{
   1934         \\    .x = if (f1()) 10 else 20,
   1935         \\    .y = f2() + 100,
   1936         \\};
   1937         \\const a = A{ .x = if (f1())
   1938         \\    10
   1939         \\else
   1940         \\    20 };
   1941         \\const a = A{
   1942         \\    .x = if (f1())
   1943         \\        10
   1944         \\    else
   1945         \\        20,
   1946         \\};
   1947         \\const a = A{ .x = switch (g) {
   1948         \\    0 => "ok",
   1949         \\    else => "no",
   1950         \\} };
   1951         \\const a = A{
   1952         \\    .x = switch (g) {
   1953         \\        0 => "ok",
   1954         \\        else => "no",
   1955         \\    },
   1956         \\};
   1957         \\
   1958     );
   1959 }
   1960 
   1961 test "zig fmt: array literal with hint" {
   1962     try testTransform(
   1963         \\const a = []u8{
   1964         \\    1, 2, //
   1965         \\    3,
   1966         \\    4,
   1967         \\    5,
   1968         \\    6,
   1969         \\    7 };
   1970         \\const a = []u8{
   1971         \\    1, 2, //
   1972         \\    3,
   1973         \\    4,
   1974         \\    5,
   1975         \\    6,
   1976         \\    7, 8 };
   1977         \\const a = []u8{
   1978         \\    1, 2, //
   1979         \\    3,
   1980         \\    4,
   1981         \\    5,
   1982         \\    6, // blah
   1983         \\    7, 8 };
   1984         \\const a = []u8{
   1985         \\    1, 2, //
   1986         \\    3, //
   1987         \\    4,
   1988         \\    5,
   1989         \\    6,
   1990         \\    7 };
   1991         \\const a = []u8{
   1992         \\    1,
   1993         \\    2,
   1994         \\    3, 4, //
   1995         \\    5, 6, //
   1996         \\    7, 8, //
   1997         \\};
   1998     ,
   1999         \\const a = []u8{
   2000         \\    1, 2, //
   2001         \\    3, 4,
   2002         \\    5, 6,
   2003         \\    7,
   2004         \\};
   2005         \\const a = []u8{
   2006         \\    1, 2, //
   2007         \\    3, 4,
   2008         \\    5, 6,
   2009         \\    7, 8,
   2010         \\};
   2011         \\const a = []u8{
   2012         \\    1, 2, //
   2013         \\    3, 4,
   2014         \\    5,
   2015         \\    6, // blah
   2016         \\    7,
   2017         \\    8,
   2018         \\};
   2019         \\const a = []u8{
   2020         \\    1, 2, //
   2021         \\    3, //
   2022         \\    4,
   2023         \\    5,
   2024         \\    6,
   2025         \\    7,
   2026         \\};
   2027         \\const a = []u8{
   2028         \\    1,
   2029         \\    2,
   2030         \\    3, 4, //
   2031         \\    5, 6, //
   2032         \\    7, 8, //
   2033         \\};
   2034         \\
   2035     );
   2036 }
   2037 
   2038 test "zig fmt: array literal vertical column alignment" {
   2039     try testTransform(
   2040         \\const a = []u8{
   2041         \\    1000, 200,
   2042         \\    30, 4,
   2043         \\    50000, 60,
   2044         \\};
   2045         \\const a = []u8{0,   1, 2, 3, 40,
   2046         \\    4,5,600,7,
   2047         \\           80,
   2048         \\    9, 10, 11, 0, 13, 14, 15,};
   2049         \\const a = [12]u8{
   2050         \\    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   2051         \\const a = [12]u8{
   2052         \\    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, };
   2053         \\
   2054     ,
   2055         \\const a = []u8{
   2056         \\    1000,  200,
   2057         \\    30,    4,
   2058         \\    50000, 60,
   2059         \\};
   2060         \\const a = []u8{
   2061         \\    0,  1,  2,   3, 40,
   2062         \\    4,  5,  600, 7, 80,
   2063         \\    9,  10, 11,  0, 13,
   2064         \\    14, 15,
   2065         \\};
   2066         \\const a = [12]u8{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   2067         \\const a = [12]u8{
   2068         \\    31,
   2069         \\    28,
   2070         \\    31,
   2071         \\    30,
   2072         \\    31,
   2073         \\    30,
   2074         \\    31,
   2075         \\    31,
   2076         \\    30,
   2077         \\    31,
   2078         \\    30,
   2079         \\    31,
   2080         \\};
   2081         \\
   2082     );
   2083 }
   2084 
   2085 test "zig fmt: multiline string with backslash at end of line" {
   2086     try testCanonical(
   2087         \\comptime {
   2088         \\    err(
   2089         \\        \\\
   2090         \\    );
   2091         \\}
   2092         \\
   2093     );
   2094 }
   2095 
   2096 test "zig fmt: multiline string parameter in fn call with trailing comma" {
   2097     try testCanonical(
   2098         \\fn foo() void {
   2099         \\    try stdout.print(
   2100         \\        \\ZIG_CMAKE_BINARY_DIR {s}
   2101         \\        \\ZIG_C_HEADER_FILES   {s}
   2102         \\        \\ZIG_DIA_GUIDS_LIB    {s}
   2103         \\        \\
   2104         \\    ,
   2105         \\        std.mem.sliceTo(c.ZIG_CMAKE_BINARY_DIR, 0),
   2106         \\        std.mem.sliceTo(c.ZIG_CXX_COMPILER, 0),
   2107         \\        std.mem.sliceTo(c.ZIG_DIA_GUIDS_LIB, 0),
   2108         \\    );
   2109         \\}
   2110         \\
   2111     );
   2112 }
   2113 
   2114 test "zig fmt: trailing comma on fn call" {
   2115     try testCanonical(
   2116         \\comptime {
   2117         \\    var module = try Module.create(
   2118         \\        allocator,
   2119         \\        zig_lib_dir,
   2120         \\        full_cache_dir,
   2121         \\    );
   2122         \\}
   2123         \\
   2124     );
   2125 }
   2126 
   2127 test "zig fmt: multi line arguments without last comma" {
   2128     try testTransform(
   2129         \\pub fn foo(
   2130         \\    a: usize,
   2131         \\    b: usize,
   2132         \\    c: usize,
   2133         \\    d: usize
   2134         \\) usize {
   2135         \\    return a + b + c + d;
   2136         \\}
   2137         \\
   2138     ,
   2139         \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
   2140         \\    return a + b + c + d;
   2141         \\}
   2142         \\
   2143     );
   2144 }
   2145 
   2146 test "zig fmt: empty block with only comment" {
   2147     try testCanonical(
   2148         \\comptime {
   2149         \\    {
   2150         \\        // comment
   2151         \\    }
   2152         \\}
   2153         \\
   2154     );
   2155 }
   2156 
   2157 test "zig fmt: trailing commas on struct decl" {
   2158     try testTransform(
   2159         \\const RoundParam = struct {
   2160         \\    k: usize, s: u32, t: u32
   2161         \\};
   2162         \\const RoundParam = struct {
   2163         \\    k: usize, s: u32, t: u32,
   2164         \\};
   2165     ,
   2166         \\const RoundParam = struct { k: usize, s: u32, t: u32 };
   2167         \\const RoundParam = struct {
   2168         \\    k: usize,
   2169         \\    s: u32,
   2170         \\    t: u32,
   2171         \\};
   2172         \\
   2173     );
   2174 }
   2175 
   2176 test "zig fmt: extra newlines at the end" {
   2177     try testTransform(
   2178         \\const a = b;
   2179         \\
   2180         \\
   2181         \\
   2182     ,
   2183         \\const a = b;
   2184         \\
   2185     );
   2186 }
   2187 
   2188 test "zig fmt: simple asm" {
   2189     try testTransform(
   2190         \\comptime {
   2191         \\    asm volatile (
   2192         \\        \\.globl aoeu;
   2193         \\        \\.type aoeu, @function;
   2194         \\        \\.set aoeu, derp;
   2195         \\    );
   2196         \\
   2197         \\    asm ("not real assembly"
   2198         \\        :[a] "x" (x),);
   2199         \\    asm ("not real assembly"
   2200         \\        :[a] "x" (->i32),:[a] "x" (1),);
   2201         \\    asm ("still not real assembly"
   2202         \\        :::"a","b",);
   2203         \\}
   2204     ,
   2205         \\comptime {
   2206         \\    asm volatile (
   2207         \\        \\.globl aoeu;
   2208         \\        \\.type aoeu, @function;
   2209         \\        \\.set aoeu, derp;
   2210         \\    );
   2211         \\
   2212         \\    asm ("not real assembly"
   2213         \\        : [a] "x" (x),
   2214         \\    );
   2215         \\    asm ("not real assembly"
   2216         \\        : [a] "x" (-> i32),
   2217         \\        : [a] "x" (1),
   2218         \\    );
   2219         \\    asm ("still not real assembly" ::: .{ .a = true, .b = true });
   2220         \\}
   2221         \\
   2222     );
   2223 }
   2224 
   2225 test "zig fmt: nested struct literal with one item" {
   2226     try testCanonical(
   2227         \\const a = foo{
   2228         \\    .item = bar{ .a = b },
   2229         \\};
   2230         \\
   2231     );
   2232 }
   2233 
   2234 test "zig fmt: switch cases trailing comma" {
   2235     try testTransform(
   2236         \\test "switch cases trailing comma"{
   2237         \\    switch (x) {
   2238         \\        1,2,3 => {},
   2239         \\        4,5, => {},
   2240         \\        6... 8, => {},
   2241         \\        9 ...
   2242         \\        10 => {},
   2243         \\        11 => {},
   2244         \\        12, => {},
   2245         \\        else => {},
   2246         \\    }
   2247         \\}
   2248     ,
   2249         \\test "switch cases trailing comma" {
   2250         \\    switch (x) {
   2251         \\        1, 2, 3 => {},
   2252         \\        4,
   2253         \\        5,
   2254         \\        => {},
   2255         \\        6...8,
   2256         \\        => {},
   2257         \\        9...10 => {},
   2258         \\        11 => {},
   2259         \\        12,
   2260         \\        => {},
   2261         \\        else => {},
   2262         \\    }
   2263         \\}
   2264         \\
   2265     );
   2266 }
   2267 
   2268 test "zig fmt: slice align" {
   2269     try testCanonical(
   2270         \\const A = struct {
   2271         \\    items: []align(A) T,
   2272         \\};
   2273         \\
   2274     );
   2275 }
   2276 
   2277 test "zig fmt: add trailing comma to array literal" {
   2278     try testTransform(
   2279         \\comptime {
   2280         \\    return []u16{'m', 's', 'y', 's', '-' // hi
   2281         \\   };
   2282         \\    return []u16{'m', 's', 'y', 's',
   2283         \\      '-'};
   2284         \\    return []u16{'m', 's', 'y', 's', '-'};
   2285         \\}
   2286     ,
   2287         \\comptime {
   2288         \\    return []u16{
   2289         \\        'm', 's', 'y', 's', '-', // hi
   2290         \\    };
   2291         \\    return []u16{ 'm', 's', 'y', 's', '-' };
   2292         \\    return []u16{ 'm', 's', 'y', 's', '-' };
   2293         \\}
   2294         \\
   2295     );
   2296 }
   2297 
   2298 test "zig fmt: first thing in file is line comment" {
   2299     try testCanonical(
   2300         \\// Introspection and determination of system libraries needed by zig.
   2301         \\
   2302         \\// Introspection and determination of system libraries needed by zig.
   2303         \\
   2304         \\const std = @import("std");
   2305         \\
   2306     );
   2307 }
   2308 
   2309 test "zig fmt: line comment after doc comment" {
   2310     try testCanonical(
   2311         \\/// doc comment
   2312         \\// line comment
   2313         \\fn foo() void {}
   2314         \\
   2315     );
   2316 }
   2317 
   2318 test "zig fmt: bit field alignment" {
   2319     try testCanonical(
   2320         \\test {
   2321         \\    assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
   2322         \\}
   2323         \\
   2324     );
   2325 }
   2326 
   2327 test "zig fmt: nested switch" {
   2328     try testCanonical(
   2329         \\test {
   2330         \\    switch (state) {
   2331         \\        TermState.Start => switch (c) {
   2332         \\            '\x1b' => state = TermState.Escape,
   2333         \\            else => try out.writeByte(c),
   2334         \\        },
   2335         \\    }
   2336         \\}
   2337         \\
   2338     );
   2339 }
   2340 
   2341 test "zig fmt: float literal with exponent" {
   2342     try testCanonical(
   2343         \\pub const f64_true_min = 4.94065645841246544177e-324;
   2344         \\const threshold = 0x1.a827999fcef32p+1022;
   2345         \\
   2346     );
   2347 }
   2348 
   2349 test "zig fmt: if-else end of comptime" {
   2350     try testCanonical(
   2351         \\comptime {
   2352         \\    if (a) {
   2353         \\        b();
   2354         \\    } else {
   2355         \\        b();
   2356         \\    }
   2357         \\}
   2358         \\
   2359     );
   2360 }
   2361 
   2362 test "zig fmt: nested blocks" {
   2363     try testCanonical(
   2364         \\comptime {
   2365         \\    {
   2366         \\        {
   2367         \\            {
   2368         \\                a();
   2369         \\            }
   2370         \\        }
   2371         \\    }
   2372         \\}
   2373         \\
   2374     );
   2375 }
   2376 
   2377 test "zig fmt: block with same line comment after end brace" {
   2378     try testCanonical(
   2379         \\comptime {
   2380         \\    {
   2381         \\        b();
   2382         \\    } // comment
   2383         \\}
   2384         \\
   2385     );
   2386 }
   2387 
   2388 test "zig fmt: statements with comment between" {
   2389     try testCanonical(
   2390         \\comptime {
   2391         \\    a = b;
   2392         \\    // comment
   2393         \\    a = b;
   2394         \\}
   2395         \\
   2396     );
   2397 }
   2398 
   2399 test "zig fmt: statements with empty line between" {
   2400     try testCanonical(
   2401         \\comptime {
   2402         \\    a = b;
   2403         \\
   2404         \\    a = b;
   2405         \\}
   2406         \\
   2407     );
   2408 }
   2409 
   2410 test "zig fmt: ptr deref operator and unwrap optional operator" {
   2411     try testCanonical(
   2412         \\const a = b.*;
   2413         \\const a = b.?;
   2414         \\
   2415     );
   2416 }
   2417 
   2418 test "zig fmt: comment after if before another if" {
   2419     try testCanonical(
   2420         \\test "aoeu" {
   2421         \\    // comment
   2422         \\    if (x) {
   2423         \\        bar();
   2424         \\    }
   2425         \\}
   2426         \\
   2427         \\test "aoeu" {
   2428         \\    if (x) {
   2429         \\        foo();
   2430         \\    }
   2431         \\    // comment
   2432         \\    if (x) {
   2433         \\        bar();
   2434         \\    }
   2435         \\}
   2436         \\
   2437     );
   2438 }
   2439 
   2440 test "zig fmt: line comment between if block and else keyword" {
   2441     try testCanonical(
   2442         \\test "aoeu" {
   2443         \\    // cexp(finite|nan +- i inf|nan) = nan + i nan
   2444         \\    if ((hx & 0x7fffffff) != 0x7f800000) {
   2445         \\        return Complex(f32).init(y - y, y - y);
   2446         \\    }
   2447         \\    // cexp(-inf +- i inf|nan) = 0 + i0
   2448         \\    else if (hx & 0x80000000 != 0) {
   2449         \\        return Complex(f32).init(0, 0);
   2450         \\    }
   2451         \\    // cexp(+inf +- i inf|nan) = inf + i nan
   2452         \\    // another comment
   2453         \\    else {
   2454         \\        return Complex(f32).init(x, y - y);
   2455         \\    }
   2456         \\}
   2457         \\
   2458     );
   2459 }
   2460 
   2461 test "zig fmt: same line comments in expression" {
   2462     try testCanonical(
   2463         \\test "aoeu" {
   2464         \\    const x = ( // a
   2465         \\        0 // b
   2466         \\    ); // c
   2467         \\}
   2468         \\
   2469     );
   2470 }
   2471 
   2472 test "zig fmt: add comma on last switch prong" {
   2473     try testTransform(
   2474         \\test "aoeu" {
   2475         \\switch (self.init_arg_expr) {
   2476         \\    InitArg.Type => |t| { },
   2477         \\    InitArg.None,
   2478         \\    InitArg.Enum => { }
   2479         \\}
   2480         \\ switch (self.init_arg_expr) {
   2481         \\     InitArg.Type => |t| { },
   2482         \\     InitArg.None,
   2483         \\     InitArg.Enum => { }//line comment
   2484         \\ }
   2485         \\}
   2486     ,
   2487         \\test "aoeu" {
   2488         \\    switch (self.init_arg_expr) {
   2489         \\        InitArg.Type => |t| {},
   2490         \\        InitArg.None, InitArg.Enum => {},
   2491         \\    }
   2492         \\    switch (self.init_arg_expr) {
   2493         \\        InitArg.Type => |t| {},
   2494         \\        InitArg.None, InitArg.Enum => {}, //line comment
   2495         \\    }
   2496         \\}
   2497         \\
   2498     );
   2499 }
   2500 
   2501 test "zig fmt: same-line comment after a statement" {
   2502     try testCanonical(
   2503         \\test "" {
   2504         \\    a = b;
   2505         \\    debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
   2506         \\    a = b;
   2507         \\}
   2508         \\
   2509     );
   2510 }
   2511 
   2512 test "zig fmt: same-line comment after var decl in struct" {
   2513     try testCanonical(
   2514         \\pub const vfs_cap_data = extern struct {
   2515         \\    const Data = struct {}; // when on disk.
   2516         \\};
   2517         \\
   2518     );
   2519 }
   2520 
   2521 test "zig fmt: same-line comment after field decl" {
   2522     try testCanonical(
   2523         \\pub const dirent = extern struct {
   2524         \\    d_name: u8,
   2525         \\    d_name: u8, // comment 1
   2526         \\    d_name: u8,
   2527         \\    d_name: u8, // comment 2
   2528         \\    d_name: u8,
   2529         \\};
   2530         \\
   2531     );
   2532 }
   2533 
   2534 test "zig fmt: same-line comment after switch prong" {
   2535     try testCanonical(
   2536         \\test "" {
   2537         \\    switch (err) {
   2538         \\        error.PathAlreadyExists => {}, // comment 2
   2539         \\        else => return err, // comment 1
   2540         \\    }
   2541         \\}
   2542         \\
   2543     );
   2544 }
   2545 
   2546 test "zig fmt: same-line comment after non-block if expression" {
   2547     try testCanonical(
   2548         \\comptime {
   2549         \\    if (sr > n_uword_bits - 1) // d > r
   2550         \\        return 0;
   2551         \\}
   2552         \\
   2553     );
   2554 }
   2555 
   2556 test "zig fmt: same-line comment on comptime expression" {
   2557     try testCanonical(
   2558         \\test "" {
   2559         \\    comptime assert(@typeInfo(T) == .int); // must pass an integer to absInt
   2560         \\}
   2561         \\
   2562     );
   2563 }
   2564 
   2565 test "zig fmt: switch with empty body" {
   2566     try testCanonical(
   2567         \\test "" {
   2568         \\    foo() catch |err| switch (err) {};
   2569         \\}
   2570         \\
   2571     );
   2572 }
   2573 
   2574 test "zig fmt: line comments in struct initializer" {
   2575     try testCanonical(
   2576         \\fn foo() void {
   2577         \\    return Self{
   2578         \\        .a = b,
   2579         \\
   2580         \\        // Initialize these two fields to buffer_size so that
   2581         \\        // in `readFn` we treat the state as being able to read
   2582         \\        .start_index = buffer_size,
   2583         \\        .end_index = buffer_size,
   2584         \\
   2585         \\        // middle
   2586         \\
   2587         \\        .a = b,
   2588         \\
   2589         \\        // end
   2590         \\    };
   2591         \\}
   2592         \\
   2593     );
   2594 }
   2595 
   2596 test "zig fmt: first line comment in struct initializer" {
   2597     try testCanonical(
   2598         \\pub fn acquire(self: *Self) HeldLock {
   2599         \\    return HeldLock{
   2600         \\        // guaranteed allocation elision
   2601         \\        .held = self.lock.acquire(),
   2602         \\        .value = &self.private_data,
   2603         \\    };
   2604         \\}
   2605         \\
   2606     );
   2607 }
   2608 
   2609 test "zig fmt: doc comments before struct field" {
   2610     try testCanonical(
   2611         \\pub const Allocator = struct {
   2612         \\    /// Allocate byte_count bytes and return them in a slice, with the
   2613         \\    /// slice's pointer aligned at least to alignment bytes.
   2614         \\    allocFn: fn () void,
   2615         \\};
   2616         \\
   2617     );
   2618 }
   2619 
   2620 test "zig fmt: error set declaration" {
   2621     try testCanonical(
   2622         \\const E = error{
   2623         \\    A,
   2624         \\    B,
   2625         \\
   2626         \\    C,
   2627         \\};
   2628         \\
   2629         \\const Error = error{
   2630         \\    /// no more memory
   2631         \\    OutOfMemory,
   2632         \\};
   2633         \\
   2634         \\const Error = error{
   2635         \\    /// no more memory
   2636         \\    OutOfMemory,
   2637         \\
   2638         \\    /// another
   2639         \\    Another,
   2640         \\
   2641         \\    // end
   2642         \\};
   2643         \\
   2644         \\const Error = error{OutOfMemory};
   2645         \\const Error = error{};
   2646         \\
   2647         \\const Error = error{ OutOfMemory, OutOfTime };
   2648         \\
   2649     );
   2650 }
   2651 
   2652 test "zig fmt: union(enum(u32)) with assigned enum values" {
   2653     try testCanonical(
   2654         \\const MultipleChoice = union(enum(u32)) {
   2655         \\    A = 20,
   2656         \\    B = 40,
   2657         \\    C = 60,
   2658         \\    D = 1000,
   2659         \\};
   2660         \\
   2661     );
   2662 }
   2663 
   2664 test "zig fmt: resume from suspend block" {
   2665     try testCanonical(
   2666         \\fn foo() void {
   2667         \\    suspend {
   2668         \\        resume @frame();
   2669         \\    }
   2670         \\}
   2671         \\
   2672     );
   2673 }
   2674 
   2675 test "zig fmt: comments before error set decl" {
   2676     try testCanonical(
   2677         \\const UnexpectedError = error{
   2678         \\    /// The Operating System returned an undocumented error code.
   2679         \\    Unexpected,
   2680         \\    // another
   2681         \\    Another,
   2682         \\
   2683         \\    // in between
   2684         \\
   2685         \\    // at end
   2686         \\};
   2687         \\
   2688     );
   2689 }
   2690 
   2691 test "zig fmt: comments before switch prong" {
   2692     try testCanonical(
   2693         \\test "" {
   2694         \\    switch (err) {
   2695         \\        error.PathAlreadyExists => continue,
   2696         \\
   2697         \\        // comment 1
   2698         \\
   2699         \\        // comment 2
   2700         \\        else => return err,
   2701         \\        // at end
   2702         \\    }
   2703         \\}
   2704         \\
   2705     );
   2706 }
   2707 
   2708 test "zig fmt: comments before var decl in struct" {
   2709     try testCanonical(
   2710         \\pub const vfs_cap_data = extern struct {
   2711         \\    // All of these are mandated as little endian
   2712         \\    // when on disk.
   2713         \\    const Data = struct {
   2714         \\        permitted: u32,
   2715         \\        inheritable: u32,
   2716         \\    };
   2717         \\
   2718         \\    // in between
   2719         \\
   2720         \\    /// All of these are mandated as little endian
   2721         \\    /// when on disk.
   2722         \\    const Data = struct {
   2723         \\        permitted: u32,
   2724         \\        inheritable: u32,
   2725         \\    };
   2726         \\
   2727         \\    // at end
   2728         \\};
   2729         \\
   2730     );
   2731 }
   2732 
   2733 test "zig fmt: array literal with 1 item on 1 line" {
   2734     try testCanonical(
   2735         \\var s = []const u64{0} ** 25;
   2736         \\
   2737     );
   2738 }
   2739 
   2740 test "zig fmt: comments before global variables" {
   2741     try testCanonical(
   2742         \\/// Foo copies keys and values before they go into the map, and
   2743         \\/// frees them when they get removed.
   2744         \\pub const Foo = struct {};
   2745         \\
   2746     );
   2747 }
   2748 
   2749 test "zig fmt: comments in statements" {
   2750     try testCanonical(
   2751         \\test "std" {
   2752         \\    // statement comment
   2753         \\    _ = @import("foo/bar.zig");
   2754         \\
   2755         \\    // middle
   2756         \\    // middle2
   2757         \\
   2758         \\    // end
   2759         \\}
   2760         \\
   2761     );
   2762 }
   2763 
   2764 test "zig fmt: comments before test decl" {
   2765     try testCanonical(
   2766         \\// top level normal comment
   2767         \\test "hi" {}
   2768         \\
   2769         \\// middle
   2770         \\
   2771         \\// end
   2772         \\
   2773     );
   2774 }
   2775 
   2776 test "zig fmt: preserve spacing" {
   2777     try testCanonical(
   2778         \\const std = @import("std");
   2779         \\
   2780         \\pub fn main() !void {
   2781         \\    var stdout_file = std.lol.abcd;
   2782         \\    var stdout_file = std.lol.abcd;
   2783         \\
   2784         \\    var stdout_file = std.lol.abcd;
   2785         \\    var stdout_file = std.lol.abcd;
   2786         \\}
   2787         \\
   2788     );
   2789 }
   2790 
   2791 test "zig fmt: return types" {
   2792     try testCanonical(
   2793         \\pub fn main() !void {}
   2794         \\pub fn main() FooBar {}
   2795         \\pub fn main() i32 {}
   2796         \\
   2797     );
   2798 }
   2799 
   2800 test "zig fmt: imports" {
   2801     try testCanonical(
   2802         \\const std = @import("std");
   2803         \\const std = @import();
   2804         \\
   2805     );
   2806 }
   2807 
   2808 test "zig fmt: global declarations" {
   2809     try testCanonical(
   2810         \\const a = b;
   2811         \\pub const a = b;
   2812         \\var a = b;
   2813         \\pub var a = b;
   2814         \\const a: i32 = b;
   2815         \\pub const a: i32 = b;
   2816         \\var a: i32 = b;
   2817         \\pub var a: i32 = b;
   2818         \\extern const a: i32 = b;
   2819         \\pub extern const a: i32 = b;
   2820         \\extern var a: i32 = b;
   2821         \\pub extern var a: i32 = b;
   2822         \\extern "a" const a: i32 = b;
   2823         \\pub extern "a" const a: i32 = b;
   2824         \\extern "a" var a: i32 = b;
   2825         \\pub extern "a" var a: i32 = b;
   2826         \\
   2827     );
   2828 }
   2829 
   2830 test "zig fmt: extern declaration" {
   2831     try testCanonical(
   2832         \\extern var foo: c_int;
   2833         \\
   2834     );
   2835 }
   2836 
   2837 test "zig fmt: alignment" {
   2838     try testCanonical(
   2839         \\var foo: c_int align(1);
   2840         \\
   2841     );
   2842 }
   2843 
   2844 test "zig fmt: C main" {
   2845     try testCanonical(
   2846         \\fn main(argc: c_int, argv: **u8) c_int {
   2847         \\    const a = b;
   2848         \\}
   2849         \\
   2850     );
   2851 }
   2852 
   2853 test "zig fmt: return" {
   2854     try testCanonical(
   2855         \\fn foo(argc: c_int, argv: **u8) c_int {
   2856         \\    return 0;
   2857         \\}
   2858         \\
   2859         \\fn bar() void {
   2860         \\    return;
   2861         \\}
   2862         \\
   2863     );
   2864 }
   2865 
   2866 test "zig fmt: function attributes" {
   2867     try testCanonical(
   2868         \\export fn foo() void {}
   2869         \\pub export fn foo() void {}
   2870         \\extern fn foo() void;
   2871         \\pub extern fn foo() void;
   2872         \\extern "c" fn foo() void;
   2873         \\pub extern "c" fn foo() void;
   2874         \\noinline fn foo() void {}
   2875         \\pub noinline fn foo() void {}
   2876         \\
   2877     );
   2878 }
   2879 
   2880 test "zig fmt: nested pointers with ** tokens" {
   2881     try testCanonical(
   2882         \\const x: *u32 = undefined;
   2883         \\const x: **u32 = undefined;
   2884         \\const x: ***u32 = undefined;
   2885         \\const x: ****u32 = undefined;
   2886         \\const x: *****u32 = undefined;
   2887         \\const x: ******u32 = undefined;
   2888         \\const x: *******u32 = undefined;
   2889         \\
   2890     );
   2891 }
   2892 
   2893 test "zig fmt: pointer attributes" {
   2894     try testCanonical(
   2895         \\extern fn f1(s: *align(*u8) u8) c_int;
   2896         \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
   2897         \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
   2898         \\extern fn f4(s: *align(1) const volatile u8) c_int;
   2899         \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
   2900         \\
   2901     );
   2902 }
   2903 
   2904 test "zig fmt: slice attributes" {
   2905     try testCanonical(
   2906         \\extern fn f1(s: []align(*u8) u8) c_int;
   2907         \\extern fn f2(s: []align(1) []const []volatile u8) c_int;
   2908         \\extern fn f3(s: []align(1) const [:0]align(1) volatile []const volatile u8) c_int;
   2909         \\extern fn f4(s: []align(1) const volatile u8) c_int;
   2910         \\extern fn f5(s: [:0]align(1) const volatile u8) c_int;
   2911         \\
   2912     );
   2913 }
   2914 
   2915 test "zig fmt: test declaration" {
   2916     try testCanonical(
   2917         \\test "test name" {
   2918         \\    const a = 1;
   2919         \\    var b = 1;
   2920         \\}
   2921         \\
   2922     );
   2923 }
   2924 
   2925 test "zig fmt: destructure" {
   2926     try testCanonical(
   2927         \\comptime {
   2928         \\    var w: u8, var x: u8 = .{ 1, 2 };
   2929         \\    w, var y: u8 = .{ 3, 4 };
   2930         \\    var z: u8, x = .{ 5, 6 };
   2931         \\    y, z = .{ 7, 8 };
   2932         \\}
   2933         \\
   2934         \\comptime {
   2935         \\    comptime var w, var x = .{ 1, 2 };
   2936         \\    comptime w, var y = .{ 3, 4 };
   2937         \\    comptime var z, x = .{ 5, 6 };
   2938         \\    comptime y, z = .{ 7, 8 };
   2939         \\}
   2940         \\
   2941     );
   2942 }
   2943 
   2944 test "zig fmt: infix operators" {
   2945     try testCanonical(
   2946         \\test {
   2947         \\    var i = undefined;
   2948         \\    i = 2;
   2949         \\    i *= 2;
   2950         \\    i |= 2;
   2951         \\    i ^= 2;
   2952         \\    i <<= 2;
   2953         \\    i >>= 2;
   2954         \\    i &= 2;
   2955         \\    i *= 2;
   2956         \\    i *%= 2;
   2957         \\    i -= 2;
   2958         \\    i -%= 2;
   2959         \\    i += 2;
   2960         \\    i +%= 2;
   2961         \\    i /= 2;
   2962         \\    i %= 2;
   2963         \\    _ = i == i;
   2964         \\    _ = i != i;
   2965         \\    _ = i != i;
   2966         \\    _ = i.i;
   2967         \\    _ = i || i;
   2968         \\    _ = i!i;
   2969         \\    _ = i ** i;
   2970         \\    _ = i ++ i;
   2971         \\    _ = i orelse i;
   2972         \\    _ = i % i;
   2973         \\    _ = i / i;
   2974         \\    _ = i *% i;
   2975         \\    _ = i * i;
   2976         \\    _ = i -% i;
   2977         \\    _ = i - i;
   2978         \\    _ = i +% i;
   2979         \\    _ = i + i;
   2980         \\    _ = i << i;
   2981         \\    _ = i >> i;
   2982         \\    _ = i & i;
   2983         \\    _ = i ^ i;
   2984         \\    _ = i | i;
   2985         \\    _ = i >= i;
   2986         \\    _ = i <= i;
   2987         \\    _ = i > i;
   2988         \\    _ = i < i;
   2989         \\    _ = i and i;
   2990         \\    _ = i or i;
   2991         \\}
   2992         \\
   2993     );
   2994 }
   2995 
   2996 test "zig fmt: precedence" {
   2997     try testCanonical(
   2998         \\test "precedence" {
   2999         \\    a!b();
   3000         \\    (a!b)();
   3001         \\    !a!b;
   3002         \\    !(a!b);
   3003         \\    !a{};
   3004         \\    !(a{});
   3005         \\    a + b{};
   3006         \\    (a + b){};
   3007         \\    a << b + c;
   3008         \\    (a << b) + c;
   3009         \\    a & b << c;
   3010         \\    (a & b) << c;
   3011         \\    a ^ b & c;
   3012         \\    (a ^ b) & c;
   3013         \\    a | b ^ c;
   3014         \\    (a | b) ^ c;
   3015         \\    a == b | c;
   3016         \\    (a == b) | c;
   3017         \\    a and b == c;
   3018         \\    (a and b) == c;
   3019         \\    a or b and c;
   3020         \\    (a or b) and c;
   3021         \\    (a or b) and c;
   3022         \\    a == b and c == d;
   3023         \\}
   3024         \\
   3025     );
   3026 }
   3027 
   3028 test "zig fmt: prefix operators" {
   3029     try testCanonical(
   3030         \\test "prefix operators" {
   3031         \\    try return --%~!&0;
   3032         \\}
   3033         \\
   3034     );
   3035 }
   3036 
   3037 test "zig fmt: call expression" {
   3038     try testCanonical(
   3039         \\test "test calls" {
   3040         \\    a();
   3041         \\    a(1);
   3042         \\    a(1, 2);
   3043         \\    a(1, 2) + a(1, 2);
   3044         \\}
   3045         \\
   3046     );
   3047 }
   3048 
   3049 test "zig fmt: anytype type" {
   3050     try testCanonical(
   3051         \\fn print(args: anytype) @This() {}
   3052         \\
   3053     );
   3054 }
   3055 
   3056 test "zig fmt: functions" {
   3057     try testCanonical(
   3058         \\extern fn puts(s: *const u8) c_int;
   3059         \\extern "c" fn puts(s: *const u8) c_int;
   3060         \\export fn puts(s: *const u8) c_int;
   3061         \\inline fn puts(s: *const u8) c_int;
   3062         \\noinline fn puts(s: *const u8) c_int;
   3063         \\pub extern fn puts(s: *const u8) c_int;
   3064         \\pub extern "c" fn puts(s: *const u8) c_int;
   3065         \\pub export fn puts(s: *const u8) c_int;
   3066         \\pub inline fn puts(s: *const u8) c_int;
   3067         \\pub noinline fn puts(s: *const u8) c_int;
   3068         \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
   3069         \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
   3070         \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
   3071         \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
   3072         \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
   3073         \\pub fn callInlineFn(func: fn () callconv(.@"inline") void) void {
   3074         \\    func();
   3075         \\}
   3076         \\
   3077     );
   3078 }
   3079 
   3080 test "zig fmt: multiline string" {
   3081     try testCanonical(
   3082         \\test "" {
   3083         \\    const s1 =
   3084         \\        \\one
   3085         \\        \\two)
   3086         \\        \\three
   3087         \\    ;
   3088         \\    const s3 = // hi
   3089         \\        \\one
   3090         \\        \\two)
   3091         \\        \\three
   3092         \\    ;
   3093         \\}
   3094         \\
   3095     );
   3096 }
   3097 
   3098 test "zig fmt: multiline string with CRLF line endings" {
   3099     try testTransform("" ++
   3100         "const s =\r\n" ++
   3101         "    \\\\one\r\n" ++
   3102         "    \\\\two)\r\n" ++
   3103         "    \\\\three\r\n" ++
   3104         ";\r\n",
   3105         \\const s =
   3106         \\    \\one
   3107         \\    \\two)
   3108         \\    \\three
   3109         \\;
   3110         \\
   3111     );
   3112 }
   3113 
   3114 test "zig fmt: values" {
   3115     try testCanonical(
   3116         \\test "values" {
   3117         \\    1;
   3118         \\    1.0;
   3119         \\    "string";
   3120         \\    'c';
   3121         \\    true;
   3122         \\    false;
   3123         \\    null;
   3124         \\    undefined;
   3125         \\    anyerror;
   3126         \\    this;
   3127         \\    unreachable;
   3128         \\}
   3129         \\
   3130     );
   3131 }
   3132 
   3133 test "zig fmt: indexing" {
   3134     try testCanonical(
   3135         \\test "test index" {
   3136         \\    a[0];
   3137         \\    a[0 + 5];
   3138         \\    a[0..];
   3139         \\    a[0..5];
   3140         \\    a[a[0]];
   3141         \\    a[a[0..]];
   3142         \\    a[a[0..5]];
   3143         \\    a[a[0]..];
   3144         \\    a[a[0..5]..];
   3145         \\    a[a[0]..a[0]];
   3146         \\    a[a[0..5]..a[0]];
   3147         \\    a[a[0..5]..a[0..5]];
   3148         \\}
   3149         \\
   3150     );
   3151 }
   3152 
   3153 test "zig fmt: struct declaration" {
   3154     try testCanonical(
   3155         \\const S = struct {
   3156         \\    const Self = @This();
   3157         \\    f1: u8,
   3158         \\    f3: u8,
   3159         \\
   3160         \\    f2: u8,
   3161         \\
   3162         \\    fn method(self: *Self) Self {
   3163         \\        return self.*;
   3164         \\    }
   3165         \\};
   3166         \\
   3167         \\const Ps = packed struct {
   3168         \\    a: u8,
   3169         \\    b: u8,
   3170         \\
   3171         \\    c: u8,
   3172         \\};
   3173         \\
   3174         \\const Ps = packed struct(u32) {
   3175         \\    a: u1,
   3176         \\    b: u2,
   3177         \\
   3178         \\    c: u29,
   3179         \\};
   3180         \\
   3181         \\const Es = extern struct {
   3182         \\    a: u8,
   3183         \\    b: u8,
   3184         \\
   3185         \\    c: u8,
   3186         \\};
   3187         \\
   3188     );
   3189 }
   3190 
   3191 test "zig fmt: enum declaration" {
   3192     try testCanonical(
   3193         \\const E = enum {
   3194         \\    Ok,
   3195         \\    SomethingElse = 0,
   3196         \\};
   3197         \\
   3198         \\const E2 = enum(u8) {
   3199         \\    Ok,
   3200         \\    SomethingElse = 255,
   3201         \\    SomethingThird,
   3202         \\};
   3203         \\
   3204         \\const Ee = extern enum {
   3205         \\    Ok,
   3206         \\    SomethingElse,
   3207         \\    SomethingThird,
   3208         \\};
   3209         \\
   3210         \\const Ep = packed enum {
   3211         \\    Ok,
   3212         \\    SomethingElse,
   3213         \\    SomethingThird,
   3214         \\};
   3215         \\
   3216     );
   3217 }
   3218 
   3219 test "zig fmt: union declaration" {
   3220     try testCanonical(
   3221         \\const U = union {
   3222         \\    Int: u8,
   3223         \\    Float: f32,
   3224         \\    None,
   3225         \\    Bool: bool,
   3226         \\};
   3227         \\
   3228         \\const Ue = union(enum) {
   3229         \\    Int: u8,
   3230         \\    Float: f32,
   3231         \\    None,
   3232         \\    Bool: bool,
   3233         \\};
   3234         \\
   3235         \\const E = enum {
   3236         \\    Int,
   3237         \\    Float,
   3238         \\    None,
   3239         \\    Bool,
   3240         \\};
   3241         \\
   3242         \\const Ue2 = union(E) {
   3243         \\    Int: u8,
   3244         \\    Float: f32,
   3245         \\    None,
   3246         \\    Bool: bool,
   3247         \\};
   3248         \\
   3249         \\const Eu = extern union {
   3250         \\    Int: u8,
   3251         \\    Float: f32,
   3252         \\    None,
   3253         \\    Bool: bool,
   3254         \\};
   3255         \\
   3256     );
   3257 }
   3258 
   3259 test "zig fmt: arrays" {
   3260     try testCanonical(
   3261         \\test "test array" {
   3262         \\    const a: [2]u8 = [2]u8{
   3263         \\        1,
   3264         \\        2,
   3265         \\    };
   3266         \\    const a: [2]u8 = []u8{
   3267         \\        1,
   3268         \\        2,
   3269         \\    };
   3270         \\    const a: [0]u8 = []u8{};
   3271         \\    const x: [4:0]u8 = undefined;
   3272         \\}
   3273         \\
   3274     );
   3275 }
   3276 
   3277 test "zig fmt: container initializers" {
   3278     try testCanonical(
   3279         \\const a0 = []u8{};
   3280         \\const a1 = []u8{1};
   3281         \\const a2 = []u8{
   3282         \\    1,
   3283         \\    2,
   3284         \\    3,
   3285         \\    4,
   3286         \\};
   3287         \\const s0 = S{};
   3288         \\const s1 = S{ .a = 1 };
   3289         \\const s2 = S{
   3290         \\    .a = 1,
   3291         \\    .b = 2,
   3292         \\};
   3293         \\
   3294     );
   3295 }
   3296 
   3297 test "zig fmt: catch" {
   3298     try testCanonical(
   3299         \\test "catch" {
   3300         \\    const a: anyerror!u8 = 0;
   3301         \\    _ = a catch return;
   3302         \\    _ = a catch
   3303         \\        return;
   3304         \\    _ = a catch |err| return;
   3305         \\    _ = a catch |err|
   3306         \\        return;
   3307         \\}
   3308         \\
   3309     );
   3310 }
   3311 
   3312 test "zig fmt: blocks" {
   3313     try testCanonical(
   3314         \\test "blocks" {
   3315         \\    {
   3316         \\        const a = 0;
   3317         \\        const b = 0;
   3318         \\    }
   3319         \\
   3320         \\    blk: {
   3321         \\        const a = 0;
   3322         \\        const b = 0;
   3323         \\    }
   3324         \\
   3325         \\    const r = blk: {
   3326         \\        const a = 0;
   3327         \\        const b = 0;
   3328         \\    };
   3329         \\}
   3330         \\
   3331     );
   3332 }
   3333 
   3334 test "zig fmt: switch" {
   3335     try testCanonical(
   3336         \\test "switch" {
   3337         \\    switch (0) {
   3338         \\        0 => {},
   3339         \\        1 => unreachable,
   3340         \\        2, 3 => {},
   3341         \\        4...7 => {},
   3342         \\        1 + 4 * 3 + 22 => {},
   3343         \\        else => {
   3344         \\            const a = 1;
   3345         \\            const b = a;
   3346         \\        },
   3347         \\    }
   3348         \\
   3349         \\    const res = switch (0) {
   3350         \\        0 => 0,
   3351         \\        1 => 2,
   3352         \\        1 => a = 4,
   3353         \\        else => 4,
   3354         \\    };
   3355         \\
   3356         \\    const Union = union(enum) {
   3357         \\        Int: i64,
   3358         \\        Float: f64,
   3359         \\    };
   3360         \\
   3361         \\    switch (u) {
   3362         \\        Union.Int => |int| {},
   3363         \\        Union.Float => |*float| unreachable,
   3364         \\        1 => |a, b| unreachable,
   3365         \\        2 => |*a, b| unreachable,
   3366         \\    }
   3367         \\}
   3368         \\
   3369     );
   3370 
   3371     try testTransform(
   3372         \\test {
   3373         \\    switch (x) {
   3374         \\        foo =>
   3375         \\            "bar",
   3376         \\    }
   3377         \\}
   3378         \\
   3379     ,
   3380         \\test {
   3381         \\    switch (x) {
   3382         \\        foo => "bar",
   3383         \\    }
   3384         \\}
   3385         \\
   3386     );
   3387 }
   3388 
   3389 test "zig fmt: switch multiline string" {
   3390     try testCanonical(
   3391         \\test "switch multiline string" {
   3392         \\    const x: u32 = 0;
   3393         \\    const str = switch (x) {
   3394         \\        1 => "one",
   3395         \\        2 =>
   3396         \\        \\ Comma after the multiline string
   3397         \\        \\ is needed
   3398         \\        ,
   3399         \\        3 => "three",
   3400         \\        else => "else",
   3401         \\    };
   3402         \\
   3403         \\    const Union = union(enum) {
   3404         \\        Int: i64,
   3405         \\        Float: f64,
   3406         \\    };
   3407         \\
   3408         \\    const str = switch (u) {
   3409         \\        Union.Int => |int|
   3410         \\        \\ Comma after the multiline string
   3411         \\        \\ is needed
   3412         \\        ,
   3413         \\        Union.Float => |*float| unreachable,
   3414         \\    };
   3415         \\}
   3416         \\
   3417     );
   3418 }
   3419 
   3420 test "zig fmt: while" {
   3421     try testCanonical(
   3422         \\test "while" {
   3423         \\    while (10 < 1) unreachable;
   3424         \\
   3425         \\    while (10 < 1) unreachable else unreachable;
   3426         \\
   3427         \\    while (10 < 1) {
   3428         \\        unreachable;
   3429         \\    }
   3430         \\
   3431         \\    while (10 < 1)
   3432         \\        unreachable;
   3433         \\
   3434         \\    var i: usize = 0;
   3435         \\    while (i < 10) : (i += 1) {
   3436         \\        continue;
   3437         \\    }
   3438         \\
   3439         \\    i = 0;
   3440         \\    while (i < 10) : (i += 1)
   3441         \\        continue;
   3442         \\
   3443         \\    i = 0;
   3444         \\    var j: usize = 0;
   3445         \\    while (i < 10) : ({
   3446         \\        i += 1;
   3447         \\        j += 1;
   3448         \\    }) continue;
   3449         \\
   3450         \\    while (i < 10) : ({
   3451         \\        i += 1;
   3452         \\        j += 1;
   3453         \\    }) {
   3454         \\        continue;
   3455         \\    }
   3456         \\
   3457         \\    var a: ?u8 = 2;
   3458         \\    while (a) |v| : (a = null) {
   3459         \\        continue;
   3460         \\    }
   3461         \\
   3462         \\    while (a) |v| : (a = null)
   3463         \\        unreachable;
   3464         \\
   3465         \\    label: while (10 < 0) {
   3466         \\        unreachable;
   3467         \\    }
   3468         \\
   3469         \\    const res = while (0 < 10) {
   3470         \\        break 7;
   3471         \\    } else {
   3472         \\        unreachable;
   3473         \\    };
   3474         \\
   3475         \\    const res = while (0 < 10)
   3476         \\        break 7
   3477         \\    else
   3478         \\        unreachable;
   3479         \\
   3480         \\    var a: anyerror!u8 = 0;
   3481         \\    while (a) |v| {
   3482         \\        a = error.Err;
   3483         \\    } else |err| {
   3484         \\        i = 1;
   3485         \\    }
   3486         \\
   3487         \\    comptime var k: usize = 0;
   3488         \\    inline while (i < 10) : (i += 1)
   3489         \\        j += 2;
   3490         \\}
   3491         \\
   3492     );
   3493 }
   3494 
   3495 test "zig fmt: for" {
   3496     try testCanonical(
   3497         \\test "for" {
   3498         \\    for (a) |v| {
   3499         \\        continue;
   3500         \\    }
   3501         \\
   3502         \\    for (a) |v| continue;
   3503         \\
   3504         \\    for (a) |v| continue else return;
   3505         \\
   3506         \\    for (a) |v| {
   3507         \\        continue;
   3508         \\    } else return;
   3509         \\
   3510         \\    for (a) |v| continue else {
   3511         \\        return;
   3512         \\    }
   3513         \\
   3514         \\    for (a) |v|
   3515         \\        continue
   3516         \\    else
   3517         \\        return;
   3518         \\
   3519         \\    for (a) |v|
   3520         \\        continue;
   3521         \\
   3522         \\    for (a) |*v|
   3523         \\        continue;
   3524         \\
   3525         \\    for (a, 0..) |v, i| {
   3526         \\        continue;
   3527         \\    }
   3528         \\
   3529         \\    for (a, 0..) |v, i|
   3530         \\        continue;
   3531         \\
   3532         \\    for (a) |b| switch (b) {
   3533         \\        c => {},
   3534         \\        d => {},
   3535         \\    };
   3536         \\
   3537         \\    const res = for (a, 0..) |v, i| {
   3538         \\        break v;
   3539         \\    } else {
   3540         \\        unreachable;
   3541         \\    };
   3542         \\
   3543         \\    var num: usize = 0;
   3544         \\    inline for (a, 0..1) |v, i| {
   3545         \\        num += v;
   3546         \\        num += i;
   3547         \\    }
   3548         \\
   3549         \\    for (a, b) |
   3550         \\        long_name,
   3551         \\        another_long_name,
   3552         \\    | {
   3553         \\        continue;
   3554         \\    }
   3555         \\}
   3556         \\
   3557     );
   3558 
   3559     try testTransform(
   3560         \\test "fix for" {
   3561         \\    for (a) |x|
   3562         \\        f(x) else continue;
   3563         \\}
   3564         \\
   3565     ,
   3566         \\test "fix for" {
   3567         \\    for (a) |x|
   3568         \\        f(x)
   3569         \\    else
   3570         \\        continue;
   3571         \\}
   3572         \\
   3573     );
   3574 
   3575     try testTransform(
   3576         \\test "fix for" {
   3577         \\    for (a, b, c,) |long, another, third,| {}
   3578         \\}
   3579         \\
   3580     ,
   3581         \\test "fix for" {
   3582         \\    for (
   3583         \\        a,
   3584         \\        b,
   3585         \\        c,
   3586         \\    ) |
   3587         \\        long,
   3588         \\        another,
   3589         \\        third,
   3590         \\    | {}
   3591         \\}
   3592         \\
   3593     );
   3594 }
   3595 
   3596 test "zig fmt: for if" {
   3597     try testCanonical(
   3598         \\test {
   3599         \\    for (a) |x| if (x) f(x);
   3600         \\
   3601         \\    for (a) |x| if (x)
   3602         \\        f(x);
   3603         \\
   3604         \\    for (a) |x| if (x) {
   3605         \\        f(x);
   3606         \\    };
   3607         \\
   3608         \\    for (a) |x|
   3609         \\        if (x)
   3610         \\            f(x);
   3611         \\
   3612         \\    for (a) |x|
   3613         \\        if (x) {
   3614         \\            f(x);
   3615         \\        };
   3616         \\}
   3617         \\
   3618     );
   3619 }
   3620 
   3621 test "zig fmt: if for" {
   3622     try testCanonical(
   3623         \\test {
   3624         \\    if (a) for (x) |x| f(x);
   3625         \\
   3626         \\    if (a) for (x) |x|
   3627         \\        f(x);
   3628         \\
   3629         \\    if (a) for (x) |x| {
   3630         \\        f(x);
   3631         \\    };
   3632         \\
   3633         \\    if (a)
   3634         \\        for (x) |x|
   3635         \\            f(x);
   3636         \\
   3637         \\    if (a)
   3638         \\        for (x) |x| {
   3639         \\            f(x);
   3640         \\        };
   3641         \\}
   3642         \\
   3643     );
   3644 }
   3645 
   3646 test "zig fmt: while if" {
   3647     try testCanonical(
   3648         \\test {
   3649         \\    while (a) if (x) f(x);
   3650         \\
   3651         \\    while (a) if (x)
   3652         \\        f(x);
   3653         \\
   3654         \\    while (a) if (x) {
   3655         \\        f(x);
   3656         \\    };
   3657         \\
   3658         \\    while (a)
   3659         \\        if (x)
   3660         \\            f(x);
   3661         \\
   3662         \\    while (a)
   3663         \\        if (x) {
   3664         \\            f(x);
   3665         \\        };
   3666         \\}
   3667         \\
   3668     );
   3669 }
   3670 
   3671 test "zig fmt: if while" {
   3672     try testCanonical(
   3673         \\test {
   3674         \\    if (a) while (x) : (cont) f(x);
   3675         \\
   3676         \\    if (a) while (x) : (cont)
   3677         \\        f(x);
   3678         \\
   3679         \\    if (a) while (x) : (cont) {
   3680         \\        f(x);
   3681         \\    };
   3682         \\
   3683         \\    if (a)
   3684         \\        while (x) : (cont)
   3685         \\            f(x);
   3686         \\
   3687         \\    if (a)
   3688         \\        while (x) : (cont) {
   3689         \\            f(x);
   3690         \\        };
   3691         \\}
   3692         \\
   3693     );
   3694 }
   3695 
   3696 test "zig fmt: while for" {
   3697     try testCanonical(
   3698         \\test {
   3699         \\    while (a) for (x) |x| f(x);
   3700         \\
   3701         \\    while (a) for (x) |x|
   3702         \\        f(x);
   3703         \\
   3704         \\    while (a) for (x) |x| {
   3705         \\        f(x);
   3706         \\    };
   3707         \\
   3708         \\    while (a)
   3709         \\        for (x) |x|
   3710         \\            f(x);
   3711         \\
   3712         \\    while (a)
   3713         \\        for (x) |x| {
   3714         \\            f(x);
   3715         \\        };
   3716         \\}
   3717         \\
   3718     );
   3719 }
   3720 
   3721 test "zig fmt: for while" {
   3722     try testCanonical(
   3723         \\test {
   3724         \\    for (a) |a| while (x) |x| f(x);
   3725         \\
   3726         \\    for (a) |a| while (x) |x|
   3727         \\        f(x);
   3728         \\
   3729         \\    for (a) |a| while (x) |x| {
   3730         \\        f(x);
   3731         \\    };
   3732         \\
   3733         \\    for (a) |a|
   3734         \\        while (x) |x|
   3735         \\            f(x);
   3736         \\
   3737         \\    for (a) |a|
   3738         \\        while (x) |x| {
   3739         \\            f(x);
   3740         \\        };
   3741         \\}
   3742         \\
   3743     );
   3744 }
   3745 
   3746 test "zig fmt: if" {
   3747     try testCanonical(
   3748         \\test "if" {
   3749         \\    if (10 < 0) {
   3750         \\        unreachable;
   3751         \\    }
   3752         \\
   3753         \\    if (10 < 0) unreachable;
   3754         \\
   3755         \\    if (10 < 0) {
   3756         \\        unreachable;
   3757         \\    } else {
   3758         \\        const a = 20;
   3759         \\    }
   3760         \\
   3761         \\    if (10 < 0) {
   3762         \\        unreachable;
   3763         \\    } else if (5 < 0) {
   3764         \\        unreachable;
   3765         \\    } else {
   3766         \\        const a = 20;
   3767         \\    }
   3768         \\
   3769         \\    const is_world_broken = if (10 < 0) true else false;
   3770         \\    const some_number = 1 + if (10 < 0) 2 else 3;
   3771         \\
   3772         \\    const a: ?u8 = 10;
   3773         \\    const b: ?u8 = null;
   3774         \\    if (a) |v| {
   3775         \\        const some = v;
   3776         \\    } else if (b) |*v| {
   3777         \\        unreachable;
   3778         \\    } else {
   3779         \\        const some = 10;
   3780         \\    }
   3781         \\
   3782         \\    const non_null_a = if (a) |v| v else 0;
   3783         \\
   3784         \\    const a_err: anyerror!u8 = 0;
   3785         \\    if (a_err) |v| {
   3786         \\        const p = v;
   3787         \\    } else |err| {
   3788         \\        unreachable;
   3789         \\    }
   3790         \\}
   3791         \\
   3792     );
   3793 }
   3794 
   3795 test "zig fmt: fix single statement if/for/while line breaks" {
   3796     try testTransform(
   3797         \\test {
   3798         \\    if (cond) a
   3799         \\    else b;
   3800         \\
   3801         \\    if (cond)
   3802         \\        a
   3803         \\    else b;
   3804         \\
   3805         \\    for (xs) |x| foo()
   3806         \\    else bar();
   3807         \\
   3808         \\    for (xs) |x|
   3809         \\        foo()
   3810         \\    else bar();
   3811         \\
   3812         \\    while (a) : (b) foo()
   3813         \\    else bar();
   3814         \\
   3815         \\    while (a) : (b)
   3816         \\        foo()
   3817         \\    else bar();
   3818         \\}
   3819         \\
   3820     ,
   3821         \\test {
   3822         \\    if (cond) a else b;
   3823         \\
   3824         \\    if (cond)
   3825         \\        a
   3826         \\    else
   3827         \\        b;
   3828         \\
   3829         \\    for (xs) |x| foo() else bar();
   3830         \\
   3831         \\    for (xs) |x|
   3832         \\        foo()
   3833         \\    else
   3834         \\        bar();
   3835         \\
   3836         \\    while (a) : (b) foo() else bar();
   3837         \\
   3838         \\    while (a) : (b)
   3839         \\        foo()
   3840         \\    else
   3841         \\        bar();
   3842         \\}
   3843         \\
   3844     );
   3845 }
   3846 
   3847 test "zig fmt: anon struct/array literal in if" {
   3848     try testCanonical(
   3849         \\test {
   3850         \\    const a = if (cond) .{
   3851         \\        1, 2,
   3852         \\        3, 4,
   3853         \\    } else .{
   3854         \\        1,
   3855         \\        2,
   3856         \\        3,
   3857         \\    };
   3858         \\
   3859         \\    const rl_and_tag: struct { rl: ResultLoc, tag: zir.Inst.Tag } = if (any_payload_is_ref) .{
   3860         \\        .rl = .ref,
   3861         \\        .tag = .switchbr_ref,
   3862         \\    } else .{
   3863         \\        .rl = .none,
   3864         \\        .tag = .switchbr,
   3865         \\    };
   3866         \\}
   3867         \\
   3868     );
   3869 }
   3870 
   3871 test "zig fmt: defer" {
   3872     try testCanonical(
   3873         \\test "defer" {
   3874         \\    var i: usize = 0;
   3875         \\    defer i = 1;
   3876         \\    defer {
   3877         \\        i += 2;
   3878         \\        i *= i;
   3879         \\    }
   3880         \\
   3881         \\    errdefer i += 3;
   3882         \\    errdefer {
   3883         \\        i += 2;
   3884         \\        i /= i;
   3885         \\    }
   3886         \\}
   3887         \\
   3888     );
   3889 }
   3890 
   3891 test "zig fmt: comptime" {
   3892     try testCanonical(
   3893         \\fn a() u8 {
   3894         \\    return 5;
   3895         \\}
   3896         \\
   3897         \\fn b(comptime i: u8) u8 {
   3898         \\    return i;
   3899         \\}
   3900         \\
   3901         \\const av = comptime a();
   3902         \\const av2 = comptime blk: {
   3903         \\    var res = a();
   3904         \\    res *= b(2);
   3905         \\    break :blk res;
   3906         \\};
   3907         \\
   3908         \\comptime {
   3909         \\    _ = a();
   3910         \\}
   3911         \\
   3912         \\test "comptime" {
   3913         \\    const av3 = comptime a();
   3914         \\    const av4 = comptime blk: {
   3915         \\        var res = a();
   3916         \\        res *= a();
   3917         \\        break :blk res;
   3918         \\    };
   3919         \\
   3920         \\    comptime var i = 0;
   3921         \\    comptime {
   3922         \\        i = a();
   3923         \\        i += b(i);
   3924         \\    }
   3925         \\}
   3926         \\
   3927     );
   3928 }
   3929 
   3930 test "zig fmt: fn type" {
   3931     try testCanonical(
   3932         \\fn a(i: u8) u8 {
   3933         \\    return i + 1;
   3934         \\}
   3935         \\
   3936         \\const a: fn (u8) u8 = undefined;
   3937         \\const b: fn (u8) callconv(.naked) u8 = undefined;
   3938         \\const ap: fn (u8) u8 = a;
   3939         \\
   3940     );
   3941 }
   3942 
   3943 test "zig fmt: inline asm" {
   3944     try testTransform(
   3945         \\pub fn syscall1(number: usize, arg1: usize) usize {
   3946         \\    return asm volatile ("syscall"
   3947         \\        : [ret] "={rax}" (-> usize),
   3948         \\        : [number] "{rax}" (number),
   3949         \\          [arg1] "{rdi}" (arg1),
   3950         \\        : "rcx", "r11"
   3951         \\    );
   3952         \\}
   3953         \\
   3954     ,
   3955         \\pub fn syscall1(number: usize, arg1: usize) usize {
   3956         \\    return asm volatile ("syscall"
   3957         \\        : [ret] "={rax}" (-> usize),
   3958         \\        : [number] "{rax}" (number),
   3959         \\          [arg1] "{rdi}" (arg1),
   3960         \\        : .{ .rcx = true, .r11 = true }
   3961         \\    );
   3962         \\}
   3963         \\
   3964     );
   3965 }
   3966 
   3967 test "zig fmt: nosuspend" {
   3968     try testCanonical(
   3969         \\const a = nosuspend foo();
   3970         \\
   3971     );
   3972 }
   3973 
   3974 test "zig fmt: Block after if" {
   3975     try testCanonical(
   3976         \\test {
   3977         \\    if (true) {
   3978         \\        const a = 0;
   3979         \\    }
   3980         \\
   3981         \\    {
   3982         \\        const a = 0;
   3983         \\    }
   3984         \\}
   3985         \\
   3986     );
   3987 }
   3988 
   3989 test "zig fmt: string identifier" {
   3990     try testCanonical(
   3991         \\const @"a b" = @"c d".@"e f";
   3992         \\fn @"g h"() void {}
   3993         \\
   3994     );
   3995 }
   3996 
   3997 test "zig fmt: error return" {
   3998     try testCanonical(
   3999         \\fn err() anyerror {
   4000         \\    call();
   4001         \\    return error.InvalidArgs;
   4002         \\}
   4003         \\
   4004     );
   4005 }
   4006 
   4007 test "zig fmt: comptime block in container" {
   4008     try testCanonical(
   4009         \\pub fn container() type {
   4010         \\    return struct {
   4011         \\        comptime {
   4012         \\            if (false) {
   4013         \\                unreachable;
   4014         \\            }
   4015         \\        }
   4016         \\    };
   4017         \\}
   4018         \\
   4019     );
   4020 }
   4021 
   4022 test "zig fmt: inline asm parameter alignment" {
   4023     try testCanonical(
   4024         \\pub fn main() void {
   4025         \\    asm volatile (
   4026         \\        \\ foo
   4027         \\        \\ bar
   4028         \\    );
   4029         \\    asm volatile (
   4030         \\        \\ foo
   4031         \\        \\ bar
   4032         \\        : [_] "" (-> usize),
   4033         \\          [_] "" (-> usize),
   4034         \\    );
   4035         \\    asm volatile (
   4036         \\        \\ foo
   4037         \\        \\ bar
   4038         \\        :
   4039         \\        : [_] "" (0),
   4040         \\          [_] "" (0),
   4041         \\    );
   4042         \\    asm volatile (
   4043         \\        \\ foo
   4044         \\        \\ bar
   4045         \\        ::: .{ .a = true, .b = true });
   4046         \\    asm volatile (
   4047         \\        \\ foo
   4048         \\        \\ bar
   4049         \\        : [_] "" (-> usize),
   4050         \\          [_] "" (-> usize),
   4051         \\        : [_] "" (0),
   4052         \\          [_] "" (0),
   4053         \\        : .{});
   4054         \\}
   4055         \\
   4056     );
   4057 }
   4058 
   4059 test "zig fmt: multiline string in array" {
   4060     try testCanonical(
   4061         \\const Foo = [][]const u8{
   4062         \\    \\aaa
   4063         \\    ,
   4064         \\    \\bbb
   4065         \\};
   4066         \\
   4067         \\fn bar() void {
   4068         \\    const Foo = [][]const u8{
   4069         \\        \\aaa
   4070         \\        ,
   4071         \\        \\bbb
   4072         \\    };
   4073         \\    const Bar = [][]const u8{ // comment here
   4074         \\        \\aaa
   4075         \\        \\
   4076         \\        , // and another comment can go here
   4077         \\        \\bbb
   4078         \\    };
   4079         \\}
   4080         \\
   4081     );
   4082 }
   4083 
   4084 test "zig fmt: if type expr" {
   4085     try testCanonical(
   4086         \\const mycond = true;
   4087         \\pub fn foo() if (mycond) i32 else void {
   4088         \\    if (mycond) {
   4089         \\        return 42;
   4090         \\    }
   4091         \\}
   4092         \\
   4093     );
   4094 }
   4095 test "zig fmt: file ends with struct field" {
   4096     try testCanonical(
   4097         \\a: bool
   4098         \\
   4099     );
   4100 }
   4101 
   4102 test "zig fmt: comment after empty comment" {
   4103     try testCanonical(
   4104         \\const x = true; //
   4105         \\//
   4106         \\//
   4107         \\//a
   4108         \\
   4109     );
   4110 }
   4111 
   4112 test "zig fmt: line comment in array" {
   4113     try testTransform(
   4114         \\test "a" {
   4115         \\    var arr = [_]u32{
   4116         \\        0
   4117         \\        // 1,
   4118         \\        // 2,
   4119         \\    };
   4120         \\}
   4121         \\
   4122     ,
   4123         \\test "a" {
   4124         \\    var arr = [_]u32{
   4125         \\        0,
   4126         \\        // 1,
   4127         \\        // 2,
   4128         \\    };
   4129         \\}
   4130         \\
   4131     );
   4132     try testCanonical(
   4133         \\test "a" {
   4134         \\    var arr = [_]u32{
   4135         \\        0,
   4136         \\        // 1,
   4137         \\        // 2,
   4138         \\    };
   4139         \\}
   4140         \\
   4141     );
   4142 }
   4143 
   4144 test "zig fmt: comment after params" {
   4145     try testTransform(
   4146         \\fn a(
   4147         \\    b: u32
   4148         \\    // c: u32,
   4149         \\    // d: u32,
   4150         \\) void {}
   4151         \\
   4152     ,
   4153         \\fn a(
   4154         \\    b: u32,
   4155         \\    // c: u32,
   4156         \\    // d: u32,
   4157         \\) void {}
   4158         \\
   4159     );
   4160     try testCanonical(
   4161         \\fn a(
   4162         \\    b: u32,
   4163         \\    // c: u32,
   4164         \\    // d: u32,
   4165         \\) void {}
   4166         \\
   4167     );
   4168 }
   4169 
   4170 test "zig fmt: comment in array initializer/access" {
   4171     try testCanonical(
   4172         \\test "a" {
   4173         \\    var a = x{ //aa
   4174         \\        //bb
   4175         \\    };
   4176         \\    var a = []x{ //aa
   4177         \\        //bb
   4178         \\    };
   4179         \\    var b = [ //aa
   4180         \\        _
   4181         \\    ]x{ //aa
   4182         \\        //bb
   4183         \\        9,
   4184         \\    };
   4185         \\    var c = b[ //aa
   4186         \\        0
   4187         \\    ];
   4188         \\    var d = [
   4189         \\        _
   4190         \\        //aa
   4191         \\        :
   4192         \\        0
   4193         \\    ]x{ //aa
   4194         \\        //bb
   4195         \\        9,
   4196         \\    };
   4197         \\    var e = d[
   4198         \\        0
   4199         \\        //aa
   4200         \\    ];
   4201         \\}
   4202         \\
   4203     );
   4204 }
   4205 
   4206 test "zig fmt: comments at several places in struct init" {
   4207     try testTransform(
   4208         \\var bar = Bar{
   4209         \\    .x = 10, // test
   4210         \\    .y = "test"
   4211         \\    // test
   4212         \\};
   4213         \\
   4214     ,
   4215         \\var bar = Bar{
   4216         \\    .x = 10, // test
   4217         \\    .y = "test",
   4218         \\    // test
   4219         \\};
   4220         \\
   4221     );
   4222 
   4223     try testCanonical(
   4224         \\var bar = Bar{ // test
   4225         \\    .x = 10, // test
   4226         \\    .y = "test",
   4227         \\    // test
   4228         \\};
   4229         \\
   4230     );
   4231 }
   4232 
   4233 test "zig fmt: container doc comments" {
   4234     try testCanonical(
   4235         \\//! tld 1
   4236         \\//! tld 2
   4237         \\//! tld 3
   4238         \\
   4239         \\// comment
   4240         \\
   4241         \\/// A doc
   4242         \\const A = struct {
   4243         \\    //! A tld 1
   4244         \\    //! A tld 2
   4245         \\    //! A tld 3
   4246         \\};
   4247         \\
   4248         \\/// B doc
   4249         \\const B = struct {
   4250         \\    //! B tld 1
   4251         \\    //! B tld 2
   4252         \\    //! B tld 3
   4253         \\
   4254         \\    /// B doc
   4255         \\    b: u32,
   4256         \\};
   4257         \\
   4258         \\/// C doc
   4259         \\const C = union(enum) { // comment
   4260         \\    //! C tld 1
   4261         \\    //! C tld 2
   4262         \\    //! C tld 3
   4263         \\};
   4264         \\
   4265         \\/// D doc
   4266         \\const D = union(Foo) {
   4267         \\    //! D tld 1
   4268         \\    //! D tld 2
   4269         \\    //! D tld 3
   4270         \\
   4271         \\    /// D doc
   4272         \\    b: u32,
   4273         \\};
   4274         \\
   4275     );
   4276     try testCanonical(
   4277         \\//! Top-level documentation.
   4278         \\
   4279         \\/// This is A
   4280         \\pub const A = usize;
   4281         \\
   4282     );
   4283     try testCanonical(
   4284         \\//! Nothing here
   4285         \\
   4286     );
   4287 }
   4288 
   4289 test "zig fmt: remove newlines surrounding doc comment" {
   4290     try testTransform(
   4291         \\
   4292         \\
   4293         \\
   4294         \\/// doc comment
   4295         \\
   4296         \\fn foo() void {}
   4297         \\
   4298     ,
   4299         \\/// doc comment
   4300         \\fn foo() void {}
   4301         \\
   4302     );
   4303 }
   4304 
   4305 test "zig fmt: remove newlines surrounding doc comment between members" {
   4306     try testTransform(
   4307         \\f1: i32,
   4308         \\
   4309         \\
   4310         \\/// doc comment
   4311         \\
   4312         \\f2: i32,
   4313         \\
   4314     ,
   4315         \\f1: i32,
   4316         \\
   4317         \\/// doc comment
   4318         \\f2: i32,
   4319         \\
   4320     );
   4321 }
   4322 
   4323 test "zig fmt: remove newlines surrounding doc comment between members within container decl (1)" {
   4324     try testTransform(
   4325         \\const Foo = struct {
   4326         \\    fn foo() void {}
   4327         \\
   4328         \\
   4329         \\    /// doc comment
   4330         \\
   4331         \\
   4332         \\    fn bar() void {}
   4333         \\};
   4334         \\
   4335     ,
   4336         \\const Foo = struct {
   4337         \\    fn foo() void {}
   4338         \\
   4339         \\    /// doc comment
   4340         \\    fn bar() void {}
   4341         \\};
   4342         \\
   4343     );
   4344 }
   4345 
   4346 test "zig fmt: remove newlines surrounding doc comment between members within container decl (2)" {
   4347     try testTransform(
   4348         \\const Foo = struct {
   4349         \\    fn foo() void {}
   4350         \\    /// doc comment 1
   4351         \\
   4352         \\    /// doc comment 2
   4353         \\
   4354         \\    fn bar() void {}
   4355         \\};
   4356         \\
   4357     ,
   4358         \\const Foo = struct {
   4359         \\    fn foo() void {}
   4360         \\    /// doc comment 1
   4361         \\    /// doc comment 2
   4362         \\    fn bar() void {}
   4363         \\};
   4364         \\
   4365     );
   4366 }
   4367 
   4368 test "zig fmt: remove newlines surrounding doc comment within container decl" {
   4369     try testTransform(
   4370         \\const Foo = struct {
   4371         \\
   4372         \\
   4373         \\    /// doc comment
   4374         \\
   4375         \\    fn foo() void {}
   4376         \\};
   4377         \\
   4378     ,
   4379         \\const Foo = struct {
   4380         \\    /// doc comment
   4381         \\    fn foo() void {}
   4382         \\};
   4383         \\
   4384     );
   4385 }
   4386 
   4387 test "zig fmt: comptime before comptime field" {
   4388     try testError(
   4389         \\const Foo = struct {
   4390         \\    a: i32,
   4391         \\    comptime comptime b: i32 = 1234,
   4392         \\};
   4393         \\
   4394     , &[_]Error{
   4395         .expected_comma_after_field,
   4396     });
   4397 }
   4398 
   4399 test "zig fmt: invalid doc comments on comptime and test blocks" {
   4400     try testError(
   4401         \\/// This is a doc comment for a comptime block.
   4402         \\comptime {}
   4403         \\/// This is a doc comment for a test
   4404         \\test "This is my test" {}
   4405     , &[_]Error{
   4406         .comptime_doc_comment,
   4407         .test_doc_comment,
   4408     });
   4409 }
   4410 
   4411 test "zig fmt: comments with CRLF line endings" {
   4412     try testTransform("" ++
   4413         "//! Top-level doc comment\r\n" ++
   4414         "//! Continuing to another line\r\n" ++
   4415         "\r\n" ++
   4416         "/// Regular doc comment\r\n" ++
   4417         "const S = struct {\r\n" ++
   4418         "    // Regular comment\r\n" ++
   4419         "    // More content\r\n" ++
   4420         "};\r\n",
   4421         \\//! Top-level doc comment
   4422         \\//! Continuing to another line
   4423         \\
   4424         \\/// Regular doc comment
   4425         \\const S = struct {
   4426         \\    // Regular comment
   4427         \\    // More content
   4428         \\};
   4429         \\
   4430     );
   4431 }
   4432 
   4433 test "zig fmt: else comptime expr" {
   4434     try testCanonical(
   4435         \\comptime {
   4436         \\    if (true) {} else comptime foo();
   4437         \\}
   4438         \\comptime {
   4439         \\    while (true) {} else comptime foo();
   4440         \\}
   4441         \\comptime {
   4442         \\    for ("") |_| {} else comptime foo();
   4443         \\}
   4444         \\
   4445     );
   4446 }
   4447 
   4448 test "zig fmt: invalid else branch statement" {
   4449     try testError(
   4450         \\comptime {
   4451         \\    if (true) {} else var a = 0;
   4452         \\    if (true) {} else defer {}
   4453         \\}
   4454         \\comptime {
   4455         \\    while (true) {} else var a = 0;
   4456         \\    while (true) {} else defer {}
   4457         \\}
   4458         \\comptime {
   4459         \\    for ("") |_| {} else var a = 0;
   4460         \\    for ("") |_| {} else defer {}
   4461         \\}
   4462     , &[_]Error{
   4463         .expected_expr_or_assignment,
   4464         .expected_expr_or_assignment,
   4465         .expected_expr_or_assignment,
   4466         .expected_expr_or_assignment,
   4467         .expected_expr_or_assignment,
   4468         .expected_expr_or_assignment,
   4469     });
   4470 }
   4471 
   4472 test "zig fmt: anytype struct field" {
   4473     try testError(
   4474         \\pub const Pointer = struct {
   4475         \\    sentinel: anytype,
   4476         \\};
   4477         \\
   4478     , &[_]Error{
   4479         .expected_type_expr,
   4480     });
   4481 }
   4482 
   4483 test "zig fmt: extern without container keyword returns error" {
   4484     try testError(
   4485         \\const container = extern {};
   4486         \\
   4487     , &[_]Error{
   4488         .expected_container,
   4489     });
   4490 }
   4491 
   4492 test "zig fmt: same line doc comment returns error" {
   4493     try testError(
   4494         \\const Foo = struct{
   4495         \\    bar: u32, /// comment
   4496         \\    foo: u32, /// comment
   4497         \\    /// comment
   4498         \\};
   4499         \\
   4500         \\const a = 42; /// comment
   4501         \\
   4502         \\extern fn foo() void; /// comment
   4503         \\
   4504         \\/// comment
   4505         \\
   4506     , &[_]Error{
   4507         .same_line_doc_comment,
   4508         .same_line_doc_comment,
   4509         .unattached_doc_comment,
   4510         .same_line_doc_comment,
   4511         .same_line_doc_comment,
   4512         .unattached_doc_comment,
   4513     });
   4514 }
   4515 
   4516 test "zig fmt: integer literals with underscore separators" {
   4517     try testTransform(
   4518         \\const
   4519         \\ x     =
   4520         \\ 1_234_567
   4521         \\ + (0b0_1-0o7_0+0xff_FF ) +  1_0;
   4522     ,
   4523         \\const x =
   4524         \\    1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 1_0;
   4525         \\
   4526     );
   4527 }
   4528 
   4529 test "zig fmt: hex literals with underscore separators" {
   4530     try testTransform(
   4531         \\pub fn orMask(a: [ 1_000 ]u64, b: [  1_000]  u64) [1_000]u64 {
   4532         \\    var c: [1_000]u64 =  [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
   4533         \\    for (c [ 1_0 .. ], 0..) |_, i| {
   4534         \\        c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
   4535         \\    }
   4536         \\    return c;
   4537         \\}
   4538         \\
   4539         \\
   4540     ,
   4541         \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
   4542         \\    var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
   4543         \\    for (c[1_0..], 0..) |_, i| {
   4544         \\        c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
   4545         \\    }
   4546         \\    return c;
   4547         \\}
   4548         \\
   4549     );
   4550 }
   4551 
   4552 test "zig fmt: decimal float literals with underscore separators" {
   4553     try testTransform(
   4554         \\pub fn main() void {
   4555         \\    const a:f64=(10.0e-0+(10.0e+0))+10_00.00_00e-2+20_00.00_10e+4;
   4556         \\    const b:f64=1_0.0--10_10.0+1_0_0.0_0+1e2;
   4557         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4558         \\}
   4559     ,
   4560         \\pub fn main() void {
   4561         \\    const a: f64 = (10.0e-0 + (10.0e+0)) + 10_00.00_00e-2 + 20_00.00_10e+4;
   4562         \\    const b: f64 = 1_0.0 - -10_10.0 + 1_0_0.0_0 + 1e2;
   4563         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4564         \\}
   4565         \\
   4566     );
   4567 }
   4568 
   4569 test "zig fmt: hexadecimal float literals with underscore separators" {
   4570     try testTransform(
   4571         \\pub fn main() void {
   4572         \\    const a: f64 = (0x10.0p-0+(0x10.0p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
   4573         \\    const b: f64 = 0x0010.0--0x00_10.0+0x10.00+0x1p4;
   4574         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4575         \\}
   4576     ,
   4577         \\pub fn main() void {
   4578         \\    const a: f64 = (0x10.0p-0 + (0x10.0p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
   4579         \\    const b: f64 = 0x0010.0 - -0x00_10.0 + 0x10.00 + 0x1p4;
   4580         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4581         \\}
   4582         \\
   4583     );
   4584 }
   4585 
   4586 test "zig fmt: C var args" {
   4587     try testCanonical(
   4588         \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
   4589         \\
   4590     );
   4591 }
   4592 
   4593 test "zig fmt: Only indent multiline string literals in function calls" {
   4594     try testCanonical(
   4595         \\test "zig fmt:" {
   4596         \\    try testTransform(
   4597         \\        \\const X = struct {
   4598         \\        \\    foo: i32, bar: i8 };
   4599         \\    ,
   4600         \\        \\const X = struct {
   4601         \\        \\    foo: i32, bar: i8
   4602         \\        \\};
   4603         \\        \\
   4604         \\    );
   4605         \\}
   4606         \\
   4607     );
   4608 }
   4609 
   4610 test "zig fmt: Don't add extra newline after if" {
   4611     try testCanonical(
   4612         \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
   4613         \\    if (cwd().symLink(existing_path, new_path, .{})) {
   4614         \\        return;
   4615         \\    }
   4616         \\}
   4617         \\
   4618     );
   4619 }
   4620 
   4621 test "zig fmt: comments in ternary ifs" {
   4622     try testCanonical(
   4623         \\const x = if (true) {
   4624         \\    1;
   4625         \\} else if (false)
   4626         \\    // Comment
   4627         \\    0;
   4628         \\const y = if (true)
   4629         \\    // Comment
   4630         \\    1
   4631         \\else
   4632         \\    // Comment
   4633         \\    0;
   4634         \\
   4635         \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
   4636         \\
   4637     );
   4638 }
   4639 
   4640 test "zig fmt: while statement in blockless if" {
   4641     try testCanonical(
   4642         \\pub fn main() void {
   4643         \\    const zoom_node = if (focused_node == layout_first)
   4644         \\        while (it.next()) |node| {
   4645         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4646         \\        } else null
   4647         \\    else
   4648         \\        focused_node;
   4649         \\}
   4650         \\
   4651     );
   4652 }
   4653 
   4654 test "zig fmt: test comments in field access chain" {
   4655     try testCanonical(
   4656         \\pub const str = struct {
   4657         \\    pub const Thing = more.more //
   4658         \\        .more() //
   4659         \\        .more().more() //
   4660         \\        .more() //
   4661         \\        // .more() //
   4662         \\        .more() //
   4663         \\        .more();
   4664         \\    data: Data,
   4665         \\};
   4666         \\
   4667         \\pub const str = struct {
   4668         \\    pub const Thing = more.more //
   4669         \\        .more() //
   4670         \\        // .more() //
   4671         \\        // .more() //
   4672         \\        // .more() //
   4673         \\        .more() //
   4674         \\        .more();
   4675         \\    data: Data,
   4676         \\};
   4677         \\
   4678         \\pub const str = struct {
   4679         \\    pub const Thing = more //
   4680         \\        .more //
   4681         \\        .more() //
   4682         \\        .more();
   4683         \\    data: Data,
   4684         \\};
   4685         \\
   4686     );
   4687 }
   4688 
   4689 test "zig fmt: allow line break before field access" {
   4690     try testCanonical(
   4691         \\test {
   4692         \\    const w = foo.bar().zippy(zag).iguessthisisok();
   4693         \\
   4694         \\    const x = foo
   4695         \\        .bar()
   4696         \\        . // comment
   4697         \\        // comment
   4698         \\        swooop().zippy(zag)
   4699         \\        .iguessthisisok();
   4700         \\
   4701         \\    const y = view.output.root.server.input_manager.default_seat.wlr_seat.name;
   4702         \\
   4703         \\    const z = view.output.root.server
   4704         \\        .input_manager //
   4705         \\        .default_seat
   4706         \\        . // comment
   4707         \\        // another comment
   4708         \\        wlr_seat.name;
   4709         \\}
   4710         \\
   4711     );
   4712     try testTransform(
   4713         \\test {
   4714         \\    const x = foo.
   4715         \\        bar()
   4716         \\        .zippy(zag).iguessthisisok();
   4717         \\
   4718         \\    const z = view.output.root.server.
   4719         \\        input_manager.
   4720         \\        default_seat.wlr_seat.name;
   4721         \\}
   4722         \\
   4723     ,
   4724         \\test {
   4725         \\    const x = foo
   4726         \\        .bar()
   4727         \\        .zippy(zag).iguessthisisok();
   4728         \\
   4729         \\    const z = view.output.root.server
   4730         \\        .input_manager
   4731         \\        .default_seat.wlr_seat.name;
   4732         \\}
   4733         \\
   4734     );
   4735 }
   4736 
   4737 test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
   4738     try testCanonical(
   4739         \\fn foo() void {
   4740         \\    z.display_message_dialog(
   4741         \\        *const [323:0]u8,
   4742         \\        \\Message Text
   4743         \\        \\------------
   4744         \\        \\xxxxxxxxxxxx
   4745         \\        \\xxxxxxxxxxxx
   4746         \\    ,
   4747         \\        g.GtkMessageType.GTK_MESSAGE_WARNING,
   4748         \\        null,
   4749         \\    );
   4750         \\
   4751         \\    z.display_message_dialog(*const [323:0]u8,
   4752         \\        \\Message Text
   4753         \\        \\------------
   4754         \\        \\xxxxxxxxxxxx
   4755         \\        \\xxxxxxxxxxxx
   4756         \\    , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
   4757         \\}
   4758         \\
   4759     );
   4760 }
   4761 
   4762 test "zig fmt: Control flow statement as body of blockless if" {
   4763     try testCanonical(
   4764         \\pub fn main() void {
   4765         \\    const zoom_node = if (focused_node == layout_first)
   4766         \\        if (it.next()) {
   4767         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4768         \\        } else null
   4769         \\    else
   4770         \\        focused_node;
   4771         \\
   4772         \\    const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
   4773         \\        if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4774         \\    } else null else focused_node;
   4775         \\
   4776         \\    const zoom_node = if (focused_node == layout_first)
   4777         \\        if (it.next()) {
   4778         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4779         \\        } else null;
   4780         \\
   4781         \\    const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
   4782         \\        if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4783         \\    };
   4784         \\
   4785         \\    const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
   4786         \\        break node;
   4787         \\    };
   4788         \\
   4789         \\    const zoom_node = if (focused_node == layout_first) switch (nodes) {
   4790         \\        0 => 0,
   4791         \\    } else focused_node;
   4792         \\}
   4793         \\
   4794     );
   4795 }
   4796 
   4797 test "zig fmt: regression test for #5722" {
   4798     try testCanonical(
   4799         \\pub fn sendViewTags(self: Self) void {
   4800         \\    var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
   4801         \\    while (it.next()) |node|
   4802         \\        view_tags.append(node.view.current_tags) catch {
   4803         \\            c.wl_resource_post_no_memory(self.wl_resource);
   4804         \\            log.err(.river_status, "out of memory", .{});
   4805         \\            return;
   4806         \\        };
   4807         \\}
   4808         \\
   4809     );
   4810 }
   4811 
   4812 test "zig fmt: regression test for #8974" {
   4813     try testCanonical(
   4814         \\pub const VARIABLE;
   4815         \\
   4816     );
   4817 }
   4818 
   4819 test "zig fmt: allow trailing line comments to do manual array formatting" {
   4820     try testCanonical(
   4821         \\fn foo() void {
   4822         \\    self.code.appendSliceAssumeCapacity(&[_]u8{
   4823         \\        0x55, // push rbp
   4824         \\        0x48, 0x89, 0xe5, // mov rbp, rsp
   4825         \\        0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
   4826         \\    });
   4827         \\
   4828         \\    di_buf.appendAssumeCapacity(&[_]u8{
   4829         \\        1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
   4830         \\        DW.AT_stmt_list, DW_FORM_data4, // form value pairs
   4831         \\        DW.AT_low_pc,    DW_FORM_addr,
   4832         \\        DW.AT_high_pc,   DW_FORM_addr,
   4833         \\        DW.AT_name,      DW_FORM_strp,
   4834         \\        DW.AT_comp_dir,  DW_FORM_strp,
   4835         \\        DW.AT_producer,  DW_FORM_strp,
   4836         \\        DW.AT_language,  DW_FORM_data2,
   4837         \\        0, 0, // sentinel
   4838         \\    });
   4839         \\
   4840         \\    self.code.appendSliceAssumeCapacity(&[_]u8{
   4841         \\        0x55, // push rbp
   4842         \\        0x48, 0x89, 0xe5, // mov rbp, rsp
   4843         \\        // How do we handle this?
   4844         \\        //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
   4845         \\        // Here's a blank line, should that be allowed?
   4846         \\
   4847         \\        0x48, 0x89, 0xe5,
   4848         \\        0x33, 0x45,
   4849         \\        // Now the comment breaks a single line -- how do we handle this?
   4850         \\        0x88,
   4851         \\    });
   4852         \\}
   4853         \\
   4854     );
   4855 }
   4856 
   4857 test "zig fmt: multiline string literals should play nice with array initializers" {
   4858     try testCanonical(
   4859         \\fn main() void {
   4860         \\    var a = .{.{.{.{.{.{.{.{
   4861         \\        0,
   4862         \\    }}}}}}}};
   4863         \\    myFunc(.{
   4864         \\        "aaaaaaa",                           "bbbbbb", "ccccc",
   4865         \\        "dddd",                              ("eee"),  ("fff"),
   4866         \\        ("gggg"),
   4867         \\        // Line comment
   4868         \\        \\Multiline String Literals can be quite long
   4869         \\        ,
   4870         \\        \\Multiline String Literals can be quite long
   4871         \\        \\Multiline String Literals can be quite long
   4872         \\        ,
   4873         \\        \\Multiline String Literals can be quite long
   4874         \\        \\Multiline String Literals can be quite long
   4875         \\        \\Multiline String Literals can be quite long
   4876         \\        \\Multiline String Literals can be quite long
   4877         \\        ,
   4878         \\        (
   4879         \\            \\Multiline String Literals can be quite long
   4880         \\        ),
   4881         \\        .{
   4882         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4883         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4884         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4885         \\        },
   4886         \\        .{(
   4887         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4888         \\        )},
   4889         \\        .{
   4890         \\            "xxxxxxx", "xxx",
   4891         \\            (
   4892         \\                \\ xxx
   4893         \\            ),
   4894         \\            "xxx",
   4895         \\            "xxx",
   4896         \\        },
   4897         \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
   4898         \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
   4899         \\        "aaaaaaa", "bbbbbb", "ccccc", // -
   4900         \\        "dddd",    ("eee"),  ("fff"),
   4901         \\        .{
   4902         \\            "xxx",            "xxx",
   4903         \\            (
   4904         \\                \\ xxx
   4905         \\            ),
   4906         \\            "xxxxxxxxxxxxxx",
   4907         \\            "xxx",
   4908         \\        },
   4909         \\        .{
   4910         \\            (
   4911         \\                \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4912         \\            ),
   4913         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4914         \\        },
   4915         \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4916         \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4917         \\    });
   4918         \\}
   4919         \\
   4920     );
   4921 }
   4922 
   4923 test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
   4924     try testCanonical(
   4925         \\pub fn makeMemUndefined(qzz: []u8) i1 {
   4926         \\    cases.add( // fixed bug foo
   4927         \\        "compile diagnostic string for top level decl type",
   4928         \\        \\export fn entry() void {
   4929         \\        \\    var foo: u32 = @This(){};
   4930         \\        \\}
   4931         \\    , &[_][]const u8{
   4932         \\        "tmp.zig:2:27: error: type 'u32' does not support array initialization",
   4933         \\    });
   4934         \\    @compileError(
   4935         \\        \\ unknown-length pointers and C pointers cannot be hashed deeply.
   4936         \\        \\ Consider providing your own hash function.
   4937         \\        \\ unknown-length pointers and C pointers cannot be hashed deeply.
   4938         \\        \\ Consider providing your own hash function.
   4939         \\    );
   4940         \\    return @intCast(doMemCheckClientRequestExpr(0, // default return
   4941         \\        .MakeMemUndefined, @intFromPtr(qzz.ptr), qzz.len, 0, 0, 0));
   4942         \\}
   4943         \\
   4944         \\// This looks like garbage don't do this
   4945         \\const rparen = tree.prevToken(
   4946         \\    // the first token for the annotation expressions is the left
   4947         \\    // parenthesis, hence the need for two prevToken
   4948         \\    if (fn_proto.getAlignExpr()) |align_expr|
   4949         \\        tree.prevToken(tree.prevToken(align_expr.firstToken()))
   4950         \\    else if (fn_proto.getSectionExpr()) |section_expr|
   4951         \\        tree.prevToken(tree.prevToken(section_expr.firstToken()))
   4952         \\    else if (fn_proto.getCallconvExpr()) |callconv_expr|
   4953         \\        tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
   4954         \\    else switch (fn_proto.return_type) {
   4955         \\        .Explicit => |node| node.firstToken(),
   4956         \\        .InferErrorSet => |node| tree.prevToken(node.firstToken()),
   4957         \\        .Invalid => unreachable,
   4958         \\    });
   4959         \\
   4960     );
   4961 }
   4962 
   4963 test "zig fmt: single argument trailing commas in @builtins()" {
   4964     try testCanonical(
   4965         \\pub fn foo(qzz: []u8) i1 {
   4966         \\    @panic(
   4967         \\        foo,
   4968         \\    );
   4969         \\    panic(
   4970         \\        foo,
   4971         \\    );
   4972         \\    @panic(
   4973         \\        foo,
   4974         \\        bar,
   4975         \\    );
   4976         \\}
   4977         \\
   4978     );
   4979 }
   4980 
   4981 test "zig fmt: trailing comma should force multiline 1 column" {
   4982     try testTransform(
   4983         \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
   4984         \\
   4985     ,
   4986         \\pub const UUID_NULL: uuid_t = [16]u8{
   4987         \\    0,
   4988         \\    0,
   4989         \\    0,
   4990         \\    0,
   4991         \\};
   4992         \\
   4993     );
   4994 }
   4995 
   4996 test "zig fmt: function params should align nicely" {
   4997     try testCanonical(
   4998         \\pub fn foo() void {
   4999         \\    cases.addRuntimeSafety("slicing operator with sentinel",
   5000         \\        \\const std = @import("std");
   5001         \\    ++ check_panic_msg ++
   5002         \\        \\pub fn main() void {
   5003         \\        \\    var buf = [4]u8{'a','b','c',0};
   5004         \\        \\    const slice = buf[0..:0];
   5005         \\        \\}
   5006         \\    );
   5007         \\}
   5008         \\
   5009     );
   5010 }
   5011 
   5012 test "zig fmt: fn proto end with anytype and comma" {
   5013     try testCanonical(
   5014         \\pub fn format(
   5015         \\    out_stream: anytype,
   5016         \\) !void {}
   5017         \\
   5018     );
   5019 }
   5020 
   5021 test "zig fmt: space after top level doc comment" {
   5022     try testCanonical(
   5023         \\//! top level doc comment
   5024         \\
   5025         \\field: i32,
   5026         \\
   5027     );
   5028 }
   5029 
   5030 test "zig fmt: remove trailing whitespace after container doc comment" {
   5031     try testTransform(
   5032         \\//! top level doc comment 
   5033         \\
   5034     ,
   5035         \\//! top level doc comment
   5036         \\
   5037     );
   5038 }
   5039 
   5040 test "zig fmt: remove trailing whitespace after doc comment" {
   5041     try testTransform(
   5042         \\/// doc comment 
   5043         \\a = 0,
   5044         \\
   5045     ,
   5046         \\/// doc comment
   5047         \\a = 0,
   5048         \\
   5049     );
   5050 }
   5051 
   5052 test "zig fmt: for loop with ptr payload and index" {
   5053     try testCanonical(
   5054         \\test {
   5055         \\    for (self.entries.items, 0..) |*item, i| {}
   5056         \\    for (self.entries.items, 0..) |*item, i|
   5057         \\        a = b;
   5058         \\    for (self.entries.items, 0..) |*item, i| a = b;
   5059         \\}
   5060         \\
   5061     );
   5062 }
   5063 
   5064 test "zig fmt: proper indent line comment after multi-line single expr while loop" {
   5065     try testCanonical(
   5066         \\test {
   5067         \\    while (a) : (b)
   5068         \\        foo();
   5069         \\
   5070         \\    // bar
   5071         \\    baz();
   5072         \\}
   5073         \\
   5074     );
   5075 }
   5076 
   5077 test "zig fmt: function with labeled block as return type" {
   5078     try testCanonical(
   5079         \\fn foo() t: {
   5080         \\    break :t bar;
   5081         \\} {
   5082         \\    baz();
   5083         \\}
   5084         \\
   5085     );
   5086 }
   5087 
   5088 test "zig fmt: extern function with missing param name" {
   5089     try testCanonical(
   5090         \\extern fn a(
   5091         \\    *b,
   5092         \\    c: *d,
   5093         \\) e;
   5094         \\extern fn f(*g, h: *i) j;
   5095         \\
   5096     );
   5097 }
   5098 
   5099 test "zig fmt: line comment after multiline single expr if statement with multiline string" {
   5100     try testCanonical(
   5101         \\test {
   5102         \\    if (foo)
   5103         \\        x =
   5104         \\            \\hello
   5105         \\            \\hello
   5106         \\            \\
   5107         \\        ;
   5108         \\
   5109         \\    // bar
   5110         \\    baz();
   5111         \\
   5112         \\    if (foo)
   5113         \\        x =
   5114         \\            \\hello
   5115         \\            \\hello
   5116         \\            \\
   5117         \\    else
   5118         \\        y =
   5119         \\            \\hello
   5120         \\            \\hello
   5121         \\            \\
   5122         \\        ;
   5123         \\
   5124         \\    // bar
   5125         \\    baz();
   5126         \\}
   5127         \\
   5128     );
   5129 }
   5130 
   5131 test "zig fmt: respect extra newline between switch items" {
   5132     try testCanonical(
   5133         \\const a = switch (b) {
   5134         \\    .c => {},
   5135         \\
   5136         \\    .d,
   5137         \\    .e,
   5138         \\    => f,
   5139         \\};
   5140         \\
   5141     );
   5142 }
   5143 
   5144 test "zig fmt: assignment with inline for and inline while" {
   5145     try testCanonical(
   5146         \\const tmp = inline for (items) |item| {};
   5147         \\
   5148     );
   5149 
   5150     try testCanonical(
   5151         \\const tmp2 = inline while (true) {};
   5152         \\
   5153     );
   5154 }
   5155 
   5156 test "zig fmt: saturating arithmetic" {
   5157     try testCanonical(
   5158         \\test {
   5159         \\    const actual = switch (op) {
   5160         \\        .add => a +| b,
   5161         \\        .sub => a -| b,
   5162         \\        .mul => a *| b,
   5163         \\        .shl => a <<| b,
   5164         \\    };
   5165         \\    switch (op) {
   5166         \\        .add => actual +|= b,
   5167         \\        .sub => actual -|= b,
   5168         \\        .mul => actual *|= b,
   5169         \\        .shl => actual <<|= b,
   5170         \\    }
   5171         \\}
   5172         \\
   5173     );
   5174 }
   5175 
   5176 test "zig fmt: insert trailing comma if there are comments between switch values" {
   5177     try testTransform(
   5178         \\const a = switch (b) {
   5179         \\    .c => {},
   5180         \\
   5181         \\    .d, // foobar
   5182         \\    .e
   5183         \\    => f,
   5184         \\
   5185         \\    .g, .h
   5186         \\    // comment
   5187         \\    => i,
   5188         \\};
   5189         \\
   5190     ,
   5191         \\const a = switch (b) {
   5192         \\    .c => {},
   5193         \\
   5194         \\    .d, // foobar
   5195         \\    .e,
   5196         \\    => f,
   5197         \\
   5198         \\    .g,
   5199         \\    .h,
   5200         \\    // comment
   5201         \\    => i,
   5202         \\};
   5203         \\
   5204     );
   5205 }
   5206 
   5207 test "zig fmt: insert trailing comma if comments in array init" {
   5208     try testTransform(
   5209         \\var a = .{
   5210         \\    "foo", //
   5211         \\    "bar"
   5212         \\};
   5213         \\var a = .{
   5214         \\    "foo",
   5215         \\    "bar" //
   5216         \\};
   5217         \\var a = .{
   5218         \\    "foo",
   5219         \\    "//"
   5220         \\};
   5221         \\var a = .{
   5222         \\    "foo",
   5223         \\    "//" //
   5224         \\};
   5225         \\
   5226     ,
   5227         \\var a = .{
   5228         \\    "foo", //
   5229         \\    "bar",
   5230         \\};
   5231         \\var a = .{
   5232         \\    "foo",
   5233         \\    "bar", //
   5234         \\};
   5235         \\var a = .{ "foo", "//" };
   5236         \\var a = .{
   5237         \\    "foo",
   5238         \\    "//", //
   5239         \\};
   5240         \\
   5241     );
   5242 }
   5243 
   5244 test "zig fmt: make single-line if no trailing comma" {
   5245     try testTransform(
   5246         \\test "function call no trailing comma" {
   5247         \\    foo(
   5248         \\        1,
   5249         \\        2
   5250         \\    );
   5251         \\}
   5252         \\
   5253     ,
   5254         \\test "function call no trailing comma" {
   5255         \\    foo(1, 2);
   5256         \\}
   5257         \\
   5258     );
   5259 
   5260     try testTransform(
   5261         \\test "struct no trailing comma" {
   5262         \\    const a = .{
   5263         \\        .foo = 1,
   5264         \\        .bar = 2
   5265         \\    };
   5266         \\}
   5267         \\
   5268     ,
   5269         \\test "struct no trailing comma" {
   5270         \\    const a = .{ .foo = 1, .bar = 2 };
   5271         \\}
   5272         \\
   5273     );
   5274 
   5275     try testTransform(
   5276         \\test "array no trailing comma" {
   5277         \\    var stream = multiOutStream(.{
   5278         \\        fbs1.outStream(),
   5279         \\        fbs2.outStream()
   5280         \\    });
   5281         \\}
   5282         \\
   5283     ,
   5284         \\test "array no trailing comma" {
   5285         \\    var stream = multiOutStream(.{ fbs1.outStream(), fbs2.outStream() });
   5286         \\}
   5287         \\
   5288     );
   5289 }
   5290 
   5291 test "zig fmt: preserve container doc comment in container without trailing comma" {
   5292     try testTransform(
   5293         \\const A = enum(u32) {
   5294         \\//! comment
   5295         \\_ };
   5296         \\
   5297     ,
   5298         \\const A = enum(u32) {
   5299         \\    //! comment
   5300         \\    _,
   5301         \\};
   5302         \\
   5303     );
   5304 }
   5305 
   5306 test "zig fmt: make single-line if no trailing comma, fmt: off" {
   5307     try testCanonical(
   5308         \\// Test trailing comma syntax
   5309         \\// zig fmt: off
   5310         \\
   5311         \\extern var a: c_int;
   5312         \\extern "c" var b: c_int;
   5313         \\export var c: c_int = 0;
   5314         \\threadlocal var d: c_int = 0;
   5315         \\extern threadlocal var e: c_int;
   5316         \\extern "c" threadlocal var f: c_int;
   5317         \\export threadlocal var g: c_int = 0;
   5318         \\
   5319         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   5320         \\const struct_no_comma = struct { x: i32, y: i32 };
   5321         \\const struct_fn_no_comma = struct { fn m() void {} y: i32 };
   5322         \\
   5323         \\const enum_no_comma = enum { A, B };
   5324         \\
   5325         \\fn container_init() void {
   5326         \\    const S = struct { x: i32, y: i32 };
   5327         \\    _ = S { .x = 1, .y = 2 };
   5328         \\    _ = S { .x = 1, .y = 2, };
   5329         \\}
   5330         \\
   5331         \\fn type_expr_return1() if (true) A {}
   5332         \\fn type_expr_return2() for (true) |_| A {}
   5333         \\fn type_expr_return3() while (true) A {}
   5334         \\
   5335         \\fn switch_cases(x: i32) void {
   5336         \\    switch (x) {
   5337         \\        1,2,3 => {},
   5338         \\        4,5, => {},
   5339         \\        6...8, => {},
   5340         \\        else => {},
   5341         \\    }
   5342         \\}
   5343         \\
   5344         \\fn switch_prongs(x: i32) void {
   5345         \\    switch (x) {
   5346         \\        0 => {},
   5347         \\        else => {},
   5348         \\    }
   5349         \\    switch (x) {
   5350         \\        0 => {},
   5351         \\        else => {}
   5352         \\    }
   5353         \\}
   5354         \\
   5355         \\const fn_no_comma = fn (i32, i32) void;
   5356         \\const fn_trailing_comma = fn (i32, i32,) void;
   5357         \\
   5358         \\fn fn_calls() void {
   5359         \\    fn add(x: i32, y: i32,) i32 { x + y };
   5360         \\    _ = add(1, 2);
   5361         \\    _ = add(1, 2,);
   5362         \\}
   5363         \\
   5364         \\fn asm_lists() void {
   5365         \\    if (false) { // Build AST but don't analyze
   5366         \\        asm ("not real assembly"
   5367         \\            :[a] "x" (x),);
   5368         \\        asm ("not real assembly"
   5369         \\            :[a] "x" (->i32),:[a] "x" (1),);
   5370         \\        asm volatile ("still not real assembly"
   5371         \\            :::.{.a = true,.b = true,});
   5372         \\    }
   5373         \\}
   5374     );
   5375 }
   5376 
   5377 test "zig fmt: variable initialized with ==" {
   5378     try testError(
   5379         \\comptime {
   5380         \\    var z: u32 == 12 + 1;
   5381         \\}
   5382     , &.{.wrong_equal_var_decl});
   5383 }
   5384 
   5385 test "zig fmt: missing const/var before local variable in comptime block" {
   5386     try testError(
   5387         \\comptime {
   5388         \\    z: u32;
   5389         \\}
   5390         \\comptime {
   5391         \\    z: u32 align(1);
   5392         \\}
   5393         \\comptime {
   5394         \\    z: u32 addrspace(.generic);
   5395         \\}
   5396         \\comptime {
   5397         \\    z: u32 linksection("foo");
   5398         \\}
   5399         \\comptime {
   5400         \\    z: u32 = 1;
   5401         \\}
   5402     , &.{
   5403         .expected_labelable,
   5404         .expected_var_const,
   5405         .expected_var_const,
   5406         .expected_var_const,
   5407         .expected_var_const,
   5408     });
   5409 }
   5410 
   5411 test "zig fmt: missing const/var before local variable" {
   5412     try testError(
   5413         \\std = foo,
   5414         \\std = foo;
   5415         \\*u32 = foo;
   5416     , &.{
   5417         .expected_comma_after_field,
   5418         .var_const_decl,
   5419         .expected_comma_after_field,
   5420     });
   5421 }
   5422 
   5423 test "zig fmt: while continue expr" {
   5424     try testCanonical(
   5425         \\test {
   5426         \\    while (i > 0)
   5427         \\        (i * 2);
   5428         \\}
   5429         \\
   5430     );
   5431     try testError(
   5432         \\test {
   5433         \\    while (i > 0) (i -= 1) {
   5434         \\        print("test123", .{});
   5435         \\    }
   5436         \\}
   5437     , &[_]Error{
   5438         .expected_continue_expr,
   5439     });
   5440 }
   5441 
   5442 test "zig fmt: canonicalize symbols (simple)" {
   5443     try testTransform(
   5444         \\const val_normal: Normal = .{};
   5445         \\const @"val_unesc_me": @"UnescMe" = .{};
   5446         \\const @"val_esc!": @"Esc!" = .{};
   5447         \\
   5448         \\fn fnNormal() void {}
   5449         \\fn @"fnUnescMe"() void {}
   5450         \\fn @"fnEsc!"() void {}
   5451         \\
   5452         \\extern fn protoNormal() void;
   5453         \\extern fn @"protoUnescMe"() void;
   5454         \\extern fn @"protoEsc!"() void;
   5455         \\
   5456         \\fn fnWithArgs(normal: Normal, @"unesc_me": @"UnescMe", @"esc!": @"Esc!") void {
   5457         \\    _ = normal;
   5458         \\    _ = @"unesc_me";
   5459         \\    _ = @"esc!";
   5460         \\}
   5461         \\
   5462         \\const Normal = struct {};
   5463         \\const @"UnescMe" = struct {
   5464         \\    @"x": @"X",
   5465         \\    const X = union(@"EnumUnesc") {
   5466         \\        normal,
   5467         \\        @"unesc_me",
   5468         \\        @"esc!",
   5469         \\    };
   5470         \\    const @"EnumUnesc" = enum {
   5471         \\        normal,
   5472         \\        @"unesc_me",
   5473         \\        @"esc!",
   5474         \\    };
   5475         \\};
   5476         \\const @"Esc!" = struct {
   5477         \\    normal: bool = false,
   5478         \\    @"unesc_me": bool = false,
   5479         \\    @"esc!": bool = false,
   5480         \\};
   5481         \\
   5482         \\pub fn main() void {
   5483         \\    _ = val_normal;
   5484         \\    _ = @"val_normal";
   5485         \\    _ = val_unesc_me;
   5486         \\    _ = @"val_unesc_me";
   5487         \\    _ = @"val_esc!";
   5488         \\
   5489         \\    fnNormal();
   5490         \\    @"fnNormal"();
   5491         \\    fnUnescMe();
   5492         \\    @"fnUnescMe"();
   5493         \\    @"fnEsc!"();
   5494         \\
   5495         \\    fnWithArgs(1, Normal{}, UnescMe{}, @"Esc!"{});
   5496         \\    fnWithArgs(1, @"Normal"{}, @"UnescMe"{}, @"Esc!"{});
   5497         \\    fnWithArgs(1, @"Normal"{}, @"Normal"{}, @"Esc!"{});
   5498         \\
   5499         \\    const local_val1: @"Normal" = .{};
   5500         \\    const @"local_val2": UnescMe = .{
   5501         \\        .@"x" = .@"unesc_me",
   5502         \\    };
   5503         \\    fnWithArgs(@"local_val1", @"local_val2", .{ .@"normal" = true, .@"unesc_me" = true, .@"esc!" = true });
   5504         \\    fnWithArgs(local_val1, local_val2, .{ .normal = true, .unesc_me = true, .@"esc!" = true });
   5505         \\
   5506         \\    var x: u8 = 'x';
   5507         \\    switch (@"x") {
   5508         \\        @"x" => {},
   5509         \\    }
   5510         \\
   5511         \\    _ = @import("std"); // Don't mess with @builtins
   5512         \\    // @"comment"
   5513         \\}
   5514         \\
   5515     ,
   5516         \\const val_normal: Normal = .{};
   5517         \\const val_unesc_me: UnescMe = .{};
   5518         \\const @"val_esc!": @"Esc!" = .{};
   5519         \\
   5520         \\fn fnNormal() void {}
   5521         \\fn fnUnescMe() void {}
   5522         \\fn @"fnEsc!"() void {}
   5523         \\
   5524         \\extern fn protoNormal() void;
   5525         \\extern fn protoUnescMe() void;
   5526         \\extern fn @"protoEsc!"() void;
   5527         \\
   5528         \\fn fnWithArgs(normal: Normal, unesc_me: UnescMe, @"esc!": @"Esc!") void {
   5529         \\    _ = normal;
   5530         \\    _ = unesc_me;
   5531         \\    _ = @"esc!";
   5532         \\}
   5533         \\
   5534         \\const Normal = struct {};
   5535         \\const UnescMe = struct {
   5536         \\    x: X,
   5537         \\    const X = union(EnumUnesc) {
   5538         \\        normal,
   5539         \\        unesc_me,
   5540         \\        @"esc!",
   5541         \\    };
   5542         \\    const EnumUnesc = enum {
   5543         \\        normal,
   5544         \\        unesc_me,
   5545         \\        @"esc!",
   5546         \\    };
   5547         \\};
   5548         \\const @"Esc!" = struct {
   5549         \\    normal: bool = false,
   5550         \\    unesc_me: bool = false,
   5551         \\    @"esc!": bool = false,
   5552         \\};
   5553         \\
   5554         \\pub fn main() void {
   5555         \\    _ = val_normal;
   5556         \\    _ = val_normal;
   5557         \\    _ = val_unesc_me;
   5558         \\    _ = val_unesc_me;
   5559         \\    _ = @"val_esc!";
   5560         \\
   5561         \\    fnNormal();
   5562         \\    fnNormal();
   5563         \\    fnUnescMe();
   5564         \\    fnUnescMe();
   5565         \\    @"fnEsc!"();
   5566         \\
   5567         \\    fnWithArgs(1, Normal{}, UnescMe{}, @"Esc!"{});
   5568         \\    fnWithArgs(1, Normal{}, UnescMe{}, @"Esc!"{});
   5569         \\    fnWithArgs(1, Normal{}, Normal{}, @"Esc!"{});
   5570         \\
   5571         \\    const local_val1: Normal = .{};
   5572         \\    const local_val2: UnescMe = .{
   5573         \\        .x = .unesc_me,
   5574         \\    };
   5575         \\    fnWithArgs(local_val1, local_val2, .{ .normal = true, .unesc_me = true, .@"esc!" = true });
   5576         \\    fnWithArgs(local_val1, local_val2, .{ .normal = true, .unesc_me = true, .@"esc!" = true });
   5577         \\
   5578         \\    var x: u8 = 'x';
   5579         \\    switch (x) {
   5580         \\        x => {},
   5581         \\    }
   5582         \\
   5583         \\    _ = @import("std"); // Don't mess with @builtins
   5584         \\    // @"comment"
   5585         \\}
   5586         \\
   5587     );
   5588 }
   5589 
   5590 // Contextually unescape when shadowing primitive types and values.
   5591 test "zig fmt: canonicalize symbols (primitive types)" {
   5592     try testTransform(
   5593         \\const @"anyopaque" = struct {
   5594         \\    @"u8": @"type" = true,
   5595         \\    @"_": @"false" = @"true",
   5596         \\    const @"type" = bool;
   5597         \\    const @"false" = bool;
   5598         \\    const @"true" = false;
   5599         \\};
   5600         \\
   5601         \\const U = union(@"null") {
   5602         \\    @"type",
   5603         \\    const @"null" = enum {
   5604         \\        @"type",
   5605         \\    };
   5606         \\};
   5607         \\
   5608         \\test {
   5609         \\    const E = enum { @"anyopaque" };
   5610         \\    _ = U{ .@"type" = {} };
   5611         \\    _ = U.@"type";
   5612         \\    _ = E.@"anyopaque";
   5613         \\}
   5614         \\
   5615         \\fn @"i10"(@"void": @"anyopaque", @"type": @"anyopaque".@"type") error{@"null"}!void {
   5616         \\    var @"f32" = @"void";
   5617         \\    @"f32".@"u8" = false;
   5618         \\    _ = @"type";
   5619         \\    _ = type;
   5620         \\    if (@"f32".@"u8") {
   5621         \\        return @"i10"(.{ .@"u8" = true, .@"_" = false }, false);
   5622         \\    } else {
   5623         \\        return error.@"null";
   5624         \\    }
   5625         \\}
   5626         \\
   5627         \\test @"i10" {
   5628         \\    try @"i10"(.{}, true);
   5629         \\    _ = @"void": while (null) |@"u3"| {
   5630         \\        break :@"void" @"u3";
   5631         \\    };
   5632         \\    _ = @"void": {
   5633         \\        break :@"void";
   5634         \\    };
   5635         \\    for ("hi", 0..) |@"u3", @"i4"| {
   5636         \\        _ = @"u3";
   5637         \\        _ = @"i4";
   5638         \\    }
   5639         \\    if (false) {} else |@"bool"| {
   5640         \\        _ = @"bool";
   5641         \\    }
   5642         \\}
   5643         \\
   5644     ,
   5645         \\const @"anyopaque" = struct {
   5646         \\    u8: @"type" = true,
   5647         \\    _: @"false" = @"true",
   5648         \\    const @"type" = bool;
   5649         \\    const @"false" = bool;
   5650         \\    const @"true" = false;
   5651         \\};
   5652         \\
   5653         \\const U = union(@"null") {
   5654         \\    type,
   5655         \\    const @"null" = enum {
   5656         \\        type,
   5657         \\    };
   5658         \\};
   5659         \\
   5660         \\test {
   5661         \\    const E = enum { anyopaque };
   5662         \\    _ = U{ .type = {} };
   5663         \\    _ = U.type;
   5664         \\    _ = E.anyopaque;
   5665         \\}
   5666         \\
   5667         \\fn @"i10"(@"void": @"anyopaque", @"type": @"anyopaque".type) error{null}!void {
   5668         \\    var @"f32" = @"void";
   5669         \\    @"f32".u8 = false;
   5670         \\    _ = @"type";
   5671         \\    _ = type;
   5672         \\    if (@"f32".u8) {
   5673         \\        return @"i10"(.{ .u8 = true, ._ = false }, false);
   5674         \\    } else {
   5675         \\        return error.null;
   5676         \\    }
   5677         \\}
   5678         \\
   5679         \\test @"i10" {
   5680         \\    try @"i10"(.{}, true);
   5681         \\    _ = void: while (null) |@"u3"| {
   5682         \\        break :void @"u3";
   5683         \\    };
   5684         \\    _ = void: {
   5685         \\        break :void;
   5686         \\    };
   5687         \\    for ("hi", 0..) |@"u3", @"i4"| {
   5688         \\        _ = @"u3";
   5689         \\        _ = @"i4";
   5690         \\    }
   5691         \\    if (false) {} else |@"bool"| {
   5692         \\        _ = @"bool";
   5693         \\    }
   5694         \\}
   5695         \\
   5696     );
   5697 }
   5698 
   5699 test "zig fmt: no space before newline before multiline string" {
   5700     try testCanonical(
   5701         \\const S = struct {
   5702         \\    text: []const u8,
   5703         \\    comment: []const u8,
   5704         \\};
   5705         \\
   5706         \\test {
   5707         \\    const s1 = .{
   5708         \\        .text =
   5709         \\        \\hello
   5710         \\        \\world
   5711         \\        ,
   5712         \\        .comment = "test",
   5713         \\    };
   5714         \\    _ = s1;
   5715         \\    const s2 = .{
   5716         \\        .comment = "test",
   5717         \\        .text =
   5718         \\        \\hello
   5719         \\        \\world
   5720         \\        ,
   5721         \\    };
   5722         \\    _ = s2;
   5723         \\}
   5724         \\
   5725     );
   5726 }
   5727 
   5728 // Normalize \xNN and \u{NN} escapes and unicode inside @"" escapes.
   5729 test "zig fmt: canonicalize symbols (character escapes)" {
   5730     try testTransform(
   5731         \\const @"\x46\x6f\x6f\x64" = struct {
   5732         \\    @"\x62\x61\x72\x6E": @"\x43\x72\x61\x62" = false,
   5733         \\    @"\u{67}\u{6C}o\u{70}\xFF": @"Cra\x62" = false,
   5734         \\    @"\x65\x72\x72\x6F\x72": Crab = true,
   5735         \\    @"\x74\x72\x79": Crab = true,
   5736         \\    @"\u{74}\u{79}\u{70}\u{65}": @"any\u{6F}\u{70}\u{61}\u{71}\u{75}\u{65}",
   5737         \\
   5738         \\    const @"\x43\x72\x61\x62" = bool;
   5739         \\    const @"\x61\x6E\x79\x6F\x70\x61que" = void;
   5740         \\};
   5741         \\
   5742         \\test "unicode" {
   5743         \\    const @"cąbbäge ⚡" = 2;
   5744         \\    _ = @"cąbbäge ⚡";
   5745         \\    const @"\u{01f422} friend\u{f6}" = 4;
   5746         \\    _ = @"🐢 friendö";
   5747         \\}
   5748         \\
   5749     ,
   5750         \\const Food = struct {
   5751         \\    barn: Crab = false,
   5752         \\    @"glop\xFF": Crab = false,
   5753         \\    @"error": Crab = true,
   5754         \\    @"try": Crab = true,
   5755         \\    type: @"anyopaque",
   5756         \\
   5757         \\    const Crab = bool;
   5758         \\    const @"anyopaque" = void;
   5759         \\};
   5760         \\
   5761         \\test "unicode" {
   5762         \\    const @"cąbbäge ⚡" = 2;
   5763         \\    _ = @"cąbbäge ⚡";
   5764         \\    const @"\u{01f422} friend\u{f6}" = 4;
   5765         \\    _ = @"🐢 friendö";
   5766         \\}
   5767         \\
   5768     );
   5769 }
   5770 
   5771 test "zig fmt: canonicalize symbols (asm)" {
   5772     try testTransform(
   5773         \\test "asm" {
   5774         \\    const @"null" = usize;
   5775         \\    const @"try": usize = 808;
   5776         \\    const arg: usize = 2;
   5777         \\    _ = asm volatile ("syscall"
   5778         \\        : [@"void"] "={rax}" (-> @"null"),
   5779         \\        : [@"error"] "{rax}" (@"try"),
   5780         \\          [@"arg1"] "{rdi}" (arg),
   5781         \\          [arg2] "{rsi}" (arg),
   5782         \\          [arg3] "{rdx}" (arg),
   5783         \\        : "rcx", "fn"
   5784         \\    );
   5785         \\
   5786         \\    const @"false": usize = 10;
   5787         \\    const @"true" = "explode";
   5788         \\    _ = asm volatile (@"true"
   5789         \\        : [one] "={rax}" (@"false"),
   5790         \\        : [two] "{rax}" (@"false"),
   5791         \\    );
   5792         \\}
   5793         \\
   5794     ,
   5795         \\test "asm" {
   5796         \\    const @"null" = usize;
   5797         \\    const @"try": usize = 808;
   5798         \\    const arg: usize = 2;
   5799         \\    _ = asm volatile ("syscall"
   5800         \\        : [void] "={rax}" (-> @"null"),
   5801         \\        : [@"error"] "{rax}" (@"try"),
   5802         \\          [arg1] "{rdi}" (arg),
   5803         \\          [arg2] "{rsi}" (arg),
   5804         \\          [arg3] "{rdx}" (arg),
   5805         \\        : .{ .rcx = true, .@"fn" = true }
   5806         \\    );
   5807         \\
   5808         \\    const @"false": usize = 10;
   5809         \\    const @"true" = "explode";
   5810         \\    _ = asm volatile (@"true"
   5811         \\        : [one] "={rax}" (false),
   5812         \\        : [two] "{rax}" (@"false"),
   5813         \\    );
   5814         \\}
   5815         \\
   5816     );
   5817 }
   5818 
   5819 test "zig fmt: don't canonicalize _ in enums" {
   5820     try testTransform(
   5821         \\const A = enum {
   5822         \\    first,
   5823         \\    second,
   5824         \\    third,
   5825         \\    _,
   5826         \\};
   5827         \\const B = enum {
   5828         \\    @"_",
   5829         \\    @"__",
   5830         \\    @"___",
   5831         \\    @"____",
   5832         \\};
   5833         \\const C = struct {
   5834         \\    @"_": u8,
   5835         \\    @"__": u8,
   5836         \\    @"___": u8,
   5837         \\    @"____": u8,
   5838         \\};
   5839         \\const D = union {
   5840         \\    @"_": u8,
   5841         \\    @"__": u8,
   5842         \\    @"___": u8,
   5843         \\    @"____": u8,
   5844         \\};
   5845         \\
   5846     ,
   5847         \\const A = enum {
   5848         \\    first,
   5849         \\    second,
   5850         \\    third,
   5851         \\    _,
   5852         \\};
   5853         \\const B = enum {
   5854         \\    @"_",
   5855         \\    __,
   5856         \\    ___,
   5857         \\    ____,
   5858         \\};
   5859         \\const C = struct {
   5860         \\    _: u8,
   5861         \\    __: u8,
   5862         \\    ___: u8,
   5863         \\    ____: u8,
   5864         \\};
   5865         \\const D = union {
   5866         \\    _: u8,
   5867         \\    __: u8,
   5868         \\    ___: u8,
   5869         \\    ____: u8,
   5870         \\};
   5871         \\
   5872     );
   5873 }
   5874 
   5875 test "zig fmt: error for missing sentinel value in sentinel slice" {
   5876     try testError(
   5877         \\const foo = foo[0..:];
   5878     , &[_]Error{
   5879         .expected_expr,
   5880     });
   5881 }
   5882 
   5883 test "zig fmt: error for invalid bit range" {
   5884     try testError(
   5885         \\var x: []align(0:0:0)u8 = bar;
   5886     , &[_]Error{
   5887         .invalid_bit_range,
   5888     });
   5889 }
   5890 
   5891 test "zig fmt: error for ptr mod on array child type" {
   5892     try testError(
   5893         \\var a: [10]align(10) u8 = e;
   5894         \\var b: [10]const u8 = f;
   5895         \\var c: [10]volatile u8 = g;
   5896         \\var d: [10]allowzero u8 = h;
   5897     , &[_]Error{
   5898         .ptr_mod_on_array_child_type,
   5899         .ptr_mod_on_array_child_type,
   5900         .ptr_mod_on_array_child_type,
   5901         .ptr_mod_on_array_child_type,
   5902     });
   5903 }
   5904 
   5905 test "zig fmt: pointer type syntax to index" {
   5906     try testCanonical(
   5907         \\test {
   5908         \\    _ = .{}[*0];
   5909         \\}
   5910         \\
   5911     );
   5912 }
   5913 
   5914 test "zig fmt: binop indentation in if statement" {
   5915     try testCanonical(
   5916         \\test {
   5917         \\    if (first_param_type.isGenericPoison() or
   5918         \\        (first_param_type.zigTypeTag(zcu) == .pointer and
   5919         \\            (first_param_type.ptrSize(zcu) == .One or
   5920         \\                first_param_type.ptrSize(zcu) == .C) and
   5921         \\            first_param_type.childType(zcu).eql(concrete_ty, zcu)))
   5922         \\    {
   5923         \\        f(x);
   5924         \\    }
   5925         \\}
   5926         \\
   5927     );
   5928 }
   5929 
   5930 test "zig fmt: test indentation after equals sign" {
   5931     try testCanonical(
   5932         \\test {
   5933         \\    const foo =
   5934         \\        if (1 == 2)
   5935         \\            1
   5936         \\        else if (3 > 4)
   5937         \\            2
   5938         \\        else
   5939         \\            0;
   5940         \\
   5941         \\    const foo, const bar =
   5942         \\        if (1 == 2)
   5943         \\            .{ 0, 0 }
   5944         \\        else if (3 > 4)
   5945         \\            .{ 1, 1 }
   5946         \\        else
   5947         \\            .{ 2, 2 };
   5948         \\
   5949         \\    while (foo) if (bar)
   5950         \\        f(x);
   5951         \\
   5952         \\    foobar =
   5953         \\        if (true)
   5954         \\            1
   5955         \\        else
   5956         \\            0;
   5957         \\
   5958         \\    const foo = if (1 == 2)
   5959         \\        1
   5960         \\    else if (3 > 4)
   5961         \\        2
   5962         \\    else
   5963         \\        0;
   5964         \\
   5965         \\    const foo, const bar = if (1 == 2)
   5966         \\        .{ 0, 0 }
   5967         \\    else if (3 > 4)
   5968         \\        .{ 1, 1 }
   5969         \\    else
   5970         \\        .{ 2, 2 };
   5971         \\
   5972         \\    foobar = if (true)
   5973         \\        1
   5974         \\    else
   5975         \\        0;
   5976         \\
   5977         \\    const is_alphanum =
   5978         \\        (ch >= 'a' and ch <= 'z') or
   5979         \\        (ch >= 'A' and ch <= 'Z') or
   5980         \\        (ch >= '0' and ch <= '9');
   5981         \\
   5982         \\    const bar = 100 + calculate(
   5983         \\        200,
   5984         \\        300,
   5985         \\    );
   5986         \\
   5987         \\    const gcc_pragma = std.meta.stringToEnum(Directive, pp.expandedSlice(directive_tok)) orelse
   5988         \\        return pp.comp.addDiagnostic(.{
   5989         \\            .tag = .unknown_gcc_pragma,
   5990         \\            .loc = directive_tok.loc,
   5991         \\        }, pp.expansionSlice(start_idx + 1));
   5992         \\
   5993         \\    const vec4s =
   5994         \\        [_][4]i32{
   5995         \\            [_]i32{ 0, 1, 0, 0 },
   5996         \\            [_]i32{ 0, -1, 0, 0 },
   5997         \\            [_]i32{ 2, 1, 2, 0 },
   5998         \\        };
   5999         \\}
   6000         \\
   6001     );
   6002 }
   6003 
   6004 test "zig fmt: test indentation of if expressions" {
   6005     try testCanonical(
   6006         \\test {
   6007         \\    const foo = 1 +
   6008         \\        if (1 == 2)
   6009         \\            2
   6010         \\        else
   6011         \\            0;
   6012         \\
   6013         \\    const foo = 1 + if (1 == 2)
   6014         \\        2
   6015         \\    else
   6016         \\        0;
   6017         \\
   6018         \\    errval catch |e|
   6019         \\        if (e == error.Meow)
   6020         \\            return 0x1F408
   6021         \\        else
   6022         \\            unreachable;
   6023         \\
   6024         \\    errval catch |e| if (e == error.Meow)
   6025         \\        return 0x1F408
   6026         \\    else
   6027         \\        unreachable;
   6028         \\
   6029         \\    return if (1 == 2)
   6030         \\        1
   6031         \\    else if (3 > 4)
   6032         \\        2
   6033         \\    else
   6034         \\        0;
   6035         \\}
   6036         \\
   6037     );
   6038 }
   6039 
   6040 test "zig fmt: indentation of comments within catch, else, orelse" {
   6041     try testCanonical(
   6042         \\comptime {
   6043         \\    _ = foo() catch
   6044         \\        //
   6045         \\        bar();
   6046         \\
   6047         \\    _ = if (foo) bar() else
   6048         \\        //
   6049         \\        qux();
   6050         \\
   6051         \\    _ = foo() orelse
   6052         \\        //
   6053         \\        qux();
   6054         \\}
   6055         \\
   6056     );
   6057 }
   6058 
   6059 test "zig fmt: canonicalize cast builtins" {
   6060     try testTransform(
   6061         \\const foo = @alignCast(@ptrCast(bar));
   6062         \\const baz = @constCast(@ptrCast(@addrSpaceCast(@volatileCast(@alignCast(bar)))));
   6063         \\
   6064     ,
   6065         \\const foo = @ptrCast(@alignCast(bar));
   6066         \\const baz = @ptrCast(@alignCast(@addrSpaceCast(@constCast(@volatileCast(bar)))));
   6067         \\
   6068     );
   6069 }
   6070 
   6071 test "zig fmt: do not canonicalize invalid cast builtins" {
   6072     try testCanonical(
   6073         \\const foo = @alignCast(@volatileCast(@ptrCast(@alignCast(bar))));
   6074         \\
   6075     );
   6076 }
   6077 
   6078 test "recovery: top level" {
   6079     try testError(
   6080         \\test "" {inline}
   6081         \\test "" {inline}
   6082     , &[_]Error{
   6083         .expected_inlinable,
   6084         .expected_inlinable,
   6085     });
   6086 }
   6087 
   6088 test "recovery: block statements" {
   6089     try testError(
   6090         \\test "" {
   6091         \\    foo + +;
   6092         \\    inline;
   6093         \\}
   6094     , &[_]Error{
   6095         .expected_expr,
   6096         .expected_semi_after_stmt,
   6097         .expected_statement,
   6098         .expected_inlinable,
   6099     });
   6100 }
   6101 
   6102 test "recovery: missing comma" {
   6103     try testError(
   6104         \\test "" {
   6105         \\    switch (foo) {
   6106         \\        2 => {}
   6107         \\        3 => {}
   6108         \\        else => {
   6109         \\            foo & bar +;
   6110         \\        }
   6111         \\    }
   6112         \\}
   6113     , &[_]Error{
   6114         .expected_comma_after_switch_prong,
   6115         .expected_comma_after_switch_prong,
   6116         .expected_expr,
   6117     });
   6118 }
   6119 
   6120 test "recovery: non-associative operators" {
   6121     try testError(
   6122         \\const x = a == b == c;
   6123         \\const x = a == b != c;
   6124     , &[_]Error{
   6125         .chained_comparison_operators,
   6126         .chained_comparison_operators,
   6127     });
   6128 }
   6129 
   6130 test "recovery: extra qualifier" {
   6131     try testError(
   6132         \\const a: *const const u8;
   6133         \\test ""
   6134     , &[_]Error{
   6135         .extra_const_qualifier,
   6136         .expected_block,
   6137     });
   6138 }
   6139 
   6140 test "recovery: missing return type" {
   6141     try testError(
   6142         \\fn foo() {
   6143         \\    a & b;
   6144         \\}
   6145         \\test ""
   6146     , &[_]Error{
   6147         .expected_return_type,
   6148         .expected_block,
   6149     });
   6150 }
   6151 
   6152 test "recovery: invalid extern/inline" {
   6153     try testError(
   6154         \\inline test "" { a & b; }
   6155     , &[_]Error{
   6156         .expected_fn,
   6157     });
   6158     try testError(
   6159         \\extern "" test "" { a & b; }
   6160     , &[_]Error{
   6161         .expected_var_decl_or_fn,
   6162     });
   6163 }
   6164 
   6165 test "recovery: missing semicolon" {
   6166     try testError(
   6167         \\test "" {
   6168         \\    comptime a & b
   6169         \\    c & d
   6170         \\    @foo
   6171         \\}
   6172     , &[_]Error{
   6173         .expected_semi_after_stmt,
   6174         .expected_semi_after_stmt,
   6175         .expected_param_list,
   6176         .expected_semi_after_stmt,
   6177     });
   6178 }
   6179 
   6180 // TODO after https://github.com/ziglang/zig/issues/35 is implemented,
   6181 // we should be able to recover from this *at any indentation level*,
   6182 // reporting a parse error and yet also parsing all the decls even
   6183 // inside structs.
   6184 test "recovery: extra '}' at top level" {
   6185     try testError(
   6186         \\}}}
   6187         \\test "" {
   6188         \\    a & b;
   6189         \\}
   6190     , &[_]Error{
   6191         .expected_token,
   6192     });
   6193 }
   6194 
   6195 test "recovery: mismatched bracket at top level" {
   6196     try testError(
   6197         \\const S = struct {
   6198         \\    arr: 128]?G
   6199         \\};
   6200     , &[_]Error{
   6201         .expected_comma_after_field,
   6202     });
   6203 }
   6204 
   6205 test "recovery: invalid global error set access" {
   6206     try testError(
   6207         \\test "" {
   6208         \\    error & foo;
   6209         \\}
   6210     , &[_]Error{
   6211         .expected_token,
   6212     });
   6213 }
   6214 
   6215 test "recovery: invalid asterisk after pointer dereference" {
   6216     try testError(
   6217         \\test "" {
   6218         \\    var sequence = "repeat".*** 10;
   6219         \\}
   6220     , &[_]Error{
   6221         .asterisk_after_ptr_deref,
   6222         .mismatched_binary_op_whitespace,
   6223     });
   6224     try testError(
   6225         \\test "" {
   6226         \\    var sequence = "repeat".** 10&a;
   6227         \\}
   6228     , &[_]Error{
   6229         .asterisk_after_ptr_deref,
   6230         .mismatched_binary_op_whitespace,
   6231     });
   6232 }
   6233 
   6234 test "recovery: missing semicolon after if, for, while stmt" {
   6235     try testError(
   6236         \\test "" {
   6237         \\    if (foo) bar
   6238         \\    for (foo) |a| bar
   6239         \\    while (foo) bar
   6240         \\    a & b;
   6241         \\}
   6242     , &[_]Error{
   6243         .expected_semi_or_else,
   6244         .expected_semi_or_else,
   6245         .expected_semi_or_else,
   6246     });
   6247 }
   6248 
   6249 test "recovery: invalid comptime" {
   6250     try testError(
   6251         \\comptime
   6252     , &[_]Error{
   6253         .expected_type_expr,
   6254     });
   6255 }
   6256 
   6257 test "recovery: missing block after suspend" {
   6258     try testError(
   6259         \\fn foo() void {
   6260         \\    suspend;
   6261         \\    nosuspend;
   6262         \\}
   6263     , &[_]Error{
   6264         .expected_block_or_expr,
   6265         .expected_block_or_expr,
   6266     });
   6267 }
   6268 
   6269 test "recovery: missing block after for/while loops" {
   6270     try testError(
   6271         \\test "" { while (foo) }
   6272     , &[_]Error{
   6273         .expected_block_or_assignment,
   6274     });
   6275     try testError(
   6276         \\test "" { for (foo) |bar| }
   6277     , &[_]Error{
   6278         .expected_block_or_assignment,
   6279     });
   6280 }
   6281 
   6282 test "recovery: missing for payload" {
   6283     try testError(
   6284         \\comptime {
   6285         \\    const a = for(a) {};
   6286         \\    const a: for(a) blk: {} = {};
   6287         \\    for(a) {}
   6288         \\}
   6289     , &[_]Error{
   6290         .expected_loop_payload,
   6291         .expected_loop_payload,
   6292         .expected_loop_payload,
   6293     });
   6294 }
   6295 
   6296 test "recovery: missing comma in params" {
   6297     try testError(
   6298         \\fn foo(comptime bool what what) void { }
   6299         \\fn bar(a: i32, b: i32 c) void { }
   6300         \\
   6301     , &[_]Error{
   6302         .expected_comma_after_param,
   6303         .expected_comma_after_param,
   6304         .expected_comma_after_param,
   6305     });
   6306 }
   6307 
   6308 test "recovery: missing while rbrace" {
   6309     try testError(
   6310         \\fn a() b {
   6311         \\    while (d) {
   6312         \\}
   6313     , &[_]Error{
   6314         .expected_statement,
   6315     });
   6316 }
   6317 
   6318 test "recovery: nonfinal varargs" {
   6319     try testError(
   6320         \\extern fn f(a: u32, ..., b: u32) void;
   6321         \\extern fn g(a: u32, ..., b: anytype) void;
   6322         \\extern fn h(a: u32, ..., ...) void;
   6323     , &[_]Error{
   6324         .varargs_nonfinal,
   6325         .varargs_nonfinal,
   6326         .varargs_nonfinal,
   6327     });
   6328 }
   6329 
   6330 test "recovery: eof in c pointer" {
   6331     try testError(
   6332         \\const Ptr = [*c
   6333     , &[_]Error{
   6334         .expected_token,
   6335     });
   6336 }
   6337 
   6338 test "matching whitespace on minus op" {
   6339     try testError(
   6340         \\ _ = 2 -1, 
   6341         \\ _ = 2- 1, 
   6342         \\ _ = 2-
   6343         \\     2,
   6344         \\ _ = 2
   6345         \\     -2,
   6346     , &[_]Error{
   6347         .mismatched_binary_op_whitespace,
   6348         .mismatched_binary_op_whitespace,
   6349         .mismatched_binary_op_whitespace,
   6350         .mismatched_binary_op_whitespace,
   6351     });
   6352 
   6353     try testError(
   6354         \\ _ = - 1,
   6355         \\ _ = -1,
   6356         \\ _ = 2 - -1,
   6357         \\ _ = 2 - 1,
   6358         \\ _ = 2-1, 
   6359         \\ _ = 2 -
   6360         \\1,
   6361         \\ _ = 2
   6362         \\     - 1,
   6363     , &[_]Error{});
   6364 }
   6365 
   6366 test "ampersand" {
   6367     try testError(
   6368         \\ _ = bar && foo,
   6369         \\ _ = bar&&foo, 
   6370         \\ _ = bar& & foo, 
   6371         \\ _ = bar& &foo,
   6372     , &.{
   6373         .invalid_ampersand_ampersand,
   6374         .invalid_ampersand_ampersand,
   6375         .mismatched_binary_op_whitespace,
   6376         .mismatched_binary_op_whitespace,
   6377     });
   6378 
   6379     try testError(
   6380         \\ _ = bar & &foo, 
   6381         \\ _ = bar & &&foo, 
   6382         \\ _ = &&foo, 
   6383     , &.{});
   6384 }
   6385 
   6386 var fixed_buffer_mem: [100 * 1024]u8 = undefined;
   6387 
   6388 fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
   6389     var c_tree = c.astParse(source, @intCast(source.len));
   6390     defer c.astDeinit(&c_tree);
   6391     var tree = try zigAst(allocator, c_tree);
   6392     defer tree.deinit(allocator);
   6393 
   6394     // Skip consistency check under valgrind: Zig's tokenizer uses SIMD
   6395     // instructions (AVX-512) that valgrind does not support.
   6396     if (!@import("std").debug.inValgrind()) {
   6397         var zig_tree = try Ast.parse(allocator, source, .zig);
   6398         defer zig_tree.deinit(allocator);
   6399         try expectAstConsistent(tree, zig_tree, source);
   6400     }
   6401 
   6402     if (tree.errors.len != 0) {
   6403         return error.ParseError;
   6404     }
   6405 
   6406     const formatted = try tree.renderAlloc(allocator);
   6407     anything_changed.* = !mem.eql(u8, formatted, source);
   6408     return formatted;
   6409 }
   6410 fn testTransformImpl(allocator: mem.Allocator, fba: *std.heap.FixedBufferAllocator, source: [:0]const u8, expected_source: []const u8) !void {
   6411     // reset the fixed buffer allocator each run so that it can be re-used for each
   6412     // iteration of the failing index
   6413     fba.reset();
   6414     var anything_changed: bool = undefined;
   6415     const result_source = try testParse(source, allocator, &anything_changed);
   6416     try std.testing.expectEqualStrings(expected_source, result_source);
   6417     const changes_expected = source.ptr != expected_source.ptr;
   6418     if (anything_changed != changes_expected) {
   6419         print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
   6420         return error.TestFailed;
   6421     }
   6422     try std.testing.expect(anything_changed == changes_expected);
   6423     allocator.free(result_source);
   6424 }
   6425 fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
   6426     var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
   6427     return std.testing.checkAllAllocationFailures(fixed_allocator.allocator(), testTransformImpl, .{ &fixed_allocator, source, expected_source });
   6428 }
   6429 fn testCanonical(source: [:0]const u8) !void {
   6430     return testTransform(source, source);
   6431 }
   6432 
   6433 const Error = std.zig.Ast.Error.Tag;
   6434 
   6435 fn testError(source: [:0]const u8, expected_errors: []const Error) !void {
   6436     var c_tree = c.astParse(source, @intCast(source.len));
   6437     defer c.astDeinit(&c_tree);
   6438     if (expected_errors.len == 0) {
   6439         try std.testing.expect(!c_tree.has_error);
   6440     } else {
   6441         try std.testing.expect(c_tree.has_error);
   6442     }
   6443 }
   6444 
   6445 // Returns the number of meaningful u32 fields in Node.Data for a given tag.
   6446 // 0 = data is undefined/unused, 1 = only first u32 is meaningful, 2 = both meaningful.
   6447 fn dataFieldCount(tag: Ast.Node.Tag) u2 {
   6448     return switch (tag) {
   6449         // data unused (undefined in Zig parser)
   6450         .identifier,
   6451         .string_literal,
   6452         .char_literal,
   6453         .number_literal,
   6454         .unreachable_literal,
   6455         .anyframe_literal,
   6456         .enum_literal,
   6457         .error_value,
   6458         => 0,
   6459 
   6460         // .node or .opt_node — only first u32
   6461         .@"defer",
   6462         .@"comptime",
   6463         .@"nosuspend",
   6464         .@"suspend",
   6465         .@"resume",
   6466         .bool_not,
   6467         .negation,
   6468         .bit_not,
   6469         .negation_wrap,
   6470         .address_of,
   6471         .@"try",
   6472         .deref,
   6473         .optional_type,
   6474         .@"return",
   6475         => 1,
   6476 
   6477         // everything else — both u32 fields
   6478         else => 2,
   6479     };
   6480 }
   6481 
   6482 fn expectAstConsistent(c_tree: Ast, zig_tree: Ast, source: [:0]const u8) !void {
   6483     _ = source;
   6484 
   6485     if (c_tree.tokens.len != zig_tree.tokens.len) {
   6486         print("token count mismatch: c={d} zig={d}\n", .{ c_tree.tokens.len, zig_tree.tokens.len });
   6487         return error.TestExpectedEqual;
   6488     }
   6489     for (0..c_tree.tokens.len) |i| {
   6490         if (c_tree.tokens.items(.start)[i] != zig_tree.tokens.items(.start)[i]) {
   6491             print("token[{d}] start mismatch: c={d} zig={d}\n", .{ i, c_tree.tokens.items(.start)[i], zig_tree.tokens.items(.start)[i] });
   6492             return error.TestExpectedEqual;
   6493         }
   6494         if (c_tree.tokens.items(.tag)[i] != zig_tree.tokens.items(.tag)[i]) {
   6495             print("token[{d}] tag mismatch: c={s} zig={s}\n", .{ i, @tagName(c_tree.tokens.items(.tag)[i]), @tagName(zig_tree.tokens.items(.tag)[i]) });
   6496             return error.TestExpectedEqual;
   6497         }
   6498     }
   6499 
   6500     if (c_tree.nodes.len != zig_tree.nodes.len) {
   6501         print("node count mismatch: c={d} zig={d}\n", .{ c_tree.nodes.len, zig_tree.nodes.len });
   6502         return error.TestExpectedEqual;
   6503     }
   6504     for (0..c_tree.nodes.len) |i| {
   6505         const c_tag = c_tree.nodes.items(.tag)[i];
   6506         const z_tag = zig_tree.nodes.items(.tag)[i];
   6507         if (c_tag != z_tag) {
   6508             print("node[{d}] tag mismatch: c={s} zig={s}\n", .{ i, @tagName(c_tag), @tagName(z_tag) });
   6509             return error.TestExpectedEqual;
   6510         }
   6511         if (c_tree.nodes.items(.main_token)[i] != zig_tree.nodes.items(.main_token)[i]) {
   6512             print("node[{d}] main_token mismatch: c={d} zig={d}\n", .{ i, c_tree.nodes.items(.main_token)[i], zig_tree.nodes.items(.main_token)[i] });
   6513             return error.TestExpectedEqual;
   6514         }
   6515         const field_count = dataFieldCount(c_tag);
   6516         if (field_count >= 1) {
   6517             const c_data: *const [2]u32 = @ptrCast(&c_tree.nodes.items(.data)[i]);
   6518             const z_data: *const [2]u32 = @ptrCast(&zig_tree.nodes.items(.data)[i]);
   6519             if (c_data[0] != z_data[0]) {
   6520                 print("node[{d}] data[0] mismatch: c={d} zig={d}\n", .{ i, c_data[0], z_data[0] });
   6521                 return error.TestExpectedEqual;
   6522             }
   6523             if (field_count >= 2 and c_data[1] != z_data[1]) {
   6524                 print("node[{d}] data[1] mismatch: c={d} zig={d}\n", .{ i, c_data[1], z_data[1] });
   6525                 return error.TestExpectedEqual;
   6526             }
   6527         }
   6528     }
   6529 
   6530     if (c_tree.extra_data.len != zig_tree.extra_data.len) {
   6531         print("extra_data length mismatch: c={d} zig={d}\n", .{ c_tree.extra_data.len, zig_tree.extra_data.len });
   6532         return error.TestExpectedEqual;
   6533     }
   6534     for (0..c_tree.extra_data.len) |i| {
   6535         if (c_tree.extra_data[i] != zig_tree.extra_data[i]) {
   6536             print("extra_data[{d}] mismatch: c={d} zig={d}\n", .{ i, c_tree.extra_data[i], zig_tree.extra_data[i] });
   6537             return error.TestExpectedEqual;
   6538         }
   6539     }
   6540 }
   6541 
   6542 const testing = std.testing;
   6543 
   6544 const Ast = std.zig.Ast;
   6545 const Allocator = std.mem.Allocator;
   6546 
   6547 const c = @cImport({
   6548     @cInclude("ast.h");
   6549 });
   6550 
   6551 const zigToken = @import("./tokenizer_test.zig").zigToken;
   6552 
   6553 pub fn zigNode(token: c_uint) Ast.Node.Tag {
   6554     return switch (token) {
   6555         c.AST_NODE_ROOT => .root,
   6556         c.AST_NODE_TEST_DECL => .test_decl,
   6557         c.AST_NODE_GLOBAL_VAR_DECL => .global_var_decl,
   6558         c.AST_NODE_LOCAL_VAR_DECL => .local_var_decl,
   6559         c.AST_NODE_SIMPLE_VAR_DECL => .simple_var_decl,
   6560         c.AST_NODE_ALIGNED_VAR_DECL => .aligned_var_decl,
   6561         c.AST_NODE_ERRDEFER => .@"errdefer",
   6562         c.AST_NODE_DEFER => .@"defer",
   6563         c.AST_NODE_CATCH => .@"catch",
   6564         c.AST_NODE_FIELD_ACCESS => .field_access,
   6565         c.AST_NODE_UNWRAP_OPTIONAL => .unwrap_optional,
   6566         c.AST_NODE_EQUAL_EQUAL => .equal_equal,
   6567         c.AST_NODE_BANG_EQUAL => .bang_equal,
   6568         c.AST_NODE_LESS_THAN => .less_than,
   6569         c.AST_NODE_GREATER_THAN => .greater_than,
   6570         c.AST_NODE_LESS_OR_EQUAL => .less_or_equal,
   6571         c.AST_NODE_GREATER_OR_EQUAL => .greater_or_equal,
   6572         c.AST_NODE_ASSIGN_MUL => .assign_mul,
   6573         c.AST_NODE_ASSIGN_DIV => .assign_div,
   6574         c.AST_NODE_ASSIGN_MOD => .assign_mod,
   6575         c.AST_NODE_ASSIGN_ADD => .assign_add,
   6576         c.AST_NODE_ASSIGN_SUB => .assign_sub,
   6577         c.AST_NODE_ASSIGN_SHL => .assign_shl,
   6578         c.AST_NODE_ASSIGN_SHL_SAT => .assign_shl_sat,
   6579         c.AST_NODE_ASSIGN_SHR => .assign_shr,
   6580         c.AST_NODE_ASSIGN_BIT_AND => .assign_bit_and,
   6581         c.AST_NODE_ASSIGN_BIT_XOR => .assign_bit_xor,
   6582         c.AST_NODE_ASSIGN_BIT_OR => .assign_bit_or,
   6583         c.AST_NODE_ASSIGN_MUL_WRAP => .assign_mul_wrap,
   6584         c.AST_NODE_ASSIGN_ADD_WRAP => .assign_add_wrap,
   6585         c.AST_NODE_ASSIGN_SUB_WRAP => .assign_sub_wrap,
   6586         c.AST_NODE_ASSIGN_MUL_SAT => .assign_mul_sat,
   6587         c.AST_NODE_ASSIGN_ADD_SAT => .assign_add_sat,
   6588         c.AST_NODE_ASSIGN_SUB_SAT => .assign_sub_sat,
   6589         c.AST_NODE_ASSIGN => .assign,
   6590         c.AST_NODE_ASSIGN_DESTRUCTURE => .assign_destructure,
   6591         c.AST_NODE_MERGE_ERROR_SETS => .merge_error_sets,
   6592         c.AST_NODE_MUL => .mul,
   6593         c.AST_NODE_DIV => .div,
   6594         c.AST_NODE_MOD => .mod,
   6595         c.AST_NODE_ARRAY_MULT => .array_mult,
   6596         c.AST_NODE_MUL_WRAP => .mul_wrap,
   6597         c.AST_NODE_MUL_SAT => .mul_sat,
   6598         c.AST_NODE_ADD => .add,
   6599         c.AST_NODE_SUB => .sub,
   6600         c.AST_NODE_ARRAY_CAT => .array_cat,
   6601         c.AST_NODE_ADD_WRAP => .add_wrap,
   6602         c.AST_NODE_SUB_WRAP => .sub_wrap,
   6603         c.AST_NODE_ADD_SAT => .add_sat,
   6604         c.AST_NODE_SUB_SAT => .sub_sat,
   6605         c.AST_NODE_SHL => .shl,
   6606         c.AST_NODE_SHL_SAT => .shl_sat,
   6607         c.AST_NODE_SHR => .shr,
   6608         c.AST_NODE_BIT_AND => .bit_and,
   6609         c.AST_NODE_BIT_XOR => .bit_xor,
   6610         c.AST_NODE_BIT_OR => .bit_or,
   6611         c.AST_NODE_ORELSE => .@"orelse",
   6612         c.AST_NODE_BOOL_AND => .bool_and,
   6613         c.AST_NODE_BOOL_OR => .bool_or,
   6614         c.AST_NODE_BOOL_NOT => .bool_not,
   6615         c.AST_NODE_NEGATION => .negation,
   6616         c.AST_NODE_BIT_NOT => .bit_not,
   6617         c.AST_NODE_NEGATION_WRAP => .negation_wrap,
   6618         c.AST_NODE_ADDRESS_OF => .address_of,
   6619         c.AST_NODE_TRY => .@"try",
   6620         c.AST_NODE_OPTIONAL_TYPE => .optional_type,
   6621         c.AST_NODE_ARRAY_TYPE => .array_type,
   6622         c.AST_NODE_ARRAY_TYPE_SENTINEL => .array_type_sentinel,
   6623         c.AST_NODE_PTR_TYPE_ALIGNED => .ptr_type_aligned,
   6624         c.AST_NODE_PTR_TYPE_SENTINEL => .ptr_type_sentinel,
   6625         c.AST_NODE_PTR_TYPE => .ptr_type,
   6626         c.AST_NODE_PTR_TYPE_BIT_RANGE => .ptr_type_bit_range,
   6627         c.AST_NODE_SLICE_OPEN => .slice_open,
   6628         c.AST_NODE_SLICE => .slice,
   6629         c.AST_NODE_SLICE_SENTINEL => .slice_sentinel,
   6630         c.AST_NODE_DEREF => .deref,
   6631         c.AST_NODE_ARRAY_ACCESS => .array_access,
   6632         c.AST_NODE_ARRAY_INIT_ONE => .array_init_one,
   6633         c.AST_NODE_ARRAY_INIT_ONE_COMMA => .array_init_one_comma,
   6634         c.AST_NODE_ARRAY_INIT_DOT_TWO => .array_init_dot_two,
   6635         c.AST_NODE_ARRAY_INIT_DOT_TWO_COMMA => .array_init_dot_two_comma,
   6636         c.AST_NODE_ARRAY_INIT_DOT => .array_init_dot,
   6637         c.AST_NODE_ARRAY_INIT_DOT_COMMA => .array_init_dot_comma,
   6638         c.AST_NODE_ARRAY_INIT => .array_init,
   6639         c.AST_NODE_ARRAY_INIT_COMMA => .array_init_comma,
   6640         c.AST_NODE_STRUCT_INIT_ONE => .struct_init_one,
   6641         c.AST_NODE_STRUCT_INIT_ONE_COMMA => .struct_init_one_comma,
   6642         c.AST_NODE_STRUCT_INIT_DOT_TWO => .struct_init_dot_two,
   6643         c.AST_NODE_STRUCT_INIT_DOT_TWO_COMMA => .struct_init_dot_two_comma,
   6644         c.AST_NODE_STRUCT_INIT_DOT => .struct_init_dot,
   6645         c.AST_NODE_STRUCT_INIT_DOT_COMMA => .struct_init_dot_comma,
   6646         c.AST_NODE_STRUCT_INIT => .struct_init,
   6647         c.AST_NODE_STRUCT_INIT_COMMA => .struct_init_comma,
   6648         c.AST_NODE_CALL_ONE => .call_one,
   6649         c.AST_NODE_CALL_ONE_COMMA => .call_one_comma,
   6650         c.AST_NODE_CALL => .call,
   6651         c.AST_NODE_CALL_COMMA => .call_comma,
   6652         c.AST_NODE_SWITCH => .@"switch",
   6653         c.AST_NODE_SWITCH_COMMA => .switch_comma,
   6654         c.AST_NODE_SWITCH_CASE_ONE => .switch_case_one,
   6655         c.AST_NODE_SWITCH_CASE_INLINE_ONE => .switch_case_inline_one,
   6656         c.AST_NODE_SWITCH_CASE => .switch_case,
   6657         c.AST_NODE_SWITCH_CASE_INLINE => .switch_case_inline,
   6658         c.AST_NODE_SWITCH_RANGE => .switch_range,
   6659         c.AST_NODE_WHILE_SIMPLE => .while_simple,
   6660         c.AST_NODE_WHILE_CONT => .while_cont,
   6661         c.AST_NODE_WHILE => .@"while",
   6662         c.AST_NODE_FOR_SIMPLE => .for_simple,
   6663         c.AST_NODE_FOR => .@"for",
   6664         c.AST_NODE_FOR_RANGE => .for_range,
   6665         c.AST_NODE_IF_SIMPLE => .if_simple,
   6666         c.AST_NODE_IF => .@"if",
   6667         c.AST_NODE_SUSPEND => .@"suspend",
   6668         c.AST_NODE_RESUME => .@"resume",
   6669         c.AST_NODE_CONTINUE => .@"continue",
   6670         c.AST_NODE_BREAK => .@"break",
   6671         c.AST_NODE_RETURN => .@"return",
   6672         c.AST_NODE_FN_PROTO_SIMPLE => .fn_proto_simple,
   6673         c.AST_NODE_FN_PROTO_MULTI => .fn_proto_multi,
   6674         c.AST_NODE_FN_PROTO_ONE => .fn_proto_one,
   6675         c.AST_NODE_FN_PROTO => .fn_proto,
   6676         c.AST_NODE_FN_DECL => .fn_decl,
   6677         c.AST_NODE_ANYFRAME_TYPE => .anyframe_type,
   6678         c.AST_NODE_ANYFRAME_LITERAL => .anyframe_literal,
   6679         c.AST_NODE_CHAR_LITERAL => .char_literal,
   6680         c.AST_NODE_NUMBER_LITERAL => .number_literal,
   6681         c.AST_NODE_UNREACHABLE_LITERAL => .unreachable_literal,
   6682         c.AST_NODE_IDENTIFIER => .identifier,
   6683         c.AST_NODE_ENUM_LITERAL => .enum_literal,
   6684         c.AST_NODE_STRING_LITERAL => .string_literal,
   6685         c.AST_NODE_MULTILINE_STRING_LITERAL => .multiline_string_literal,
   6686         c.AST_NODE_GROUPED_EXPRESSION => .grouped_expression,
   6687         c.AST_NODE_BUILTIN_CALL_TWO => .builtin_call_two,
   6688         c.AST_NODE_BUILTIN_CALL_TWO_COMMA => .builtin_call_two_comma,
   6689         c.AST_NODE_BUILTIN_CALL => .builtin_call,
   6690         c.AST_NODE_BUILTIN_CALL_COMMA => .builtin_call_comma,
   6691         c.AST_NODE_ERROR_SET_DECL => .error_set_decl,
   6692         c.AST_NODE_CONTAINER_DECL => .container_decl,
   6693         c.AST_NODE_CONTAINER_DECL_TRAILING => .container_decl_trailing,
   6694         c.AST_NODE_CONTAINER_DECL_TWO => .container_decl_two,
   6695         c.AST_NODE_CONTAINER_DECL_TWO_TRAILING => .container_decl_two_trailing,
   6696         c.AST_NODE_CONTAINER_DECL_ARG => .container_decl_arg,
   6697         c.AST_NODE_CONTAINER_DECL_ARG_TRAILING => .container_decl_arg_trailing,
   6698         c.AST_NODE_TAGGED_UNION => .tagged_union,
   6699         c.AST_NODE_TAGGED_UNION_TRAILING => .tagged_union_trailing,
   6700         c.AST_NODE_TAGGED_UNION_TWO => .tagged_union_two,
   6701         c.AST_NODE_TAGGED_UNION_TWO_TRAILING => .tagged_union_two_trailing,
   6702         c.AST_NODE_TAGGED_UNION_ENUM_TAG => .tagged_union_enum_tag,
   6703         c.AST_NODE_TAGGED_UNION_ENUM_TAG_TRAILING => .tagged_union_enum_tag_trailing,
   6704         c.AST_NODE_CONTAINER_FIELD_INIT => .container_field_init,
   6705         c.AST_NODE_CONTAINER_FIELD_ALIGN => .container_field_align,
   6706         c.AST_NODE_CONTAINER_FIELD => .container_field,
   6707         c.AST_NODE_COMPTIME => .@"comptime",
   6708         c.AST_NODE_NOSUSPEND => .@"nosuspend",
   6709         c.AST_NODE_BLOCK_TWO => .block_two,
   6710         c.AST_NODE_BLOCK_TWO_SEMICOLON => .block_two_semicolon,
   6711         c.AST_NODE_BLOCK => .block,
   6712         c.AST_NODE_BLOCK_SEMICOLON => .block_semicolon,
   6713         c.AST_NODE_ASM_SIMPLE => .asm_simple,
   6714         c.AST_NODE_ASM_LEGACY => .asm_legacy,
   6715         c.AST_NODE_ASM => .@"asm",
   6716         c.AST_NODE_ASM_OUTPUT => .asm_output,
   6717         c.AST_NODE_ASM_INPUT => .asm_input,
   6718         c.AST_NODE_ERROR_VALUE => .error_value,
   6719         c.AST_NODE_ERROR_UNION => .error_union,
   6720         else => undefined,
   6721     };
   6722 }
   6723 
   6724 fn toIndex(v: u32) Ast.Node.Index {
   6725     return @enumFromInt(v);
   6726 }
   6727 
   6728 fn toOptIndex(v: u32) Ast.Node.OptionalIndex {
   6729     return if (v == 0) .none else @enumFromInt(v);
   6730 }
   6731 
   6732 fn toExtraIndex(v: u32) Ast.ExtraIndex {
   6733     return @enumFromInt(v);
   6734 }
   6735 
   6736 fn toOptTokenIndex(v: u32) Ast.OptionalTokenIndex {
   6737     return @enumFromInt(v);
   6738 }
   6739 
   6740 fn zigData(tag: Ast.Node.Tag, lhs: u32, rhs: u32) Ast.Node.Data {
   6741     return switch (tag) {
   6742         // data unused
   6743         .identifier,
   6744         .string_literal,
   6745         .char_literal,
   6746         .number_literal,
   6747         .unreachable_literal,
   6748         .anyframe_literal,
   6749         .enum_literal,
   6750         .error_value,
   6751         => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
   6752 
   6753         // .node (single node index)
   6754         .@"defer",
   6755         .@"comptime",
   6756         .@"nosuspend",
   6757         .@"suspend",
   6758         .@"resume",
   6759         .bool_not,
   6760         .negation,
   6761         .bit_not,
   6762         .negation_wrap,
   6763         .address_of,
   6764         .@"try",
   6765         .deref,
   6766         .optional_type,
   6767         => .{ .node = toIndex(lhs) },
   6768 
   6769         // .opt_node (single optional node)
   6770         .@"return",
   6771         => .{ .opt_node = toOptIndex(lhs) },
   6772 
   6773         // .node_and_node
   6774         .fn_decl,
   6775         .container_field_align,
   6776         .error_union,
   6777         .@"catch",
   6778         .equal_equal,
   6779         .bang_equal,
   6780         .less_than,
   6781         .greater_than,
   6782         .less_or_equal,
   6783         .greater_or_equal,
   6784         .assign_mul,
   6785         .assign_div,
   6786         .assign_mod,
   6787         .assign_add,
   6788         .assign_sub,
   6789         .assign_shl,
   6790         .assign_shl_sat,
   6791         .assign_shr,
   6792         .assign_bit_and,
   6793         .assign_bit_xor,
   6794         .assign_bit_or,
   6795         .assign_mul_wrap,
   6796         .assign_add_wrap,
   6797         .assign_sub_wrap,
   6798         .assign_mul_sat,
   6799         .assign_add_sat,
   6800         .assign_sub_sat,
   6801         .assign,
   6802         .merge_error_sets,
   6803         .mul,
   6804         .div,
   6805         .mod,
   6806         .array_mult,
   6807         .mul_wrap,
   6808         .mul_sat,
   6809         .add,
   6810         .sub,
   6811         .array_cat,
   6812         .add_wrap,
   6813         .sub_wrap,
   6814         .add_sat,
   6815         .sub_sat,
   6816         .shl,
   6817         .shl_sat,
   6818         .shr,
   6819         .bit_and,
   6820         .bit_xor,
   6821         .bit_or,
   6822         .@"orelse",
   6823         .bool_and,
   6824         .bool_or,
   6825         .array_type,
   6826         .array_access,
   6827         .switch_range,
   6828         => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
   6829 
   6830         // .opt_node_and_opt_node
   6831         .fn_proto_simple,
   6832         .simple_var_decl,
   6833         .block_two,
   6834         .block_two_semicolon,
   6835         .builtin_call_two,
   6836         .builtin_call_two_comma,
   6837         .container_decl_two,
   6838         .container_decl_two_trailing,
   6839         .tagged_union_two,
   6840         .tagged_union_two_trailing,
   6841         .struct_init_dot_two,
   6842         .struct_init_dot_two_comma,
   6843         .array_init_dot_two,
   6844         .array_init_dot_two_comma,
   6845         => .{ .opt_node_and_opt_node = .{ toOptIndex(lhs), toOptIndex(rhs) } },
   6846 
   6847         // .node_and_opt_node
   6848         .call_one,
   6849         .call_one_comma,
   6850         .struct_init_one,
   6851         .struct_init_one_comma,
   6852         .container_field_init,
   6853         .aligned_var_decl,
   6854         => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
   6855 
   6856         // .node_and_node (array_init_one uses node_and_node, not
   6857         // node_and_opt_node)
   6858         .array_init_one,
   6859         .array_init_one_comma,
   6860         => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
   6861 
   6862         // .opt_node_and_node
   6863         .ptr_type_aligned,
   6864         .ptr_type_sentinel,
   6865         .switch_case_one,
   6866         .switch_case_inline_one,
   6867         => .{ .opt_node_and_node = .{ toOptIndex(lhs), toIndex(rhs) } },
   6868 
   6869         // .node_and_extra
   6870         .call,
   6871         .call_comma,
   6872         .container_field,
   6873         .array_type_sentinel,
   6874         .slice,
   6875         .slice_sentinel,
   6876         .array_init,
   6877         .array_init_comma,
   6878         .struct_init,
   6879         .struct_init_comma,
   6880         .@"switch",
   6881         .switch_comma,
   6882         .container_decl_arg,
   6883         .container_decl_arg_trailing,
   6884         .tagged_union_enum_tag,
   6885         .tagged_union_enum_tag_trailing,
   6886         .@"asm",
   6887         => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
   6888 
   6889         // .extra_and_node
   6890         .assign_destructure,
   6891         .switch_case,
   6892         .switch_case_inline,
   6893         .ptr_type,
   6894         .ptr_type_bit_range,
   6895         => .{ .extra_and_node = .{ toExtraIndex(lhs), toIndex(rhs) } },
   6896 
   6897         // .extra_and_opt_node
   6898         .global_var_decl,
   6899         .local_var_decl,
   6900         .fn_proto_multi,
   6901         .fn_proto_one,
   6902         .fn_proto,
   6903         => .{ .extra_and_opt_node = .{ toExtraIndex(lhs), toOptIndex(rhs) } },
   6904 
   6905         // .extra_range (SubRange)
   6906         .root,
   6907         .block,
   6908         .block_semicolon,
   6909         .builtin_call,
   6910         .builtin_call_comma,
   6911         .container_decl,
   6912         .container_decl_trailing,
   6913         .tagged_union,
   6914         .tagged_union_trailing,
   6915         .array_init_dot,
   6916         .array_init_dot_comma,
   6917         .struct_init_dot,
   6918         .struct_init_dot_comma,
   6919         => .{ .extra_range = .{ .start = toExtraIndex(lhs), .end = toExtraIndex(rhs) } },
   6920 
   6921         // .node_and_token
   6922         .grouped_expression,
   6923         .asm_input,
   6924         .asm_simple,
   6925         .field_access,
   6926         .unwrap_optional,
   6927         => .{ .node_and_token = .{ toIndex(lhs), rhs } },
   6928 
   6929         // .opt_node_and_token
   6930         .asm_output,
   6931         => .{ .opt_node_and_token = .{ toOptIndex(lhs), rhs } },
   6932 
   6933         // .opt_token_and_node
   6934         .test_decl,
   6935         .@"errdefer",
   6936         => .{ .opt_token_and_node = .{ toOptTokenIndex(lhs), toIndex(rhs) } },
   6937 
   6938         // .opt_token_and_opt_node
   6939         .@"break",
   6940         .@"continue",
   6941         => .{ .opt_token_and_opt_node = .{ toOptTokenIndex(lhs), toOptIndex(rhs) } },
   6942 
   6943         // .token_and_token
   6944         .error_set_decl,
   6945         .multiline_string_literal,
   6946         => .{ .token_and_token = .{ lhs, rhs } },
   6947 
   6948         // .token_and_node
   6949         .anyframe_type,
   6950         => .{ .token_and_node = .{ lhs, toIndex(rhs) } },
   6951 
   6952         // .node_and_node for slice_open (lhs[rhs..])
   6953         .slice_open,
   6954         => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
   6955 
   6956         .while_simple,
   6957         .for_simple,
   6958         .if_simple,
   6959         => .{ .node_and_node = .{ toIndex(lhs), toIndex(rhs) } },
   6960 
   6961         .while_cont,
   6962         .@"while",
   6963         .@"if",
   6964         => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
   6965 
   6966         .for_range,
   6967         => .{ .node_and_opt_node = .{ toIndex(lhs), toOptIndex(rhs) } },
   6968 
   6969         .@"for",
   6970         => .{ .@"for" = .{ toExtraIndex(lhs), @bitCast(rhs) } },
   6971 
   6972         .asm_legacy,
   6973         => .{ .node_and_extra = .{ toIndex(lhs), toExtraIndex(rhs) } },
   6974     };
   6975 }
   6976 
   6977 // zigAst converts a c.Ast to std.Zig.Ast. The resulting Ast should be freed with deinit().
   6978 pub fn zigAst(gpa: Allocator, c_ast: c.Ast) !Ast {
   6979     var tokens = Ast.TokenList{};
   6980     try tokens.resize(gpa, c_ast.tokens.len);
   6981     errdefer tokens.deinit(gpa);
   6982 
   6983     for (0..c_ast.tokens.len) |i|
   6984         tokens.set(i, .{
   6985             .tag = zigToken(c_ast.tokens.tags[i]),
   6986             .start = c_ast.tokens.starts[i],
   6987         });
   6988 
   6989     var nodes = Ast.NodeList{};
   6990     try nodes.resize(gpa, c_ast.nodes.len);
   6991     errdefer nodes.deinit(gpa);
   6992 
   6993     for (0..c_ast.nodes.len) |i| {
   6994         const tag = zigNode(c_ast.nodes.tags[i]);
   6995         nodes.set(i, .{
   6996             .tag = tag,
   6997             .main_token = c_ast.nodes.main_tokens[i],
   6998             .data = zigData(tag, c_ast.nodes.datas[i].lhs, c_ast.nodes.datas[i].rhs),
   6999         });
   7000     }
   7001 
   7002     const extra_data = try gpa.alloc(u32, c_ast.extra_data.len);
   7003     errdefer gpa.free(extra_data);
   7004     @memcpy(extra_data, c_ast.extra_data.arr[0..c_ast.extra_data.len]);
   7005 
   7006     const errors = if (c_ast.has_error) blk: {
   7007         const errs = try gpa.alloc(Ast.Error, 1);
   7008         errs[0] = .{ .tag = .expected_token, .token = 0, .extra = .{ .none = {} } };
   7009         break :blk errs;
   7010     } else try gpa.alloc(Ast.Error, 0);
   7011     errdefer gpa.free(errors);
   7012 
   7013     return Ast{
   7014         .source = c_ast.source[0..c_ast.source_len :0],
   7015         .mode = .zig,
   7016         .tokens = tokens.slice(),
   7017         .nodes = nodes.slice(),
   7018         .extra_data = extra_data,
   7019         .errors = errors,
   7020     };
   7021 }