zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 9bf7ae8d (129298B) - Raw


      1 test "zig fmt: preserves clobbers in inline asm with stray comma" {
      2     try testCanonical(
      3         \\fn foo() void {
      4         \\    asm volatile (""
      5         \\        : [_] "" (-> type),
      6         \\        :
      7         \\        : "clobber"
      8         \\    );
      9         \\    asm volatile (""
     10         \\        :
     11         \\        : [_] "" (type),
     12         \\        : "clobber"
     13         \\    );
     14         \\}
     15         \\
     16     );
     17 }
     18 
     19 test "zig fmt: respect line breaks in struct field value declaration" {
     20     try testCanonical(
     21         \\const Foo = struct {
     22         \\    bar: u32 =
     23         \\        42,
     24         \\    bar: u32 =
     25         \\        // a comment
     26         \\        42,
     27         \\    bar: u32 =
     28         \\        42,
     29         \\    // a comment
     30         \\    bar: []const u8 =
     31         \\        \\ foo
     32         \\        \\ bar
     33         \\        \\ baz
     34         \\    ,
     35         \\    bar: u32 =
     36         \\        blk: {
     37         \\            break :blk 42;
     38         \\        },
     39         \\};
     40         \\
     41     );
     42 }
     43 
     44 test "zig fmt: respect line breaks before functions" {
     45     try testCanonical(
     46         \\const std = @import("std");
     47         \\
     48         \\inline fn foo() void {}
     49         \\
     50         \\noinline fn foo() void {}
     51         \\
     52         \\export fn foo() void {}
     53         \\
     54         \\extern fn foo() void;
     55         \\
     56         \\extern "foo" fn foo() void;
     57         \\
     58     );
     59 }
     60 
     61 test "zig fmt: rewrite callconv(.Inline) to the inline keyword" {
     62     try testTransform(
     63         \\fn foo() callconv(.Inline) void {}
     64         \\const bar = .Inline;
     65         \\fn foo() callconv(bar) void {}
     66         \\
     67     ,
     68         \\inline fn foo() void {}
     69         \\const bar = .Inline;
     70         \\fn foo() callconv(bar) void {}
     71         \\
     72     );
     73 }
     74 
     75 // TODO Remove this after zig 0.10.0 is released.
     76 test "zig fmt: rewrite c_void to anyopaque" {
     77     try testTransform(
     78         \\const Foo = struct {
     79         \\    c_void: *c_void,
     80         \\};
     81         \\
     82         \\fn foo(a: ?*c_void) !*c_void {
     83         \\    return a orelse unreachable;
     84         \\}
     85         \\
     86     ,
     87         \\const Foo = struct {
     88         \\    c_void: *anyopaque,
     89         \\};
     90         \\
     91         \\fn foo(a: ?*anyopaque) !*anyopaque {
     92         \\    return a orelse unreachable;
     93         \\}
     94         \\
     95     );
     96 }
     97 
     98 test "zig fmt: simple top level comptime block" {
     99     try testCanonical(
    100         \\// line comment
    101         \\comptime {}
    102         \\
    103     );
    104 }
    105 
    106 test "zig fmt: two spaced line comments before decl" {
    107     try testCanonical(
    108         \\// line comment
    109         \\
    110         \\// another
    111         \\comptime {}
    112         \\
    113     );
    114 }
    115 
    116 test "zig fmt: respect line breaks after var declarations" {
    117     try testCanonical(
    118         \\const crc =
    119         \\    lookup_tables[0][p[7]] ^
    120         \\    lookup_tables[1][p[6]] ^
    121         \\    lookup_tables[2][p[5]] ^
    122         \\    lookup_tables[3][p[4]] ^
    123         \\    lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
    124         \\    lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
    125         \\    lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
    126         \\    lookup_tables[7][@truncate(u8, self.crc >> 0)];
    127         \\
    128     );
    129 }
    130 
    131 test "zig fmt: multiline string mixed with comments" {
    132     try testCanonical(
    133         \\const s1 =
    134         \\    //\\one
    135         \\    \\two)
    136         \\    \\three
    137         \\;
    138         \\const s2 =
    139         \\    \\one
    140         \\    \\two)
    141         \\    //\\three
    142         \\;
    143         \\const s3 =
    144         \\    \\one
    145         \\    //\\two)
    146         \\    \\three
    147         \\;
    148         \\const s4 =
    149         \\    \\one
    150         \\    //\\two
    151         \\    \\three
    152         \\    //\\four
    153         \\    \\five
    154         \\;
    155         \\const a =
    156         \\    1;
    157         \\
    158     );
    159 }
    160 
    161 test "zig fmt: empty file" {
    162     try testCanonical(
    163         \\
    164     );
    165 }
    166 
    167 test "zig fmt: file ends in comment" {
    168     try testTransform(
    169         \\     //foobar
    170     ,
    171         \\//foobar
    172         \\
    173     );
    174 }
    175 
    176 test "zig fmt: file ends in comment after var decl" {
    177     try testTransform(
    178         \\const x = 42;
    179         \\     //foobar
    180     ,
    181         \\const x = 42;
    182         \\//foobar
    183         \\
    184     );
    185 }
    186 
    187 test "zig fmt: doc comments on test" {
    188     try testCanonical(
    189         \\/// hello
    190         \\/// world
    191         \\test "" {}
    192         \\
    193     );
    194 }
    195 
    196 test "zig fmt: if statment" {
    197     try testCanonical(
    198         \\test "" {
    199         \\    if (optional()) |some|
    200         \\        bar = some.foo();
    201         \\}
    202         \\
    203     );
    204 }
    205 
    206 test "zig fmt: top-level fields" {
    207     try testCanonical(
    208         \\a: did_you_know,
    209         \\b: all_files_are,
    210         \\structs: ?x,
    211         \\
    212     );
    213 }
    214 
    215 test "zig fmt: decl between fields" {
    216     try testError(
    217         \\const S = struct {
    218         \\    const foo = 2;
    219         \\    const bar = 2;
    220         \\    const baz = 2;
    221         \\    a: usize,
    222         \\    const foo1 = 2;
    223         \\    const bar1 = 2;
    224         \\    const baz1 = 2;
    225         \\    b: usize,
    226         \\};
    227     , &[_]Error{
    228         .decl_between_fields,
    229     });
    230 }
    231 
    232 test "zig fmt: eof after missing comma" {
    233     try testError(
    234         \\foo()
    235     , &[_]Error{
    236         .expected_comma_after_field,
    237     });
    238 }
    239 
    240 test "zig fmt: errdefer with payload" {
    241     try testCanonical(
    242         \\pub fn main() anyerror!void {
    243         \\    errdefer |a| x += 1;
    244         \\    errdefer |a| {}
    245         \\    errdefer |a| {
    246         \\        x += 1;
    247         \\    }
    248         \\}
    249         \\
    250     );
    251 }
    252 
    253 test "zig fmt: nosuspend block" {
    254     try testCanonical(
    255         \\pub fn main() anyerror!void {
    256         \\    nosuspend {
    257         \\        var foo: Foo = .{ .bar = 42 };
    258         \\    }
    259         \\}
    260         \\
    261     );
    262 }
    263 
    264 test "zig fmt: nosuspend await" {
    265     try testCanonical(
    266         \\fn foo() void {
    267         \\    x = nosuspend await y;
    268         \\}
    269         \\
    270     );
    271 }
    272 
    273 test "zig fmt: container declaration, single line" {
    274     try testCanonical(
    275         \\const X = struct { foo: i32 };
    276         \\const X = struct { foo: i32, bar: i32 };
    277         \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
    278         \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
    279         \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
    280         \\
    281     );
    282 }
    283 
    284 test "zig fmt: container declaration, one item, multi line trailing comma" {
    285     try testCanonical(
    286         \\test "" {
    287         \\    comptime {
    288         \\        const X = struct {
    289         \\            x: i32,
    290         \\        };
    291         \\    }
    292         \\}
    293         \\
    294     );
    295 }
    296 
    297 test "zig fmt: container declaration, no trailing comma on separate line" {
    298     try testTransform(
    299         \\test "" {
    300         \\    comptime {
    301         \\        const X = struct {
    302         \\            x: i32
    303         \\        };
    304         \\    }
    305         \\}
    306         \\
    307     ,
    308         \\test "" {
    309         \\    comptime {
    310         \\        const X = struct { x: i32 };
    311         \\    }
    312         \\}
    313         \\
    314     );
    315 }
    316 
    317 test "zig fmt: container declaration, line break, no trailing comma" {
    318     try testTransform(
    319         \\const X = struct {
    320         \\    foo: i32, bar: i8 };
    321     ,
    322         \\const X = struct { foo: i32, bar: i8 };
    323         \\
    324     );
    325 }
    326 
    327 test "zig fmt: container declaration, transform trailing comma" {
    328     try testTransform(
    329         \\const X = struct {
    330         \\    foo: i32, bar: i8, };
    331     ,
    332         \\const X = struct {
    333         \\    foo: i32,
    334         \\    bar: i8,
    335         \\};
    336         \\
    337     );
    338 }
    339 
    340 test "zig fmt: container declaration, comment, add trailing comma" {
    341     try testTransform(
    342         \\const X = struct {
    343         \\    foo: i32, // foo
    344         \\    bar: i8
    345         \\};
    346     ,
    347         \\const X = struct {
    348         \\    foo: i32, // foo
    349         \\    bar: i8,
    350         \\};
    351         \\
    352     );
    353     try testTransform(
    354         \\const X = struct {
    355         \\    foo: i32 // foo
    356         \\};
    357     ,
    358         \\const X = struct {
    359         \\    foo: i32, // foo
    360         \\};
    361         \\
    362     );
    363 }
    364 
    365 test "zig fmt: container declaration, multiline string, add trailing comma" {
    366     try testTransform(
    367         \\const X = struct {
    368         \\    foo: []const u8 =
    369         \\        \\ foo
    370         \\    ,
    371         \\    bar: i8
    372         \\};
    373     ,
    374         \\const X = struct {
    375         \\    foo: []const u8 =
    376         \\        \\ foo
    377         \\    ,
    378         \\    bar: i8,
    379         \\};
    380         \\
    381     );
    382 }
    383 
    384 test "zig fmt: container declaration, doc comment on member, add trailing comma" {
    385     try testTransform(
    386         \\pub const Pos = struct {
    387         \\    /// X-axis.
    388         \\    x: u32,
    389         \\    /// Y-axis.
    390         \\    y: u32
    391         \\};
    392     ,
    393         \\pub const Pos = struct {
    394         \\    /// X-axis.
    395         \\    x: u32,
    396         \\    /// Y-axis.
    397         \\    y: u32,
    398         \\};
    399         \\
    400     );
    401 }
    402 
    403 test "zig fmt: remove empty lines at start/end of container decl" {
    404     try testTransform(
    405         \\const X = struct {
    406         \\
    407         \\    foo: i32,
    408         \\
    409         \\    bar: i8,
    410         \\
    411         \\};
    412         \\
    413     ,
    414         \\const X = struct {
    415         \\    foo: i32,
    416         \\
    417         \\    bar: i8,
    418         \\};
    419         \\
    420     );
    421 }
    422 
    423 test "zig fmt: remove empty lines at start/end of block" {
    424     try testTransform(
    425         \\test {
    426         \\
    427         \\    if (foo) {
    428         \\        foo();
    429         \\    }
    430         \\
    431         \\}
    432         \\
    433     ,
    434         \\test {
    435         \\    if (foo) {
    436         \\        foo();
    437         \\    }
    438         \\}
    439         \\
    440     );
    441 }
    442 
    443 test "zig fmt: allow empty line before commment at start of block" {
    444     try testCanonical(
    445         \\test {
    446         \\
    447         \\    // foo
    448         \\    const x = 42;
    449         \\}
    450         \\
    451     );
    452 }
    453 
    454 test "zig fmt: allow empty line before commment at start of block" {
    455     try testCanonical(
    456         \\test {
    457         \\
    458         \\    // foo
    459         \\    const x = 42;
    460         \\}
    461         \\
    462     );
    463 }
    464 
    465 test "zig fmt: trailing comma in fn parameter list" {
    466     try testCanonical(
    467         \\pub fn f(
    468         \\    a: i32,
    469         \\    b: i32,
    470         \\) i32 {}
    471         \\pub fn f(
    472         \\    a: i32,
    473         \\    b: i32,
    474         \\) align(8) i32 {}
    475         \\pub fn f(
    476         \\    a: i32,
    477         \\    b: i32,
    478         \\) addrspace(.generic) i32 {}
    479         \\pub fn f(
    480         \\    a: i32,
    481         \\    b: i32,
    482         \\) linksection(".text") i32 {}
    483         \\pub fn f(
    484         \\    a: i32,
    485         \\    b: i32,
    486         \\) callconv(.C) i32 {}
    487         \\pub fn f(
    488         \\    a: i32,
    489         \\    b: i32,
    490         \\) align(8) linksection(".text") i32 {}
    491         \\pub fn f(
    492         \\    a: i32,
    493         \\    b: i32,
    494         \\) align(8) callconv(.C) i32 {}
    495         \\pub fn f(
    496         \\    a: i32,
    497         \\    b: i32,
    498         \\) align(8) linksection(".text") callconv(.C) i32 {}
    499         \\pub fn f(
    500         \\    a: i32,
    501         \\    b: i32,
    502         \\) linksection(".text") callconv(.C) i32 {}
    503         \\
    504     );
    505 }
    506 
    507 test "zig fmt: comptime struct field" {
    508     try testCanonical(
    509         \\const Foo = struct {
    510         \\    a: i32,
    511         \\    comptime b: i32 = 1234,
    512         \\};
    513         \\
    514     );
    515 }
    516 
    517 test "zig fmt: break from block" {
    518     try testCanonical(
    519         \\const a = blk: {
    520         \\    break :blk 42;
    521         \\};
    522         \\const b = blk: {
    523         \\    break :blk;
    524         \\};
    525         \\const c = {
    526         \\    break 42;
    527         \\};
    528         \\const d = {
    529         \\    break;
    530         \\};
    531         \\
    532     );
    533 }
    534 
    535 test "zig fmt: grouped expressions (parentheses)" {
    536     try testCanonical(
    537         \\const r = (x + y) * (a + b);
    538         \\
    539     );
    540 }
    541 
    542 test "zig fmt: c pointer type" {
    543     try testCanonical(
    544         \\pub extern fn repro() [*c]const u8;
    545         \\
    546     );
    547 }
    548 
    549 test "zig fmt: builtin call with trailing comma" {
    550     try testCanonical(
    551         \\pub fn main() void {
    552         \\    @breakpoint();
    553         \\    _ = @boolToInt(a);
    554         \\    _ = @call(
    555         \\        a,
    556         \\        b,
    557         \\        c,
    558         \\    );
    559         \\}
    560         \\
    561     );
    562 }
    563 
    564 test "zig fmt: asm expression with comptime content" {
    565     try testCanonical(
    566         \\comptime {
    567         \\    asm ("foo" ++ "bar");
    568         \\}
    569         \\pub fn main() void {
    570         \\    asm volatile ("foo" ++ "bar");
    571         \\    asm volatile ("foo" ++ "bar"
    572         \\        : [_] "" (x),
    573         \\    );
    574         \\    asm volatile ("foo" ++ "bar"
    575         \\        : [_] "" (x),
    576         \\        : [_] "" (y),
    577         \\    );
    578         \\    asm volatile ("foo" ++ "bar"
    579         \\        : [_] "" (x),
    580         \\        : [_] "" (y),
    581         \\        : "h", "e", "l", "l", "o"
    582         \\    );
    583         \\}
    584         \\
    585     );
    586 }
    587 
    588 test "zig fmt: array types last token" {
    589     try testCanonical(
    590         \\test {
    591         \\    const x = [40]u32;
    592         \\}
    593         \\
    594         \\test {
    595         \\    const x = [40:0]u32;
    596         \\}
    597         \\
    598     );
    599 }
    600 
    601 test "zig fmt: sentinel-terminated array type" {
    602     try testCanonical(
    603         \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
    604         \\    return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
    605         \\}
    606         \\
    607     );
    608 }
    609 
    610 test "zig fmt: sentinel-terminated slice type" {
    611     try testCanonical(
    612         \\pub fn toSlice(self: Buffer) [:0]u8 {
    613         \\    return self.list.toSlice()[0..self.len()];
    614         \\}
    615         \\
    616     );
    617 }
    618 
    619 test "zig fmt: pointer-to-one with modifiers" {
    620     try testCanonical(
    621         \\const x: *u32 = undefined;
    622         \\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    623         \\const z: *allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    624         \\
    625     );
    626 }
    627 
    628 test "zig fmt: pointer-to-many with modifiers" {
    629     try testCanonical(
    630         \\const x: [*]u32 = undefined;
    631         \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    632         \\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    633         \\
    634     );
    635 }
    636 
    637 test "zig fmt: sentinel pointer with modifiers" {
    638     try testCanonical(
    639         \\const x: [*:42]u32 = undefined;
    640         \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    641         \\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    642         \\
    643     );
    644 }
    645 
    646 test "zig fmt: c pointer with modifiers" {
    647     try testCanonical(
    648         \\const x: [*c]u32 = undefined;
    649         \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    650         \\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
    651         \\
    652     );
    653 }
    654 
    655 test "zig fmt: slice with modifiers" {
    656     try testCanonical(
    657         \\const x: []u32 = undefined;
    658         \\const y: []allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    659         \\
    660     );
    661 }
    662 
    663 test "zig fmt: sentinel slice with modifiers" {
    664     try testCanonical(
    665         \\const x: [:42]u32 = undefined;
    666         \\const y: [:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
    667         \\
    668     );
    669 }
    670 
    671 test "zig fmt: anon literal in array" {
    672     try testCanonical(
    673         \\var arr: [2]Foo = .{
    674         \\    .{ .a = 2 },
    675         \\    .{ .b = 3 },
    676         \\};
    677         \\
    678     );
    679 }
    680 
    681 test "zig fmt: alignment in anonymous literal" {
    682     try testTransform(
    683         \\const a = .{
    684         \\    "U",     "L",     "F",
    685         \\    "U'",
    686         \\    "L'",
    687         \\    "F'",
    688         \\};
    689         \\
    690     ,
    691         \\const a = .{
    692         \\    "U",  "L",  "F",
    693         \\    "U'", "L'", "F'",
    694         \\};
    695         \\
    696     );
    697 }
    698 
    699 test "zig fmt: anon struct literal 0 element" {
    700     try testCanonical(
    701         \\test {
    702         \\    const x = .{};
    703         \\}
    704         \\
    705     );
    706 }
    707 
    708 test "zig fmt: anon struct literal 1 element" {
    709     try testCanonical(
    710         \\test {
    711         \\    const x = .{ .a = b };
    712         \\}
    713         \\
    714     );
    715 }
    716 
    717 test "zig fmt: anon struct literal 1 element comma" {
    718     try testCanonical(
    719         \\test {
    720         \\    const x = .{
    721         \\        .a = b,
    722         \\    };
    723         \\}
    724         \\
    725     );
    726 }
    727 
    728 test "zig fmt: anon struct literal 2 element" {
    729     try testCanonical(
    730         \\test {
    731         \\    const x = .{ .a = b, .c = d };
    732         \\}
    733         \\
    734     );
    735 }
    736 
    737 test "zig fmt: anon struct literal 2 element comma" {
    738     try testCanonical(
    739         \\test {
    740         \\    const x = .{
    741         \\        .a = b,
    742         \\        .c = d,
    743         \\    };
    744         \\}
    745         \\
    746     );
    747 }
    748 
    749 test "zig fmt: anon struct literal 3 element" {
    750     try testCanonical(
    751         \\test {
    752         \\    const x = .{ .a = b, .c = d, .e = f };
    753         \\}
    754         \\
    755     );
    756 }
    757 
    758 test "zig fmt: anon struct literal 3 element comma" {
    759     try testCanonical(
    760         \\test {
    761         \\    const x = .{
    762         \\        .a = b,
    763         \\        .c = d,
    764         \\        .e = f,
    765         \\    };
    766         \\}
    767         \\
    768     );
    769 }
    770 
    771 test "zig fmt: struct literal 0 element" {
    772     try testCanonical(
    773         \\test {
    774         \\    const x = X{};
    775         \\}
    776         \\
    777     );
    778 }
    779 
    780 test "zig fmt: struct literal 1 element" {
    781     try testCanonical(
    782         \\test {
    783         \\    const x = X{ .a = b };
    784         \\}
    785         \\
    786     );
    787 }
    788 
    789 test "zig fmt: Unicode code point literal larger than u8" {
    790     try testCanonical(
    791         \\test {
    792         \\    const x = X{
    793         \\        .a = b,
    794         \\    };
    795         \\}
    796         \\
    797     );
    798 }
    799 
    800 test "zig fmt: struct literal 2 element" {
    801     try testCanonical(
    802         \\test {
    803         \\    const x = X{ .a = b, .c = d };
    804         \\}
    805         \\
    806     );
    807 }
    808 
    809 test "zig fmt: struct literal 2 element comma" {
    810     try testCanonical(
    811         \\test {
    812         \\    const x = X{
    813         \\        .a = b,
    814         \\        .c = d,
    815         \\    };
    816         \\}
    817         \\
    818     );
    819 }
    820 
    821 test "zig fmt: struct literal 3 element" {
    822     try testCanonical(
    823         \\test {
    824         \\    const x = X{ .a = b, .c = d, .e = f };
    825         \\}
    826         \\
    827     );
    828 }
    829 
    830 test "zig fmt: struct literal 3 element comma" {
    831     try testCanonical(
    832         \\test {
    833         \\    const x = X{
    834         \\        .a = b,
    835         \\        .c = d,
    836         \\        .e = f,
    837         \\    };
    838         \\}
    839         \\
    840     );
    841 }
    842 
    843 test "zig fmt: anon list literal 1 element" {
    844     try testCanonical(
    845         \\test {
    846         \\    const x = .{a};
    847         \\}
    848         \\
    849     );
    850 }
    851 
    852 test "zig fmt: anon list literal 1 element comma" {
    853     try testCanonical(
    854         \\test {
    855         \\    const x = .{
    856         \\        a,
    857         \\    };
    858         \\}
    859         \\
    860     );
    861 }
    862 
    863 test "zig fmt: anon list literal 2 element" {
    864     try testCanonical(
    865         \\test {
    866         \\    const x = .{ a, b };
    867         \\}
    868         \\
    869     );
    870 }
    871 
    872 test "zig fmt: anon list literal 2 element comma" {
    873     try testCanonical(
    874         \\test {
    875         \\    const x = .{
    876         \\        a,
    877         \\        b,
    878         \\    };
    879         \\}
    880         \\
    881     );
    882 }
    883 
    884 test "zig fmt: anon list literal 3 element" {
    885     try testCanonical(
    886         \\test {
    887         \\    const x = .{ a, b, c };
    888         \\}
    889         \\
    890     );
    891 }
    892 
    893 test "zig fmt: anon list literal 3 element comma" {
    894     try testCanonical(
    895         \\test {
    896         \\    const x = .{
    897         \\        a,
    898         \\        // foo
    899         \\        b,
    900         \\
    901         \\        c,
    902         \\    };
    903         \\}
    904         \\
    905     );
    906 }
    907 
    908 test "zig fmt: array literal 0 element" {
    909     try testCanonical(
    910         \\test {
    911         \\    const x = [_]u32{};
    912         \\}
    913         \\
    914     );
    915 }
    916 
    917 test "zig fmt: array literal 1 element" {
    918     try testCanonical(
    919         \\test {
    920         \\    const x = [_]u32{a};
    921         \\}
    922         \\
    923     );
    924 }
    925 
    926 test "zig fmt: array literal 1 element comma" {
    927     try testCanonical(
    928         \\test {
    929         \\    const x = [1]u32{
    930         \\        a,
    931         \\    };
    932         \\}
    933         \\
    934     );
    935 }
    936 
    937 test "zig fmt: array literal 2 element" {
    938     try testCanonical(
    939         \\test {
    940         \\    const x = [_]u32{ a, b };
    941         \\}
    942         \\
    943     );
    944 }
    945 
    946 test "zig fmt: array literal 2 element comma" {
    947     try testCanonical(
    948         \\test {
    949         \\    const x = [2]u32{
    950         \\        a,
    951         \\        b,
    952         \\    };
    953         \\}
    954         \\
    955     );
    956 }
    957 
    958 test "zig fmt: array literal 3 element" {
    959     try testCanonical(
    960         \\test {
    961         \\    const x = [_]u32{ a, b, c };
    962         \\}
    963         \\
    964     );
    965 }
    966 
    967 test "zig fmt: array literal 3 element comma" {
    968     try testCanonical(
    969         \\test {
    970         \\    const x = [3]u32{
    971         \\        a,
    972         \\        b,
    973         \\        c,
    974         \\    };
    975         \\}
    976         \\
    977     );
    978 }
    979 
    980 test "zig fmt: sentinel array literal 1 element" {
    981     try testCanonical(
    982         \\test {
    983         \\    const x = [_:9000]u32{a};
    984         \\}
    985         \\
    986     );
    987 }
    988 
    989 test "zig fmt: slices" {
    990     try testCanonical(
    991         \\const a = b[0..];
    992         \\const c = d[0..1];
    993         \\const d = f[0.. :0];
    994         \\const e = f[0..1 :0];
    995         \\
    996     );
    997 }
    998 
    999 test "zig fmt: slices with spaces in bounds" {
   1000     try testCanonical(
   1001         \\const a = b[0 + 0 ..];
   1002         \\const c = d[0 + 0 .. 1];
   1003         \\const c = d[0 + 0 .. :0];
   1004         \\const e = f[0 .. 1 + 1 :0];
   1005         \\
   1006     );
   1007 }
   1008 
   1009 test "zig fmt: block in slice expression" {
   1010     try testCanonical(
   1011         \\const a = b[{
   1012         \\    _ = x;
   1013         \\}..];
   1014         \\const c = d[0..{
   1015         \\    _ = x;
   1016         \\    _ = y;
   1017         \\}];
   1018         \\const e = f[0..1 :{
   1019         \\    _ = x;
   1020         \\    _ = y;
   1021         \\    _ = z;
   1022         \\}];
   1023         \\
   1024     );
   1025 }
   1026 
   1027 test "zig fmt: async function" {
   1028     try testCanonical(
   1029         \\pub const Server = struct {
   1030         \\    handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
   1031         \\};
   1032         \\test "hi" {
   1033         \\    var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
   1034         \\}
   1035         \\
   1036     );
   1037 }
   1038 
   1039 test "zig fmt: whitespace fixes" {
   1040     try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a  = b;}\r\n",
   1041         \\test "" {
   1042         \\    const hi = x;
   1043         \\}
   1044         \\// zig fmt: off
   1045         \\test ""{
   1046         \\    const a  = b;}
   1047         \\
   1048     );
   1049 }
   1050 
   1051 test "zig fmt: while else err prong with no block" {
   1052     try testCanonical(
   1053         \\test "" {
   1054         \\    const result = while (returnError()) |value| {
   1055         \\        break value;
   1056         \\    } else |err| @as(i32, 2);
   1057         \\    try expect(result == 2);
   1058         \\}
   1059         \\
   1060     );
   1061 }
   1062 
   1063 test "zig fmt: tagged union with enum values" {
   1064     try testCanonical(
   1065         \\const MultipleChoice2 = union(enum(u32)) {
   1066         \\    Unspecified1: i32,
   1067         \\    A: f32 = 20,
   1068         \\    Unspecified2: void,
   1069         \\    B: bool = 40,
   1070         \\    Unspecified3: i32,
   1071         \\    C: i8 = 60,
   1072         \\    Unspecified4: void,
   1073         \\    D: void = 1000,
   1074         \\    Unspecified5: i32,
   1075         \\};
   1076         \\
   1077     );
   1078 }
   1079 
   1080 test "zig fmt: tagged union enum tag last token" {
   1081     try testCanonical(
   1082         \\test {
   1083         \\    const U = union(enum(u32)) {};
   1084         \\}
   1085         \\
   1086         \\test {
   1087         \\    const U = union(enum(u32)) { foo };
   1088         \\}
   1089         \\
   1090         \\test {
   1091         \\    const U = union(enum(u32)) {
   1092         \\        foo,
   1093         \\    };
   1094         \\}
   1095         \\
   1096     );
   1097 }
   1098 
   1099 test "zig fmt: allowzero pointer" {
   1100     try testCanonical(
   1101         \\const T = [*]allowzero const u8;
   1102         \\
   1103     );
   1104 }
   1105 
   1106 test "zig fmt: empty enum decls" {
   1107     try testCanonical(
   1108         \\const A = enum {};
   1109         \\const B = enum(u32) {};
   1110         \\const C = extern enum(c_int) {};
   1111         \\const D = packed enum(u8) {};
   1112         \\
   1113     );
   1114 }
   1115 
   1116 test "zig fmt: empty union decls" {
   1117     try testCanonical(
   1118         \\const A = union {};
   1119         \\const B = union(enum) {};
   1120         \\const C = union(Foo) {};
   1121         \\const D = extern union {};
   1122         \\const E = packed union {};
   1123         \\
   1124     );
   1125 }
   1126 
   1127 test "zig fmt: enum literal" {
   1128     try testCanonical(
   1129         \\const x = .hi;
   1130         \\
   1131     );
   1132 }
   1133 
   1134 test "zig fmt: enum literal inside array literal" {
   1135     try testCanonical(
   1136         \\test "enums in arrays" {
   1137         \\    var colors = []Color{.Green};
   1138         \\    colors = []Colors{ .Green, .Cyan };
   1139         \\    colors = []Colors{
   1140         \\        .Grey,
   1141         \\        .Green,
   1142         \\        .Cyan,
   1143         \\    };
   1144         \\}
   1145         \\
   1146     );
   1147 }
   1148 
   1149 test "zig fmt: character literal larger than u8" {
   1150     try testCanonical(
   1151         \\const x = '\u{01f4a9}';
   1152         \\
   1153     );
   1154 }
   1155 
   1156 test "zig fmt: infix operator and then multiline string literal" {
   1157     try testCanonical(
   1158         \\const x = "" ++
   1159         \\    \\ hi
   1160         \\;
   1161         \\
   1162     );
   1163 }
   1164 
   1165 test "zig fmt: infix operator and then multiline string literal" {
   1166     try testCanonical(
   1167         \\const x = "" ++
   1168         \\    \\ hi0
   1169         \\    \\ hi1
   1170         \\    \\ hi2
   1171         \\;
   1172         \\
   1173     );
   1174 }
   1175 
   1176 test "zig fmt: C pointers" {
   1177     try testCanonical(
   1178         \\const Ptr = [*c]i32;
   1179         \\
   1180     );
   1181 }
   1182 
   1183 test "zig fmt: threadlocal" {
   1184     try testCanonical(
   1185         \\threadlocal var x: i32 = 1234;
   1186         \\
   1187     );
   1188 }
   1189 
   1190 test "zig fmt: linksection" {
   1191     try testCanonical(
   1192         \\export var aoeu: u64 linksection(".text.derp") = 1234;
   1193         \\export fn _start() linksection(".text.boot") callconv(.Naked) noreturn {}
   1194         \\
   1195     );
   1196 }
   1197 
   1198 test "zig fmt: addrspace" {
   1199     try testCanonical(
   1200         \\export var python_length: u64 align(1) addrspace(.generic);
   1201         \\export var python_color: Color addrspace(.generic) = .green;
   1202         \\export var python_legs: u0 align(8) addrspace(.generic) linksection(".python") = 0;
   1203         \\export fn python_hiss() align(8) addrspace(.generic) linksection(".python") void;
   1204         \\
   1205     );
   1206 }
   1207 
   1208 test "zig fmt: correctly space struct fields with doc comments" {
   1209     try testTransform(
   1210         \\pub const S = struct {
   1211         \\    /// A
   1212         \\    a: u8,
   1213         \\    /// B
   1214         \\    /// B (cont)
   1215         \\    b: u8,
   1216         \\
   1217         \\
   1218         \\    /// C
   1219         \\    c: u8,
   1220         \\};
   1221         \\
   1222     ,
   1223         \\pub const S = struct {
   1224         \\    /// A
   1225         \\    a: u8,
   1226         \\    /// B
   1227         \\    /// B (cont)
   1228         \\    b: u8,
   1229         \\
   1230         \\    /// C
   1231         \\    c: u8,
   1232         \\};
   1233         \\
   1234     );
   1235 }
   1236 
   1237 test "zig fmt: doc comments on param decl" {
   1238     try testCanonical(
   1239         \\pub const Allocator = struct {
   1240         \\    shrinkFn: fn (
   1241         \\        self: Allocator,
   1242         \\        /// Guaranteed to be the same as what was returned from most recent call to
   1243         \\        /// `allocFn`, `reallocFn`, or `shrinkFn`.
   1244         \\        old_mem: []u8,
   1245         \\        /// Guaranteed to be the same as what was returned from most recent call to
   1246         \\        /// `allocFn`, `reallocFn`, or `shrinkFn`.
   1247         \\        old_alignment: u29,
   1248         \\        /// Guaranteed to be less than or equal to `old_mem.len`.
   1249         \\        new_byte_count: usize,
   1250         \\        /// Guaranteed to be less than or equal to `old_alignment`.
   1251         \\        new_alignment: u29,
   1252         \\    ) []u8,
   1253         \\};
   1254         \\
   1255     );
   1256 }
   1257 
   1258 test "zig fmt: aligned struct field" {
   1259     try testCanonical(
   1260         \\pub const S = struct {
   1261         \\    f: i32 align(32),
   1262         \\};
   1263         \\
   1264     );
   1265     try testCanonical(
   1266         \\pub const S = struct {
   1267         \\    f: i32 align(32) = 1,
   1268         \\};
   1269         \\
   1270     );
   1271 }
   1272 
   1273 test "zig fmt: comment to disable/enable zig fmt first" {
   1274     try testCanonical(
   1275         \\// Test trailing comma syntax
   1276         \\// zig fmt: off
   1277         \\
   1278         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1279     );
   1280 }
   1281 
   1282 test "zig fmt: 'zig fmt: (off|on)' can be surrounded by arbitrary whitespace" {
   1283     try testTransform(
   1284         \\// Test trailing comma syntax
   1285         \\//     zig fmt: off
   1286         \\
   1287         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1288         \\
   1289         \\//   zig fmt: on
   1290     ,
   1291         \\// Test trailing comma syntax
   1292         \\// zig fmt: off
   1293         \\
   1294         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   1295         \\
   1296         \\// zig fmt: on
   1297         \\
   1298     );
   1299 }
   1300 
   1301 test "zig fmt: comment to disable/enable zig fmt" {
   1302     try testTransform(
   1303         \\const  a  =  b;
   1304         \\// zig fmt: off
   1305         \\const  c  =  d;
   1306         \\// zig fmt: on
   1307         \\const  e  =  f;
   1308     ,
   1309         \\const a = b;
   1310         \\// zig fmt: off
   1311         \\const  c  =  d;
   1312         \\// zig fmt: on
   1313         \\const e = f;
   1314         \\
   1315     );
   1316 }
   1317 
   1318 test "zig fmt: line comment following 'zig fmt: off'" {
   1319     try testCanonical(
   1320         \\// zig fmt: off
   1321         \\// Test
   1322         \\const  e  =  f;
   1323     );
   1324 }
   1325 
   1326 test "zig fmt: doc comment following 'zig fmt: off'" {
   1327     try testCanonical(
   1328         \\// zig fmt: off
   1329         \\/// test
   1330         \\const  e  =  f;
   1331     );
   1332 }
   1333 
   1334 test "zig fmt: line and doc comment following 'zig fmt: off'" {
   1335     try testCanonical(
   1336         \\// zig fmt: off
   1337         \\// test 1
   1338         \\/// test 2
   1339         \\const  e  =  f;
   1340     );
   1341 }
   1342 
   1343 test "zig fmt: doc and line comment following 'zig fmt: off'" {
   1344     try testCanonical(
   1345         \\// zig fmt: off
   1346         \\/// test 1
   1347         \\// test 2
   1348         \\const  e  =  f;
   1349     );
   1350 }
   1351 
   1352 test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
   1353     try testCanonical(
   1354         \\// zig fmt: off
   1355         \\// zig fmt: on
   1356         \\// zig fmt: off
   1357         \\const  e  =  f;
   1358         \\// zig fmt: off
   1359         \\// zig fmt: on
   1360         \\// zig fmt: off
   1361         \\const  a  =  b;
   1362         \\// zig fmt: on
   1363         \\const c = d;
   1364         \\// zig fmt: on
   1365         \\
   1366     );
   1367 }
   1368 
   1369 test "zig fmt: line comment following 'zig fmt: on'" {
   1370     try testCanonical(
   1371         \\// zig fmt: off
   1372         \\const  e  =  f;
   1373         \\// zig fmt: on
   1374         \\// test
   1375         \\const e = f;
   1376         \\
   1377     );
   1378 }
   1379 
   1380 test "zig fmt: doc comment following 'zig fmt: on'" {
   1381     try testCanonical(
   1382         \\// zig fmt: off
   1383         \\const  e  =  f;
   1384         \\// zig fmt: on
   1385         \\/// test
   1386         \\const e = f;
   1387         \\
   1388     );
   1389 }
   1390 
   1391 test "zig fmt: line and doc comment following 'zig fmt: on'" {
   1392     try testCanonical(
   1393         \\// zig fmt: off
   1394         \\const  e  =  f;
   1395         \\// zig fmt: on
   1396         \\// test1
   1397         \\/// test2
   1398         \\const e = f;
   1399         \\
   1400     );
   1401 }
   1402 
   1403 test "zig fmt: doc and line comment following 'zig fmt: on'" {
   1404     try testCanonical(
   1405         \\// zig fmt: off
   1406         \\const  e  =  f;
   1407         \\// zig fmt: on
   1408         \\/// test1
   1409         \\// test2
   1410         \\const e = f;
   1411         \\
   1412     );
   1413 }
   1414 
   1415 test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
   1416     try testTransform(
   1417         \\test "" {
   1418         \\    const x = 42;
   1419         \\
   1420         \\    if (foobar) |y| {
   1421         \\    // zig fmt: off
   1422         \\            }// zig fmt: on
   1423         \\
   1424         \\    const  z  = 420;
   1425         \\}
   1426         \\
   1427     ,
   1428         \\test "" {
   1429         \\    const x = 42;
   1430         \\
   1431         \\    if (foobar) |y| {
   1432         \\        // zig fmt: off
   1433         \\            }// zig fmt: on
   1434         \\
   1435         \\    const z = 420;
   1436         \\}
   1437         \\
   1438     );
   1439 }
   1440 
   1441 test "zig fmt: 'zig fmt: on' indentation is unchanged" {
   1442     try testCanonical(
   1443         \\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
   1444         \\    // zig fmt: off
   1445         \\    try output.main_amount.init(output, "main_amount"); errdefer optput.main_amount.deinit();
   1446         \\    try output.main_factor.init(output, "main_factor"); errdefer optput.main_factor.deinit();
   1447         \\    try output.view_padding.init(output, "view_padding"); errdefer optput.view_padding.deinit();
   1448         \\    try output.outer_padding.init(output, "outer_padding"); errdefer optput.outer_padding.deinit();
   1449         \\    // zig fmt: on
   1450         \\
   1451         \\    // zig fmt: off
   1452         \\    try output.top.init(output, .top); errdefer optput.top.deinit();
   1453         \\    try output.right.init(output, .right); errdefer optput.right.deinit();
   1454         \\    try output.bottom.init(output, .bottom); errdefer optput.bottom.deinit();
   1455         \\    try output.left.init(output, .left); errdefer optput.left.deinit();
   1456         \\        // zig fmt: on
   1457         \\}
   1458         \\
   1459     );
   1460 }
   1461 
   1462 test "zig fmt: pointer of unknown length" {
   1463     try testCanonical(
   1464         \\fn foo(ptr: [*]u8) void {}
   1465         \\
   1466     );
   1467 }
   1468 
   1469 test "zig fmt: spaces around slice operator" {
   1470     try testCanonical(
   1471         \\var a = b[c..d];
   1472         \\var a = b[c..d :0];
   1473         \\var a = b[c + 1 .. d];
   1474         \\var a = b[c + 1 ..];
   1475         \\var a = b[c .. d + 1];
   1476         \\var a = b[c .. d + 1 :0];
   1477         \\var a = b[c.a..d.e];
   1478         \\var a = b[c.a..d.e :0];
   1479         \\
   1480     );
   1481 }
   1482 
   1483 test "zig fmt: async call in if condition" {
   1484     try testCanonical(
   1485         \\comptime {
   1486         \\    if (async b()) {
   1487         \\        a();
   1488         \\    }
   1489         \\}
   1490         \\
   1491     );
   1492 }
   1493 
   1494 test "zig fmt: 2nd arg multiline string" {
   1495     try testCanonical(
   1496         \\comptime {
   1497         \\    cases.addAsm("hello world linux x86_64",
   1498         \\        \\.text
   1499         \\    , "Hello, world!\n");
   1500         \\}
   1501         \\
   1502     );
   1503     try testTransform(
   1504         \\comptime {
   1505         \\    cases.addAsm("hello world linux x86_64",
   1506         \\        \\.text
   1507         \\    , "Hello, world!\n",);
   1508         \\}
   1509     ,
   1510         \\comptime {
   1511         \\    cases.addAsm(
   1512         \\        "hello world linux x86_64",
   1513         \\        \\.text
   1514         \\    ,
   1515         \\        "Hello, world!\n",
   1516         \\    );
   1517         \\}
   1518         \\
   1519     );
   1520 }
   1521 
   1522 test "zig fmt: 2nd arg multiline string many args" {
   1523     try testCanonical(
   1524         \\comptime {
   1525         \\    cases.addAsm("hello world linux x86_64",
   1526         \\        \\.text
   1527         \\    , "Hello, world!\n", "Hello, world!\n");
   1528         \\}
   1529         \\
   1530     );
   1531 }
   1532 
   1533 test "zig fmt: final arg multiline string" {
   1534     try testCanonical(
   1535         \\comptime {
   1536         \\    cases.addAsm("hello world linux x86_64", "Hello, world!\n",
   1537         \\        \\.text
   1538         \\    );
   1539         \\}
   1540         \\
   1541     );
   1542 }
   1543 
   1544 test "zig fmt: if condition wraps" {
   1545     try testTransform(
   1546         \\comptime {
   1547         \\    if (cond and
   1548         \\        cond) {
   1549         \\        return x;
   1550         \\    }
   1551         \\    while (cond and
   1552         \\        cond) {
   1553         \\        return x;
   1554         \\    }
   1555         \\    if (a == b and
   1556         \\        c) {
   1557         \\        a = b;
   1558         \\    }
   1559         \\    while (a == b and
   1560         \\        c) {
   1561         \\        a = b;
   1562         \\    }
   1563         \\    if ((cond and
   1564         \\        cond)) {
   1565         \\        return x;
   1566         \\    }
   1567         \\    while ((cond and
   1568         \\        cond)) {
   1569         \\        return x;
   1570         \\    }
   1571         \\    var a = if (a) |*f| x: {
   1572         \\        break :x &a.b;
   1573         \\    } else |err| err;
   1574         \\    var a = if (cond and
   1575         \\                cond) |*f|
   1576         \\    x: {
   1577         \\        break :x &a.b;
   1578         \\    } else |err| err;
   1579         \\}
   1580     ,
   1581         \\comptime {
   1582         \\    if (cond and
   1583         \\        cond)
   1584         \\    {
   1585         \\        return x;
   1586         \\    }
   1587         \\    while (cond and
   1588         \\        cond)
   1589         \\    {
   1590         \\        return x;
   1591         \\    }
   1592         \\    if (a == b and
   1593         \\        c)
   1594         \\    {
   1595         \\        a = b;
   1596         \\    }
   1597         \\    while (a == b and
   1598         \\        c)
   1599         \\    {
   1600         \\        a = b;
   1601         \\    }
   1602         \\    if ((cond and
   1603         \\        cond))
   1604         \\    {
   1605         \\        return x;
   1606         \\    }
   1607         \\    while ((cond and
   1608         \\        cond))
   1609         \\    {
   1610         \\        return x;
   1611         \\    }
   1612         \\    var a = if (a) |*f| x: {
   1613         \\        break :x &a.b;
   1614         \\    } else |err| err;
   1615         \\    var a = if (cond and
   1616         \\        cond) |*f|
   1617         \\    x: {
   1618         \\        break :x &a.b;
   1619         \\    } else |err| err;
   1620         \\}
   1621         \\
   1622     );
   1623 }
   1624 
   1625 test "zig fmt: if condition has line break but must not wrap" {
   1626     try testCanonical(
   1627         \\comptime {
   1628         \\    if (self.user_input_options.put(
   1629         \\        name,
   1630         \\        UserInputOption{
   1631         \\            .name = name,
   1632         \\            .used = false,
   1633         \\        },
   1634         \\    ) catch unreachable) |*prev_value| {
   1635         \\        foo();
   1636         \\        bar();
   1637         \\    }
   1638         \\    if (put(
   1639         \\        a,
   1640         \\        b,
   1641         \\    )) {
   1642         \\        foo();
   1643         \\    }
   1644         \\}
   1645         \\
   1646     );
   1647 }
   1648 
   1649 test "zig fmt: if condition has line break but must not wrap (no fn call comma)" {
   1650     try testCanonical(
   1651         \\comptime {
   1652         \\    if (self.user_input_options.put(name, UserInputOption{
   1653         \\        .name = name,
   1654         \\        .used = false,
   1655         \\    }) catch unreachable) |*prev_value| {
   1656         \\        foo();
   1657         \\        bar();
   1658         \\    }
   1659         \\    if (put(
   1660         \\        a,
   1661         \\        b,
   1662         \\    )) {
   1663         \\        foo();
   1664         \\    }
   1665         \\}
   1666         \\
   1667     );
   1668 }
   1669 
   1670 test "zig fmt: function call with multiline argument" {
   1671     try testCanonical(
   1672         \\comptime {
   1673         \\    self.user_input_options.put(name, UserInputOption{
   1674         \\        .name = name,
   1675         \\        .used = false,
   1676         \\    });
   1677         \\}
   1678         \\
   1679     );
   1680 }
   1681 
   1682 test "zig fmt: if-else with comment before else" {
   1683     try testCanonical(
   1684         \\comptime {
   1685         \\    // cexp(finite|nan +- i inf|nan) = nan + i nan
   1686         \\    if ((hx & 0x7fffffff) != 0x7f800000) {
   1687         \\        return Complex(f32).init(y - y, y - y);
   1688         \\    } // cexp(-inf +- i inf|nan) = 0 + i0
   1689         \\    else if (hx & 0x80000000 != 0) {
   1690         \\        return Complex(f32).init(0, 0);
   1691         \\    } // cexp(+inf +- i inf|nan) = inf + i nan
   1692         \\    else {
   1693         \\        return Complex(f32).init(x, y - y);
   1694         \\    }
   1695         \\}
   1696         \\
   1697     );
   1698 }
   1699 
   1700 test "zig fmt: if nested" {
   1701     try testCanonical(
   1702         \\pub fn foo() void {
   1703         \\    return if ((aInt & bInt) >= 0)
   1704         \\        if (aInt < bInt)
   1705         \\            GE_LESS
   1706         \\        else if (aInt == bInt)
   1707         \\            GE_EQUAL
   1708         \\        else
   1709         \\            GE_GREATER
   1710         \\        // comment
   1711         \\    else if (aInt > bInt)
   1712         \\        GE_LESS
   1713         \\    else if (aInt == bInt)
   1714         \\        GE_EQUAL
   1715         \\    else
   1716         \\        GE_GREATER;
   1717         \\    // comment
   1718         \\}
   1719         \\
   1720     );
   1721 }
   1722 
   1723 test "zig fmt: respect line breaks in if-else" {
   1724     try testCanonical(
   1725         \\comptime {
   1726         \\    return if (cond) a else b;
   1727         \\    return if (cond)
   1728         \\        a
   1729         \\    else
   1730         \\        b;
   1731         \\    return if (cond)
   1732         \\        a
   1733         \\    else if (cond)
   1734         \\        b
   1735         \\    else
   1736         \\        c;
   1737         \\}
   1738         \\
   1739     );
   1740 }
   1741 
   1742 test "zig fmt: respect line breaks after infix operators" {
   1743     try testCanonical(
   1744         \\comptime {
   1745         \\    self.crc =
   1746         \\        lookup_tables[0][p[7]] ^
   1747         \\        lookup_tables[1][p[6]] ^
   1748         \\        lookup_tables[2][p[5]] ^
   1749         \\        lookup_tables[3][p[4]] ^
   1750         \\        lookup_tables[4][@truncate(u8, self.crc >> 24)] ^
   1751         \\        lookup_tables[5][@truncate(u8, self.crc >> 16)] ^
   1752         \\        lookup_tables[6][@truncate(u8, self.crc >> 8)] ^
   1753         \\        lookup_tables[7][@truncate(u8, self.crc >> 0)];
   1754         \\}
   1755         \\
   1756     );
   1757 }
   1758 
   1759 test "zig fmt: fn decl with trailing comma" {
   1760     try testTransform(
   1761         \\fn foo(a: i32, b: i32,) void {}
   1762     ,
   1763         \\fn foo(
   1764         \\    a: i32,
   1765         \\    b: i32,
   1766         \\) void {}
   1767         \\
   1768     );
   1769 }
   1770 
   1771 test "zig fmt: enum decl with no trailing comma" {
   1772     try testTransform(
   1773         \\const StrLitKind = enum {Normal, C};
   1774     ,
   1775         \\const StrLitKind = enum { Normal, C };
   1776         \\
   1777     );
   1778 }
   1779 
   1780 test "zig fmt: switch comment before prong" {
   1781     try testCanonical(
   1782         \\comptime {
   1783         \\    switch (a) {
   1784         \\        // hi
   1785         \\        0 => {},
   1786         \\    }
   1787         \\}
   1788         \\
   1789     );
   1790 }
   1791 
   1792 test "zig fmt: struct literal no trailing comma" {
   1793     try testTransform(
   1794         \\const a = foo{ .x = 1, .y = 2 };
   1795         \\const a = foo{ .x = 1,
   1796         \\    .y = 2 };
   1797         \\const a = foo{ .x = 1,
   1798         \\    .y = 2, };
   1799     ,
   1800         \\const a = foo{ .x = 1, .y = 2 };
   1801         \\const a = foo{ .x = 1, .y = 2 };
   1802         \\const a = foo{
   1803         \\    .x = 1,
   1804         \\    .y = 2,
   1805         \\};
   1806         \\
   1807     );
   1808 }
   1809 
   1810 test "zig fmt: struct literal containing a multiline expression" {
   1811     try testTransform(
   1812         \\const a = A{ .x = if (f1()) 10 else 20 };
   1813         \\const a = A{ .x = if (f1()) 10 else 20, };
   1814         \\const a = A{ .x = if (f1())
   1815         \\    10 else 20 };
   1816         \\const a = A{ .x = if (f1())
   1817         \\    10 else 20,};
   1818         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
   1819         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100, };
   1820         \\const a = A{ .x = if (f1())
   1821         \\    10 else 20};
   1822         \\const a = A{ .x = if (f1())
   1823         \\    10 else 20,};
   1824         \\const a = A{ .x = switch(g) {0 => "ok", else => "no"} };
   1825         \\const a = A{ .x = switch(g) {0 => "ok", else => "no"}, };
   1826         \\
   1827     ,
   1828         \\const a = A{ .x = if (f1()) 10 else 20 };
   1829         \\const a = A{
   1830         \\    .x = if (f1()) 10 else 20,
   1831         \\};
   1832         \\const a = A{ .x = if (f1())
   1833         \\    10
   1834         \\else
   1835         \\    20 };
   1836         \\const a = A{
   1837         \\    .x = if (f1())
   1838         \\        10
   1839         \\    else
   1840         \\        20,
   1841         \\};
   1842         \\const a = A{ .x = if (f1()) 10 else 20, .y = f2() + 100 };
   1843         \\const a = A{
   1844         \\    .x = if (f1()) 10 else 20,
   1845         \\    .y = f2() + 100,
   1846         \\};
   1847         \\const a = A{ .x = if (f1())
   1848         \\    10
   1849         \\else
   1850         \\    20 };
   1851         \\const a = A{
   1852         \\    .x = if (f1())
   1853         \\        10
   1854         \\    else
   1855         \\        20,
   1856         \\};
   1857         \\const a = A{ .x = switch (g) {
   1858         \\    0 => "ok",
   1859         \\    else => "no",
   1860         \\} };
   1861         \\const a = A{
   1862         \\    .x = switch (g) {
   1863         \\        0 => "ok",
   1864         \\        else => "no",
   1865         \\    },
   1866         \\};
   1867         \\
   1868     );
   1869 }
   1870 
   1871 test "zig fmt: array literal with hint" {
   1872     try testTransform(
   1873         \\const a = []u8{
   1874         \\    1, 2, //
   1875         \\    3,
   1876         \\    4,
   1877         \\    5,
   1878         \\    6,
   1879         \\    7 };
   1880         \\const a = []u8{
   1881         \\    1, 2, //
   1882         \\    3,
   1883         \\    4,
   1884         \\    5,
   1885         \\    6,
   1886         \\    7, 8 };
   1887         \\const a = []u8{
   1888         \\    1, 2, //
   1889         \\    3,
   1890         \\    4,
   1891         \\    5,
   1892         \\    6, // blah
   1893         \\    7, 8 };
   1894         \\const a = []u8{
   1895         \\    1, 2, //
   1896         \\    3, //
   1897         \\    4,
   1898         \\    5,
   1899         \\    6,
   1900         \\    7 };
   1901         \\const a = []u8{
   1902         \\    1,
   1903         \\    2,
   1904         \\    3, 4, //
   1905         \\    5, 6, //
   1906         \\    7, 8, //
   1907         \\};
   1908     ,
   1909         \\const a = []u8{
   1910         \\    1, 2, //
   1911         \\    3, 4,
   1912         \\    5, 6,
   1913         \\    7,
   1914         \\};
   1915         \\const a = []u8{
   1916         \\    1, 2, //
   1917         \\    3, 4,
   1918         \\    5, 6,
   1919         \\    7, 8,
   1920         \\};
   1921         \\const a = []u8{
   1922         \\    1, 2, //
   1923         \\    3, 4,
   1924         \\    5,
   1925         \\    6, // blah
   1926         \\    7,
   1927         \\    8,
   1928         \\};
   1929         \\const a = []u8{
   1930         \\    1, 2, //
   1931         \\    3, //
   1932         \\    4,
   1933         \\    5,
   1934         \\    6,
   1935         \\    7,
   1936         \\};
   1937         \\const a = []u8{
   1938         \\    1,
   1939         \\    2,
   1940         \\    3, 4, //
   1941         \\    5, 6, //
   1942         \\    7, 8, //
   1943         \\};
   1944         \\
   1945     );
   1946 }
   1947 
   1948 test "zig fmt: array literal vertical column alignment" {
   1949     try testTransform(
   1950         \\const a = []u8{
   1951         \\    1000, 200,
   1952         \\    30, 4,
   1953         \\    50000, 60,
   1954         \\};
   1955         \\const a = []u8{0,   1, 2, 3, 40,
   1956         \\    4,5,600,7,
   1957         \\           80,
   1958         \\    9, 10, 11, 0, 13, 14, 15,};
   1959         \\const a = [12]u8{
   1960         \\    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   1961         \\const a = [12]u8{
   1962         \\    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, };
   1963         \\
   1964     ,
   1965         \\const a = []u8{
   1966         \\    1000,  200,
   1967         \\    30,    4,
   1968         \\    50000, 60,
   1969         \\};
   1970         \\const a = []u8{
   1971         \\    0,  1,  2,   3, 40,
   1972         \\    4,  5,  600, 7, 80,
   1973         \\    9,  10, 11,  0, 13,
   1974         \\    14, 15,
   1975         \\};
   1976         \\const a = [12]u8{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   1977         \\const a = [12]u8{
   1978         \\    31,
   1979         \\    28,
   1980         \\    31,
   1981         \\    30,
   1982         \\    31,
   1983         \\    30,
   1984         \\    31,
   1985         \\    31,
   1986         \\    30,
   1987         \\    31,
   1988         \\    30,
   1989         \\    31,
   1990         \\};
   1991         \\
   1992     );
   1993 }
   1994 
   1995 test "zig fmt: multiline string with backslash at end of line" {
   1996     try testCanonical(
   1997         \\comptime {
   1998         \\    err(
   1999         \\        \\\
   2000         \\    );
   2001         \\}
   2002         \\
   2003     );
   2004 }
   2005 
   2006 test "zig fmt: multiline string parameter in fn call with trailing comma" {
   2007     try testCanonical(
   2008         \\fn foo() void {
   2009         \\    try stdout.print(
   2010         \\        \\ZIG_CMAKE_BINARY_DIR {}
   2011         \\        \\ZIG_C_HEADER_FILES   {}
   2012         \\        \\ZIG_DIA_GUIDS_LIB    {}
   2013         \\        \\
   2014         \\    ,
   2015         \\        std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
   2016         \\        std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
   2017         \\        std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
   2018         \\    );
   2019         \\}
   2020         \\
   2021     );
   2022 }
   2023 
   2024 test "zig fmt: trailing comma on fn call" {
   2025     try testCanonical(
   2026         \\comptime {
   2027         \\    var module = try Module.create(
   2028         \\        allocator,
   2029         \\        zig_lib_dir,
   2030         \\        full_cache_dir,
   2031         \\    );
   2032         \\}
   2033         \\
   2034     );
   2035 }
   2036 
   2037 test "zig fmt: multi line arguments without last comma" {
   2038     try testTransform(
   2039         \\pub fn foo(
   2040         \\    a: usize,
   2041         \\    b: usize,
   2042         \\    c: usize,
   2043         \\    d: usize
   2044         \\) usize {
   2045         \\    return a + b + c + d;
   2046         \\}
   2047         \\
   2048     ,
   2049         \\pub fn foo(a: usize, b: usize, c: usize, d: usize) usize {
   2050         \\    return a + b + c + d;
   2051         \\}
   2052         \\
   2053     );
   2054 }
   2055 
   2056 test "zig fmt: empty block with only comment" {
   2057     try testCanonical(
   2058         \\comptime {
   2059         \\    {
   2060         \\        // comment
   2061         \\    }
   2062         \\}
   2063         \\
   2064     );
   2065 }
   2066 
   2067 test "zig fmt: trailing commas on struct decl" {
   2068     try testTransform(
   2069         \\const RoundParam = struct {
   2070         \\    k: usize, s: u32, t: u32
   2071         \\};
   2072         \\const RoundParam = struct {
   2073         \\    k: usize, s: u32, t: u32,
   2074         \\};
   2075     ,
   2076         \\const RoundParam = struct { k: usize, s: u32, t: u32 };
   2077         \\const RoundParam = struct {
   2078         \\    k: usize,
   2079         \\    s: u32,
   2080         \\    t: u32,
   2081         \\};
   2082         \\
   2083     );
   2084 }
   2085 
   2086 test "zig fmt: extra newlines at the end" {
   2087     try testTransform(
   2088         \\const a = b;
   2089         \\
   2090         \\
   2091         \\
   2092     ,
   2093         \\const a = b;
   2094         \\
   2095     );
   2096 }
   2097 
   2098 test "zig fmt: simple asm" {
   2099     try testTransform(
   2100         \\comptime {
   2101         \\    asm volatile (
   2102         \\        \\.globl aoeu;
   2103         \\        \\.type aoeu, @function;
   2104         \\        \\.set aoeu, derp;
   2105         \\    );
   2106         \\
   2107         \\    asm ("not real assembly"
   2108         \\        :[a] "x" (x),);
   2109         \\    asm ("not real assembly"
   2110         \\        :[a] "x" (->i32),:[a] "x" (1),);
   2111         \\    asm ("still not real assembly"
   2112         \\        :::"a","b",);
   2113         \\}
   2114     ,
   2115         \\comptime {
   2116         \\    asm volatile (
   2117         \\        \\.globl aoeu;
   2118         \\        \\.type aoeu, @function;
   2119         \\        \\.set aoeu, derp;
   2120         \\    );
   2121         \\
   2122         \\    asm ("not real assembly"
   2123         \\        : [a] "x" (x),
   2124         \\    );
   2125         \\    asm ("not real assembly"
   2126         \\        : [a] "x" (-> i32),
   2127         \\        : [a] "x" (1),
   2128         \\    );
   2129         \\    asm ("still not real assembly" ::: "a", "b");
   2130         \\}
   2131         \\
   2132     );
   2133 }
   2134 
   2135 test "zig fmt: nested struct literal with one item" {
   2136     try testCanonical(
   2137         \\const a = foo{
   2138         \\    .item = bar{ .a = b },
   2139         \\};
   2140         \\
   2141     );
   2142 }
   2143 
   2144 test "zig fmt: switch cases trailing comma" {
   2145     try testTransform(
   2146         \\test "switch cases trailing comma"{
   2147         \\    switch (x) {
   2148         \\        1,2,3 => {},
   2149         \\        4,5, => {},
   2150         \\        6... 8, => {},
   2151         \\        else => {},
   2152         \\    }
   2153         \\}
   2154     ,
   2155         \\test "switch cases trailing comma" {
   2156         \\    switch (x) {
   2157         \\        1, 2, 3 => {},
   2158         \\        4,
   2159         \\        5,
   2160         \\        => {},
   2161         \\        6...8 => {},
   2162         \\        else => {},
   2163         \\    }
   2164         \\}
   2165         \\
   2166     );
   2167 }
   2168 
   2169 test "zig fmt: slice align" {
   2170     try testCanonical(
   2171         \\const A = struct {
   2172         \\    items: []align(A) T,
   2173         \\};
   2174         \\
   2175     );
   2176 }
   2177 
   2178 test "zig fmt: add trailing comma to array literal" {
   2179     try testTransform(
   2180         \\comptime {
   2181         \\    return []u16{'m', 's', 'y', 's', '-' // hi
   2182         \\   };
   2183         \\    return []u16{'m', 's', 'y', 's',
   2184         \\      '-'};
   2185         \\    return []u16{'m', 's', 'y', 's', '-'};
   2186         \\}
   2187     ,
   2188         \\comptime {
   2189         \\    return []u16{
   2190         \\        'm', 's', 'y', 's', '-', // hi
   2191         \\    };
   2192         \\    return []u16{ 'm', 's', 'y', 's', '-' };
   2193         \\    return []u16{ 'm', 's', 'y', 's', '-' };
   2194         \\}
   2195         \\
   2196     );
   2197 }
   2198 
   2199 test "zig fmt: first thing in file is line comment" {
   2200     try testCanonical(
   2201         \\// Introspection and determination of system libraries needed by zig.
   2202         \\
   2203         \\// Introspection and determination of system libraries needed by zig.
   2204         \\
   2205         \\const std = @import("std");
   2206         \\
   2207     );
   2208 }
   2209 
   2210 test "zig fmt: line comment after doc comment" {
   2211     try testCanonical(
   2212         \\/// doc comment
   2213         \\// line comment
   2214         \\fn foo() void {}
   2215         \\
   2216     );
   2217 }
   2218 
   2219 test "zig fmt: bit field alignment" {
   2220     try testCanonical(
   2221         \\test {
   2222         \\    assert(@TypeOf(&blah.b) == *align(1:3:6) const u3);
   2223         \\}
   2224         \\
   2225     );
   2226 }
   2227 
   2228 test "zig fmt: nested switch" {
   2229     try testCanonical(
   2230         \\test {
   2231         \\    switch (state) {
   2232         \\        TermState.Start => switch (c) {
   2233         \\            '\x1b' => state = TermState.Escape,
   2234         \\            else => try out.writeByte(c),
   2235         \\        },
   2236         \\    }
   2237         \\}
   2238         \\
   2239     );
   2240 }
   2241 
   2242 test "zig fmt: float literal with exponent" {
   2243     try testCanonical(
   2244         \\pub const f64_true_min = 4.94065645841246544177e-324;
   2245         \\const threshold = 0x1.a827999fcef32p+1022;
   2246         \\
   2247     );
   2248 }
   2249 
   2250 test "zig fmt: if-else end of comptime" {
   2251     try testCanonical(
   2252         \\comptime {
   2253         \\    if (a) {
   2254         \\        b();
   2255         \\    } else {
   2256         \\        b();
   2257         \\    }
   2258         \\}
   2259         \\
   2260     );
   2261 }
   2262 
   2263 test "zig fmt: nested blocks" {
   2264     try testCanonical(
   2265         \\comptime {
   2266         \\    {
   2267         \\        {
   2268         \\            {
   2269         \\                a();
   2270         \\            }
   2271         \\        }
   2272         \\    }
   2273         \\}
   2274         \\
   2275     );
   2276 }
   2277 
   2278 test "zig fmt: block with same line comment after end brace" {
   2279     try testCanonical(
   2280         \\comptime {
   2281         \\    {
   2282         \\        b();
   2283         \\    } // comment
   2284         \\}
   2285         \\
   2286     );
   2287 }
   2288 
   2289 test "zig fmt: statements with comment between" {
   2290     try testCanonical(
   2291         \\comptime {
   2292         \\    a = b;
   2293         \\    // comment
   2294         \\    a = b;
   2295         \\}
   2296         \\
   2297     );
   2298 }
   2299 
   2300 test "zig fmt: statements with empty line between" {
   2301     try testCanonical(
   2302         \\comptime {
   2303         \\    a = b;
   2304         \\
   2305         \\    a = b;
   2306         \\}
   2307         \\
   2308     );
   2309 }
   2310 
   2311 test "zig fmt: ptr deref operator and unwrap optional operator" {
   2312     try testCanonical(
   2313         \\const a = b.*;
   2314         \\const a = b.?;
   2315         \\
   2316     );
   2317 }
   2318 
   2319 test "zig fmt: comment after if before another if" {
   2320     try testCanonical(
   2321         \\test "aoeu" {
   2322         \\    // comment
   2323         \\    if (x) {
   2324         \\        bar();
   2325         \\    }
   2326         \\}
   2327         \\
   2328         \\test "aoeu" {
   2329         \\    if (x) {
   2330         \\        foo();
   2331         \\    }
   2332         \\    // comment
   2333         \\    if (x) {
   2334         \\        bar();
   2335         \\    }
   2336         \\}
   2337         \\
   2338     );
   2339 }
   2340 
   2341 test "zig fmt: line comment between if block and else keyword" {
   2342     try testCanonical(
   2343         \\test "aoeu" {
   2344         \\    // cexp(finite|nan +- i inf|nan) = nan + i nan
   2345         \\    if ((hx & 0x7fffffff) != 0x7f800000) {
   2346         \\        return Complex(f32).init(y - y, y - y);
   2347         \\    }
   2348         \\    // cexp(-inf +- i inf|nan) = 0 + i0
   2349         \\    else if (hx & 0x80000000 != 0) {
   2350         \\        return Complex(f32).init(0, 0);
   2351         \\    }
   2352         \\    // cexp(+inf +- i inf|nan) = inf + i nan
   2353         \\    // another comment
   2354         \\    else {
   2355         \\        return Complex(f32).init(x, y - y);
   2356         \\    }
   2357         \\}
   2358         \\
   2359     );
   2360 }
   2361 
   2362 test "zig fmt: same line comments in expression" {
   2363     try testCanonical(
   2364         \\test "aoeu" {
   2365         \\    const x = ( // a
   2366         \\        0 // b
   2367         \\    ); // c
   2368         \\}
   2369         \\
   2370     );
   2371 }
   2372 
   2373 test "zig fmt: add comma on last switch prong" {
   2374     try testTransform(
   2375         \\test "aoeu" {
   2376         \\switch (self.init_arg_expr) {
   2377         \\    InitArg.Type => |t| { },
   2378         \\    InitArg.None,
   2379         \\    InitArg.Enum => { }
   2380         \\}
   2381         \\ switch (self.init_arg_expr) {
   2382         \\     InitArg.Type => |t| { },
   2383         \\     InitArg.None,
   2384         \\     InitArg.Enum => { }//line comment
   2385         \\ }
   2386         \\}
   2387     ,
   2388         \\test "aoeu" {
   2389         \\    switch (self.init_arg_expr) {
   2390         \\        InitArg.Type => |t| {},
   2391         \\        InitArg.None, InitArg.Enum => {},
   2392         \\    }
   2393         \\    switch (self.init_arg_expr) {
   2394         \\        InitArg.Type => |t| {},
   2395         \\        InitArg.None, InitArg.Enum => {}, //line comment
   2396         \\    }
   2397         \\}
   2398         \\
   2399     );
   2400 }
   2401 
   2402 test "zig fmt: same-line comment after a statement" {
   2403     try testCanonical(
   2404         \\test "" {
   2405         \\    a = b;
   2406         \\    debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
   2407         \\    a = b;
   2408         \\}
   2409         \\
   2410     );
   2411 }
   2412 
   2413 test "zig fmt: same-line comment after var decl in struct" {
   2414     try testCanonical(
   2415         \\pub const vfs_cap_data = extern struct {
   2416         \\    const Data = struct {}; // when on disk.
   2417         \\};
   2418         \\
   2419     );
   2420 }
   2421 
   2422 test "zig fmt: same-line comment after field decl" {
   2423     try testCanonical(
   2424         \\pub const dirent = extern struct {
   2425         \\    d_name: u8,
   2426         \\    d_name: u8, // comment 1
   2427         \\    d_name: u8,
   2428         \\    d_name: u8, // comment 2
   2429         \\    d_name: u8,
   2430         \\};
   2431         \\
   2432     );
   2433 }
   2434 
   2435 test "zig fmt: same-line comment after switch prong" {
   2436     try testCanonical(
   2437         \\test "" {
   2438         \\    switch (err) {
   2439         \\        error.PathAlreadyExists => {}, // comment 2
   2440         \\        else => return err, // comment 1
   2441         \\    }
   2442         \\}
   2443         \\
   2444     );
   2445 }
   2446 
   2447 test "zig fmt: same-line comment after non-block if expression" {
   2448     try testCanonical(
   2449         \\comptime {
   2450         \\    if (sr > n_uword_bits - 1) // d > r
   2451         \\        return 0;
   2452         \\}
   2453         \\
   2454     );
   2455 }
   2456 
   2457 test "zig fmt: same-line comment on comptime expression" {
   2458     try testCanonical(
   2459         \\test "" {
   2460         \\    comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
   2461         \\}
   2462         \\
   2463     );
   2464 }
   2465 
   2466 test "zig fmt: switch with empty body" {
   2467     try testCanonical(
   2468         \\test "" {
   2469         \\    foo() catch |err| switch (err) {};
   2470         \\}
   2471         \\
   2472     );
   2473 }
   2474 
   2475 test "zig fmt: line comments in struct initializer" {
   2476     try testCanonical(
   2477         \\fn foo() void {
   2478         \\    return Self{
   2479         \\        .a = b,
   2480         \\
   2481         \\        // Initialize these two fields to buffer_size so that
   2482         \\        // in `readFn` we treat the state as being able to read
   2483         \\        .start_index = buffer_size,
   2484         \\        .end_index = buffer_size,
   2485         \\
   2486         \\        // middle
   2487         \\
   2488         \\        .a = b,
   2489         \\
   2490         \\        // end
   2491         \\    };
   2492         \\}
   2493         \\
   2494     );
   2495 }
   2496 
   2497 test "zig fmt: first line comment in struct initializer" {
   2498     try testCanonical(
   2499         \\pub fn acquire(self: *Self) HeldLock {
   2500         \\    return HeldLock{
   2501         \\        // guaranteed allocation elision
   2502         \\        .held = self.lock.acquire(),
   2503         \\        .value = &self.private_data,
   2504         \\    };
   2505         \\}
   2506         \\
   2507     );
   2508 }
   2509 
   2510 test "zig fmt: doc comments before struct field" {
   2511     try testCanonical(
   2512         \\pub const Allocator = struct {
   2513         \\    /// Allocate byte_count bytes and return them in a slice, with the
   2514         \\    /// slice's pointer aligned at least to alignment bytes.
   2515         \\    allocFn: fn () void,
   2516         \\};
   2517         \\
   2518     );
   2519 }
   2520 
   2521 test "zig fmt: error set declaration" {
   2522     try testCanonical(
   2523         \\const E = error{
   2524         \\    A,
   2525         \\    B,
   2526         \\
   2527         \\    C,
   2528         \\};
   2529         \\
   2530         \\const Error = error{
   2531         \\    /// no more memory
   2532         \\    OutOfMemory,
   2533         \\};
   2534         \\
   2535         \\const Error = error{
   2536         \\    /// no more memory
   2537         \\    OutOfMemory,
   2538         \\
   2539         \\    /// another
   2540         \\    Another,
   2541         \\
   2542         \\    // end
   2543         \\};
   2544         \\
   2545         \\const Error = error{OutOfMemory};
   2546         \\const Error = error{};
   2547         \\
   2548         \\const Error = error{ OutOfMemory, OutOfTime };
   2549         \\
   2550     );
   2551 }
   2552 
   2553 test "zig fmt: union(enum(u32)) with assigned enum values" {
   2554     try testCanonical(
   2555         \\const MultipleChoice = union(enum(u32)) {
   2556         \\    A = 20,
   2557         \\    B = 40,
   2558         \\    C = 60,
   2559         \\    D = 1000,
   2560         \\};
   2561         \\
   2562     );
   2563 }
   2564 
   2565 test "zig fmt: resume from suspend block" {
   2566     try testCanonical(
   2567         \\fn foo() void {
   2568         \\    suspend {
   2569         \\        resume @frame();
   2570         \\    }
   2571         \\}
   2572         \\
   2573     );
   2574 }
   2575 
   2576 test "zig fmt: comments before error set decl" {
   2577     try testCanonical(
   2578         \\const UnexpectedError = error{
   2579         \\    /// The Operating System returned an undocumented error code.
   2580         \\    Unexpected,
   2581         \\    // another
   2582         \\    Another,
   2583         \\
   2584         \\    // in between
   2585         \\
   2586         \\    // at end
   2587         \\};
   2588         \\
   2589     );
   2590 }
   2591 
   2592 test "zig fmt: comments before switch prong" {
   2593     try testCanonical(
   2594         \\test "" {
   2595         \\    switch (err) {
   2596         \\        error.PathAlreadyExists => continue,
   2597         \\
   2598         \\        // comment 1
   2599         \\
   2600         \\        // comment 2
   2601         \\        else => return err,
   2602         \\        // at end
   2603         \\    }
   2604         \\}
   2605         \\
   2606     );
   2607 }
   2608 
   2609 test "zig fmt: comments before var decl in struct" {
   2610     try testCanonical(
   2611         \\pub const vfs_cap_data = extern struct {
   2612         \\    // All of these are mandated as little endian
   2613         \\    // when on disk.
   2614         \\    const Data = struct {
   2615         \\        permitted: u32,
   2616         \\        inheritable: u32,
   2617         \\    };
   2618         \\
   2619         \\    // in between
   2620         \\
   2621         \\    /// All of these are mandated as little endian
   2622         \\    /// when on disk.
   2623         \\    const Data = struct {
   2624         \\        permitted: u32,
   2625         \\        inheritable: u32,
   2626         \\    };
   2627         \\
   2628         \\    // at end
   2629         \\};
   2630         \\
   2631     );
   2632 }
   2633 
   2634 test "zig fmt: array literal with 1 item on 1 line" {
   2635     try testCanonical(
   2636         \\var s = []const u64{0} ** 25;
   2637         \\
   2638     );
   2639 }
   2640 
   2641 test "zig fmt: comments before global variables" {
   2642     try testCanonical(
   2643         \\/// Foo copies keys and values before they go into the map, and
   2644         \\/// frees them when they get removed.
   2645         \\pub const Foo = struct {};
   2646         \\
   2647     );
   2648 }
   2649 
   2650 test "zig fmt: comments in statements" {
   2651     try testCanonical(
   2652         \\test "std" {
   2653         \\    // statement comment
   2654         \\    _ = @import("foo/bar.zig");
   2655         \\
   2656         \\    // middle
   2657         \\    // middle2
   2658         \\
   2659         \\    // end
   2660         \\}
   2661         \\
   2662     );
   2663 }
   2664 
   2665 test "zig fmt: comments before test decl" {
   2666     try testCanonical(
   2667         \\/// top level doc comment
   2668         \\test "hi" {}
   2669         \\
   2670         \\// top level normal comment
   2671         \\test "hi" {}
   2672         \\
   2673         \\// middle
   2674         \\
   2675         \\// end
   2676         \\
   2677     );
   2678 }
   2679 
   2680 test "zig fmt: preserve spacing" {
   2681     try testCanonical(
   2682         \\const std = @import("std");
   2683         \\
   2684         \\pub fn main() !void {
   2685         \\    var stdout_file = std.io.getStdOut;
   2686         \\    var stdout_file = std.io.getStdOut;
   2687         \\
   2688         \\    var stdout_file = std.io.getStdOut;
   2689         \\    var stdout_file = std.io.getStdOut;
   2690         \\}
   2691         \\
   2692     );
   2693 }
   2694 
   2695 test "zig fmt: return types" {
   2696     try testCanonical(
   2697         \\pub fn main() !void {}
   2698         \\pub fn main() FooBar {}
   2699         \\pub fn main() i32 {}
   2700         \\
   2701     );
   2702 }
   2703 
   2704 test "zig fmt: imports" {
   2705     try testCanonical(
   2706         \\const std = @import("std");
   2707         \\const std = @import();
   2708         \\
   2709     );
   2710 }
   2711 
   2712 test "zig fmt: global declarations" {
   2713     try testCanonical(
   2714         \\const a = b;
   2715         \\pub const a = b;
   2716         \\var a = b;
   2717         \\pub var a = b;
   2718         \\const a: i32 = b;
   2719         \\pub const a: i32 = b;
   2720         \\var a: i32 = b;
   2721         \\pub var a: i32 = b;
   2722         \\extern const a: i32 = b;
   2723         \\pub extern const a: i32 = b;
   2724         \\extern var a: i32 = b;
   2725         \\pub extern var a: i32 = b;
   2726         \\extern "a" const a: i32 = b;
   2727         \\pub extern "a" const a: i32 = b;
   2728         \\extern "a" var a: i32 = b;
   2729         \\pub extern "a" var a: i32 = b;
   2730         \\
   2731     );
   2732 }
   2733 
   2734 test "zig fmt: extern declaration" {
   2735     try testCanonical(
   2736         \\extern var foo: c_int;
   2737         \\
   2738     );
   2739 }
   2740 
   2741 test "zig fmt: alignment" {
   2742     try testCanonical(
   2743         \\var foo: c_int align(1);
   2744         \\
   2745     );
   2746 }
   2747 
   2748 test "zig fmt: C main" {
   2749     try testCanonical(
   2750         \\fn main(argc: c_int, argv: **u8) c_int {
   2751         \\    const a = b;
   2752         \\}
   2753         \\
   2754     );
   2755 }
   2756 
   2757 test "zig fmt: return" {
   2758     try testCanonical(
   2759         \\fn foo(argc: c_int, argv: **u8) c_int {
   2760         \\    return 0;
   2761         \\}
   2762         \\
   2763         \\fn bar() void {
   2764         \\    return;
   2765         \\}
   2766         \\
   2767     );
   2768 }
   2769 
   2770 test "zig fmt: function attributes" {
   2771     try testCanonical(
   2772         \\export fn foo() void {}
   2773         \\pub export fn foo() void {}
   2774         \\extern fn foo() void;
   2775         \\pub extern fn foo() void;
   2776         \\extern "c" fn foo() void;
   2777         \\pub extern "c" fn foo() void;
   2778         \\noinline fn foo() void {}
   2779         \\pub noinline fn foo() void {}
   2780         \\
   2781     );
   2782 }
   2783 
   2784 test "zig fmt: nested pointers with ** tokens" {
   2785     try testCanonical(
   2786         \\const x: *u32 = undefined;
   2787         \\const x: **u32 = undefined;
   2788         \\const x: ***u32 = undefined;
   2789         \\const x: ****u32 = undefined;
   2790         \\const x: *****u32 = undefined;
   2791         \\const x: ******u32 = undefined;
   2792         \\const x: *******u32 = undefined;
   2793         \\
   2794     );
   2795 }
   2796 
   2797 test "zig fmt: pointer attributes" {
   2798     try testCanonical(
   2799         \\extern fn f1(s: *align(*u8) u8) c_int;
   2800         \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
   2801         \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
   2802         \\extern fn f4(s: *align(1) const volatile u8) c_int;
   2803         \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
   2804         \\
   2805     );
   2806 }
   2807 
   2808 test "zig fmt: slice attributes" {
   2809     try testCanonical(
   2810         \\extern fn f1(s: []align(*u8) u8) c_int;
   2811         \\extern fn f2(s: []align(1) []const []volatile u8) c_int;
   2812         \\extern fn f3(s: []align(1) const [:0]align(1) volatile []const volatile u8) c_int;
   2813         \\extern fn f4(s: []align(1) const volatile u8) c_int;
   2814         \\extern fn f5(s: [:0]align(1) const volatile u8) c_int;
   2815         \\
   2816     );
   2817 }
   2818 
   2819 test "zig fmt: test declaration" {
   2820     try testCanonical(
   2821         \\test "test name" {
   2822         \\    const a = 1;
   2823         \\    var b = 1;
   2824         \\}
   2825         \\
   2826     );
   2827 }
   2828 
   2829 test "zig fmt: infix operators" {
   2830     try testCanonical(
   2831         \\test {
   2832         \\    var i = undefined;
   2833         \\    i = 2;
   2834         \\    i *= 2;
   2835         \\    i |= 2;
   2836         \\    i ^= 2;
   2837         \\    i <<= 2;
   2838         \\    i >>= 2;
   2839         \\    i &= 2;
   2840         \\    i *= 2;
   2841         \\    i *%= 2;
   2842         \\    i -= 2;
   2843         \\    i -%= 2;
   2844         \\    i += 2;
   2845         \\    i +%= 2;
   2846         \\    i /= 2;
   2847         \\    i %= 2;
   2848         \\    _ = i == i;
   2849         \\    _ = i != i;
   2850         \\    _ = i != i;
   2851         \\    _ = i.i;
   2852         \\    _ = i || i;
   2853         \\    _ = i!i;
   2854         \\    _ = i ** i;
   2855         \\    _ = i ++ i;
   2856         \\    _ = i orelse i;
   2857         \\    _ = i % i;
   2858         \\    _ = i / i;
   2859         \\    _ = i *% i;
   2860         \\    _ = i * i;
   2861         \\    _ = i -% i;
   2862         \\    _ = i - i;
   2863         \\    _ = i +% i;
   2864         \\    _ = i + i;
   2865         \\    _ = i << i;
   2866         \\    _ = i >> i;
   2867         \\    _ = i & i;
   2868         \\    _ = i ^ i;
   2869         \\    _ = i | i;
   2870         \\    _ = i >= i;
   2871         \\    _ = i <= i;
   2872         \\    _ = i > i;
   2873         \\    _ = i < i;
   2874         \\    _ = i and i;
   2875         \\    _ = i or i;
   2876         \\}
   2877         \\
   2878     );
   2879 }
   2880 
   2881 test "zig fmt: precedence" {
   2882     try testCanonical(
   2883         \\test "precedence" {
   2884         \\    a!b();
   2885         \\    (a!b)();
   2886         \\    !a!b;
   2887         \\    !(a!b);
   2888         \\    !a{};
   2889         \\    !(a{});
   2890         \\    a + b{};
   2891         \\    (a + b){};
   2892         \\    a << b + c;
   2893         \\    (a << b) + c;
   2894         \\    a & b << c;
   2895         \\    (a & b) << c;
   2896         \\    a ^ b & c;
   2897         \\    (a ^ b) & c;
   2898         \\    a | b ^ c;
   2899         \\    (a | b) ^ c;
   2900         \\    a == b | c;
   2901         \\    (a == b) | c;
   2902         \\    a and b == c;
   2903         \\    (a and b) == c;
   2904         \\    a or b and c;
   2905         \\    (a or b) and c;
   2906         \\    (a or b) and c;
   2907         \\    a == b and c == d;
   2908         \\}
   2909         \\
   2910     );
   2911 }
   2912 
   2913 test "zig fmt: prefix operators" {
   2914     try testCanonical(
   2915         \\test "prefix operators" {
   2916         \\    try return --%~!&0;
   2917         \\}
   2918         \\
   2919     );
   2920 }
   2921 
   2922 test "zig fmt: call expression" {
   2923     try testCanonical(
   2924         \\test "test calls" {
   2925         \\    a();
   2926         \\    a(1);
   2927         \\    a(1, 2);
   2928         \\    a(1, 2) + a(1, 2);
   2929         \\}
   2930         \\
   2931     );
   2932 }
   2933 
   2934 test "zig fmt: anytype type" {
   2935     try testCanonical(
   2936         \\fn print(args: anytype) @This() {}
   2937         \\
   2938     );
   2939 }
   2940 
   2941 test "zig fmt: functions" {
   2942     try testCanonical(
   2943         \\extern fn puts(s: *const u8) c_int;
   2944         \\extern "c" fn puts(s: *const u8) c_int;
   2945         \\export fn puts(s: *const u8) c_int;
   2946         \\inline fn puts(s: *const u8) c_int;
   2947         \\noinline fn puts(s: *const u8) c_int;
   2948         \\pub extern fn puts(s: *const u8) c_int;
   2949         \\pub extern "c" fn puts(s: *const u8) c_int;
   2950         \\pub export fn puts(s: *const u8) c_int;
   2951         \\pub inline fn puts(s: *const u8) c_int;
   2952         \\pub noinline fn puts(s: *const u8) c_int;
   2953         \\pub extern fn puts(s: *const u8) align(2 + 2) c_int;
   2954         \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int;
   2955         \\pub export fn puts(s: *const u8) align(2 + 2) c_int;
   2956         \\pub inline fn puts(s: *const u8) align(2 + 2) c_int;
   2957         \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int;
   2958         \\pub fn callInlineFn(func: fn () callconv(.Inline) void) void {
   2959         \\    func();
   2960         \\}
   2961         \\
   2962     );
   2963 }
   2964 
   2965 test "zig fmt: multiline string" {
   2966     try testCanonical(
   2967         \\test "" {
   2968         \\    const s1 =
   2969         \\        \\one
   2970         \\        \\two)
   2971         \\        \\three
   2972         \\    ;
   2973         \\    const s3 = // hi
   2974         \\        \\one
   2975         \\        \\two)
   2976         \\        \\three
   2977         \\    ;
   2978         \\}
   2979         \\
   2980     );
   2981 }
   2982 
   2983 test "zig fmt: values" {
   2984     try testCanonical(
   2985         \\test "values" {
   2986         \\    1;
   2987         \\    1.0;
   2988         \\    "string";
   2989         \\    'c';
   2990         \\    true;
   2991         \\    false;
   2992         \\    null;
   2993         \\    undefined;
   2994         \\    anyerror;
   2995         \\    this;
   2996         \\    unreachable;
   2997         \\}
   2998         \\
   2999     );
   3000 }
   3001 
   3002 test "zig fmt: indexing" {
   3003     try testCanonical(
   3004         \\test "test index" {
   3005         \\    a[0];
   3006         \\    a[0 + 5];
   3007         \\    a[0..];
   3008         \\    a[0..5];
   3009         \\    a[a[0]];
   3010         \\    a[a[0..]];
   3011         \\    a[a[0..5]];
   3012         \\    a[a[0]..];
   3013         \\    a[a[0..5]..];
   3014         \\    a[a[0]..a[0]];
   3015         \\    a[a[0..5]..a[0]];
   3016         \\    a[a[0..5]..a[0..5]];
   3017         \\}
   3018         \\
   3019     );
   3020 }
   3021 
   3022 test "zig fmt: struct declaration" {
   3023     try testCanonical(
   3024         \\const S = struct {
   3025         \\    const Self = @This();
   3026         \\    f1: u8,
   3027         \\    f3: u8,
   3028         \\
   3029         \\    f2: u8,
   3030         \\
   3031         \\    fn method(self: *Self) Self {
   3032         \\        return self.*;
   3033         \\    }
   3034         \\};
   3035         \\
   3036         \\const Ps = packed struct {
   3037         \\    a: u8,
   3038         \\    b: u8,
   3039         \\
   3040         \\    c: u8,
   3041         \\};
   3042         \\
   3043         \\const Es = extern struct {
   3044         \\    a: u8,
   3045         \\    b: u8,
   3046         \\
   3047         \\    c: u8,
   3048         \\};
   3049         \\
   3050     );
   3051 }
   3052 
   3053 test "zig fmt: enum declaration" {
   3054     try testCanonical(
   3055         \\const E = enum {
   3056         \\    Ok,
   3057         \\    SomethingElse = 0,
   3058         \\};
   3059         \\
   3060         \\const E2 = enum(u8) {
   3061         \\    Ok,
   3062         \\    SomethingElse = 255,
   3063         \\    SomethingThird,
   3064         \\};
   3065         \\
   3066         \\const Ee = extern enum {
   3067         \\    Ok,
   3068         \\    SomethingElse,
   3069         \\    SomethingThird,
   3070         \\};
   3071         \\
   3072         \\const Ep = packed enum {
   3073         \\    Ok,
   3074         \\    SomethingElse,
   3075         \\    SomethingThird,
   3076         \\};
   3077         \\
   3078     );
   3079 }
   3080 
   3081 test "zig fmt: union declaration" {
   3082     try testCanonical(
   3083         \\const U = union {
   3084         \\    Int: u8,
   3085         \\    Float: f32,
   3086         \\    None,
   3087         \\    Bool: bool,
   3088         \\};
   3089         \\
   3090         \\const Ue = union(enum) {
   3091         \\    Int: u8,
   3092         \\    Float: f32,
   3093         \\    None,
   3094         \\    Bool: bool,
   3095         \\};
   3096         \\
   3097         \\const E = enum {
   3098         \\    Int,
   3099         \\    Float,
   3100         \\    None,
   3101         \\    Bool,
   3102         \\};
   3103         \\
   3104         \\const Ue2 = union(E) {
   3105         \\    Int: u8,
   3106         \\    Float: f32,
   3107         \\    None,
   3108         \\    Bool: bool,
   3109         \\};
   3110         \\
   3111         \\const Eu = extern union {
   3112         \\    Int: u8,
   3113         \\    Float: f32,
   3114         \\    None,
   3115         \\    Bool: bool,
   3116         \\};
   3117         \\
   3118     );
   3119 }
   3120 
   3121 test "zig fmt: arrays" {
   3122     try testCanonical(
   3123         \\test "test array" {
   3124         \\    const a: [2]u8 = [2]u8{
   3125         \\        1,
   3126         \\        2,
   3127         \\    };
   3128         \\    const a: [2]u8 = []u8{
   3129         \\        1,
   3130         \\        2,
   3131         \\    };
   3132         \\    const a: [0]u8 = []u8{};
   3133         \\    const x: [4:0]u8 = undefined;
   3134         \\}
   3135         \\
   3136     );
   3137 }
   3138 
   3139 test "zig fmt: container initializers" {
   3140     try testCanonical(
   3141         \\const a0 = []u8{};
   3142         \\const a1 = []u8{1};
   3143         \\const a2 = []u8{
   3144         \\    1,
   3145         \\    2,
   3146         \\    3,
   3147         \\    4,
   3148         \\};
   3149         \\const s0 = S{};
   3150         \\const s1 = S{ .a = 1 };
   3151         \\const s2 = S{
   3152         \\    .a = 1,
   3153         \\    .b = 2,
   3154         \\};
   3155         \\
   3156     );
   3157 }
   3158 
   3159 test "zig fmt: catch" {
   3160     try testCanonical(
   3161         \\test "catch" {
   3162         \\    const a: anyerror!u8 = 0;
   3163         \\    _ = a catch return;
   3164         \\    _ = a catch
   3165         \\        return;
   3166         \\    _ = a catch |err| return;
   3167         \\    _ = a catch |err|
   3168         \\        return;
   3169         \\}
   3170         \\
   3171     );
   3172 }
   3173 
   3174 test "zig fmt: blocks" {
   3175     try testCanonical(
   3176         \\test "blocks" {
   3177         \\    {
   3178         \\        const a = 0;
   3179         \\        const b = 0;
   3180         \\    }
   3181         \\
   3182         \\    blk: {
   3183         \\        const a = 0;
   3184         \\        const b = 0;
   3185         \\    }
   3186         \\
   3187         \\    const r = blk: {
   3188         \\        const a = 0;
   3189         \\        const b = 0;
   3190         \\    };
   3191         \\}
   3192         \\
   3193     );
   3194 }
   3195 
   3196 test "zig fmt: switch" {
   3197     try testCanonical(
   3198         \\test "switch" {
   3199         \\    switch (0) {
   3200         \\        0 => {},
   3201         \\        1 => unreachable,
   3202         \\        2, 3 => {},
   3203         \\        4...7 => {},
   3204         \\        1 + 4 * 3 + 22 => {},
   3205         \\        else => {
   3206         \\            const a = 1;
   3207         \\            const b = a;
   3208         \\        },
   3209         \\    }
   3210         \\
   3211         \\    const res = switch (0) {
   3212         \\        0 => 0,
   3213         \\        1 => 2,
   3214         \\        1 => a = 4,
   3215         \\        else => 4,
   3216         \\    };
   3217         \\
   3218         \\    const Union = union(enum) {
   3219         \\        Int: i64,
   3220         \\        Float: f64,
   3221         \\    };
   3222         \\
   3223         \\    switch (u) {
   3224         \\        Union.Int => |int| {},
   3225         \\        Union.Float => |*float| unreachable,
   3226         \\    }
   3227         \\}
   3228         \\
   3229     );
   3230 
   3231     try testTransform(
   3232         \\test {
   3233         \\    switch (x) {
   3234         \\        foo =>
   3235         \\            "bar",
   3236         \\    }
   3237         \\}
   3238         \\
   3239     ,
   3240         \\test {
   3241         \\    switch (x) {
   3242         \\        foo => "bar",
   3243         \\    }
   3244         \\}
   3245         \\
   3246     );
   3247 }
   3248 
   3249 test "zig fmt: switch multiline string" {
   3250     try testCanonical(
   3251         \\test "switch multiline string" {
   3252         \\    const x: u32 = 0;
   3253         \\    const str = switch (x) {
   3254         \\        1 => "one",
   3255         \\        2 =>
   3256         \\        \\ Comma after the multiline string
   3257         \\        \\ is needed
   3258         \\        ,
   3259         \\        3 => "three",
   3260         \\        else => "else",
   3261         \\    };
   3262         \\
   3263         \\    const Union = union(enum) {
   3264         \\        Int: i64,
   3265         \\        Float: f64,
   3266         \\    };
   3267         \\
   3268         \\    const str = switch (u) {
   3269         \\        Union.Int => |int|
   3270         \\        \\ Comma after the multiline string
   3271         \\        \\ is needed
   3272         \\        ,
   3273         \\        Union.Float => |*float| unreachable,
   3274         \\    };
   3275         \\}
   3276         \\
   3277     );
   3278 }
   3279 
   3280 test "zig fmt: while" {
   3281     try testCanonical(
   3282         \\test "while" {
   3283         \\    while (10 < 1) unreachable;
   3284         \\
   3285         \\    while (10 < 1) unreachable else unreachable;
   3286         \\
   3287         \\    while (10 < 1) {
   3288         \\        unreachable;
   3289         \\    }
   3290         \\
   3291         \\    while (10 < 1)
   3292         \\        unreachable;
   3293         \\
   3294         \\    var i: usize = 0;
   3295         \\    while (i < 10) : (i += 1) {
   3296         \\        continue;
   3297         \\    }
   3298         \\
   3299         \\    i = 0;
   3300         \\    while (i < 10) : (i += 1)
   3301         \\        continue;
   3302         \\
   3303         \\    i = 0;
   3304         \\    var j: usize = 0;
   3305         \\    while (i < 10) : ({
   3306         \\        i += 1;
   3307         \\        j += 1;
   3308         \\    }) continue;
   3309         \\
   3310         \\    while (i < 10) : ({
   3311         \\        i += 1;
   3312         \\        j += 1;
   3313         \\    }) {
   3314         \\        continue;
   3315         \\    }
   3316         \\
   3317         \\    var a: ?u8 = 2;
   3318         \\    while (a) |v| : (a = null) {
   3319         \\        continue;
   3320         \\    }
   3321         \\
   3322         \\    while (a) |v| : (a = null)
   3323         \\        unreachable;
   3324         \\
   3325         \\    label: while (10 < 0) {
   3326         \\        unreachable;
   3327         \\    }
   3328         \\
   3329         \\    const res = while (0 < 10) {
   3330         \\        break 7;
   3331         \\    } else {
   3332         \\        unreachable;
   3333         \\    };
   3334         \\
   3335         \\    const res = while (0 < 10)
   3336         \\        break 7
   3337         \\    else
   3338         \\        unreachable;
   3339         \\
   3340         \\    var a: anyerror!u8 = 0;
   3341         \\    while (a) |v| {
   3342         \\        a = error.Err;
   3343         \\    } else |err| {
   3344         \\        i = 1;
   3345         \\    }
   3346         \\
   3347         \\    comptime var k: usize = 0;
   3348         \\    inline while (i < 10) : (i += 1)
   3349         \\        j += 2;
   3350         \\}
   3351         \\
   3352     );
   3353 }
   3354 
   3355 test "zig fmt: for" {
   3356     try testCanonical(
   3357         \\test "for" {
   3358         \\    for (a) |v| {
   3359         \\        continue;
   3360         \\    }
   3361         \\
   3362         \\    for (a) |v| continue;
   3363         \\
   3364         \\    for (a) |v| continue else return;
   3365         \\
   3366         \\    for (a) |v| {
   3367         \\        continue;
   3368         \\    } else return;
   3369         \\
   3370         \\    for (a) |v| continue else {
   3371         \\        return;
   3372         \\    }
   3373         \\
   3374         \\    for (a) |v|
   3375         \\        continue
   3376         \\    else
   3377         \\        return;
   3378         \\
   3379         \\    for (a) |v|
   3380         \\        continue;
   3381         \\
   3382         \\    for (a) |*v|
   3383         \\        continue;
   3384         \\
   3385         \\    for (a) |v, i| {
   3386         \\        continue;
   3387         \\    }
   3388         \\
   3389         \\    for (a) |v, i|
   3390         \\        continue;
   3391         \\
   3392         \\    for (a) |b| switch (b) {
   3393         \\        c => {},
   3394         \\        d => {},
   3395         \\    };
   3396         \\
   3397         \\    const res = for (a) |v, i| {
   3398         \\        break v;
   3399         \\    } else {
   3400         \\        unreachable;
   3401         \\    };
   3402         \\
   3403         \\    var num: usize = 0;
   3404         \\    inline for (a) |v, i| {
   3405         \\        num += v;
   3406         \\        num += i;
   3407         \\    }
   3408         \\}
   3409         \\
   3410     );
   3411 
   3412     try testTransform(
   3413         \\test "fix for" {
   3414         \\    for (a) |x|
   3415         \\        f(x) else continue;
   3416         \\}
   3417         \\
   3418     ,
   3419         \\test "fix for" {
   3420         \\    for (a) |x|
   3421         \\        f(x)
   3422         \\    else
   3423         \\        continue;
   3424         \\}
   3425         \\
   3426     );
   3427 }
   3428 
   3429 test "zig fmt: for if" {
   3430     try testCanonical(
   3431         \\test {
   3432         \\    for (a) |x| if (x) f(x);
   3433         \\
   3434         \\    for (a) |x| if (x)
   3435         \\        f(x);
   3436         \\
   3437         \\    for (a) |x| if (x) {
   3438         \\        f(x);
   3439         \\    };
   3440         \\
   3441         \\    for (a) |x|
   3442         \\        if (x)
   3443         \\            f(x);
   3444         \\
   3445         \\    for (a) |x|
   3446         \\        if (x) {
   3447         \\            f(x);
   3448         \\        };
   3449         \\}
   3450         \\
   3451     );
   3452 }
   3453 
   3454 test "zig fmt: if for" {
   3455     try testCanonical(
   3456         \\test {
   3457         \\    if (a) for (x) |x| f(x);
   3458         \\
   3459         \\    if (a) for (x) |x|
   3460         \\        f(x);
   3461         \\
   3462         \\    if (a) for (x) |x| {
   3463         \\        f(x);
   3464         \\    };
   3465         \\
   3466         \\    if (a)
   3467         \\        for (x) |x|
   3468         \\            f(x);
   3469         \\
   3470         \\    if (a)
   3471         \\        for (x) |x| {
   3472         \\            f(x);
   3473         \\        };
   3474         \\}
   3475         \\
   3476     );
   3477 }
   3478 
   3479 test "zig fmt: while if" {
   3480     try testCanonical(
   3481         \\test {
   3482         \\    while (a) if (x) f(x);
   3483         \\
   3484         \\    while (a) if (x)
   3485         \\        f(x);
   3486         \\
   3487         \\    while (a) if (x) {
   3488         \\        f(x);
   3489         \\    };
   3490         \\
   3491         \\    while (a)
   3492         \\        if (x)
   3493         \\            f(x);
   3494         \\
   3495         \\    while (a)
   3496         \\        if (x) {
   3497         \\            f(x);
   3498         \\        };
   3499         \\}
   3500         \\
   3501     );
   3502 }
   3503 
   3504 test "zig fmt: if while" {
   3505     try testCanonical(
   3506         \\test {
   3507         \\    if (a) while (x) : (cont) f(x);
   3508         \\
   3509         \\    if (a) while (x) : (cont)
   3510         \\        f(x);
   3511         \\
   3512         \\    if (a) while (x) : (cont) {
   3513         \\        f(x);
   3514         \\    };
   3515         \\
   3516         \\    if (a)
   3517         \\        while (x) : (cont)
   3518         \\            f(x);
   3519         \\
   3520         \\    if (a)
   3521         \\        while (x) : (cont) {
   3522         \\            f(x);
   3523         \\        };
   3524         \\}
   3525         \\
   3526     );
   3527 }
   3528 
   3529 test "zig fmt: while for" {
   3530     try testCanonical(
   3531         \\test {
   3532         \\    while (a) for (x) |x| f(x);
   3533         \\
   3534         \\    while (a) for (x) |x|
   3535         \\        f(x);
   3536         \\
   3537         \\    while (a) for (x) |x| {
   3538         \\        f(x);
   3539         \\    };
   3540         \\
   3541         \\    while (a)
   3542         \\        for (x) |x|
   3543         \\            f(x);
   3544         \\
   3545         \\    while (a)
   3546         \\        for (x) |x| {
   3547         \\            f(x);
   3548         \\        };
   3549         \\}
   3550         \\
   3551     );
   3552 }
   3553 
   3554 test "zig fmt: for while" {
   3555     try testCanonical(
   3556         \\test {
   3557         \\    for (a) |a| while (x) |x| f(x);
   3558         \\
   3559         \\    for (a) |a| while (x) |x|
   3560         \\        f(x);
   3561         \\
   3562         \\    for (a) |a| while (x) |x| {
   3563         \\        f(x);
   3564         \\    };
   3565         \\
   3566         \\    for (a) |a|
   3567         \\        while (x) |x|
   3568         \\            f(x);
   3569         \\
   3570         \\    for (a) |a|
   3571         \\        while (x) |x| {
   3572         \\            f(x);
   3573         \\        };
   3574         \\}
   3575         \\
   3576     );
   3577 }
   3578 
   3579 test "zig fmt: if" {
   3580     try testCanonical(
   3581         \\test "if" {
   3582         \\    if (10 < 0) {
   3583         \\        unreachable;
   3584         \\    }
   3585         \\
   3586         \\    if (10 < 0) unreachable;
   3587         \\
   3588         \\    if (10 < 0) {
   3589         \\        unreachable;
   3590         \\    } else {
   3591         \\        const a = 20;
   3592         \\    }
   3593         \\
   3594         \\    if (10 < 0) {
   3595         \\        unreachable;
   3596         \\    } else if (5 < 0) {
   3597         \\        unreachable;
   3598         \\    } else {
   3599         \\        const a = 20;
   3600         \\    }
   3601         \\
   3602         \\    const is_world_broken = if (10 < 0) true else false;
   3603         \\    const some_number = 1 + if (10 < 0) 2 else 3;
   3604         \\
   3605         \\    const a: ?u8 = 10;
   3606         \\    const b: ?u8 = null;
   3607         \\    if (a) |v| {
   3608         \\        const some = v;
   3609         \\    } else if (b) |*v| {
   3610         \\        unreachable;
   3611         \\    } else {
   3612         \\        const some = 10;
   3613         \\    }
   3614         \\
   3615         \\    const non_null_a = if (a) |v| v else 0;
   3616         \\
   3617         \\    const a_err: anyerror!u8 = 0;
   3618         \\    if (a_err) |v| {
   3619         \\        const p = v;
   3620         \\    } else |err| {
   3621         \\        unreachable;
   3622         \\    }
   3623         \\}
   3624         \\
   3625     );
   3626 }
   3627 
   3628 test "zig fmt: fix single statement if/for/while line breaks" {
   3629     try testTransform(
   3630         \\test {
   3631         \\    if (cond) a
   3632         \\    else b;
   3633         \\
   3634         \\    if (cond)
   3635         \\        a
   3636         \\    else b;
   3637         \\
   3638         \\    for (xs) |x| foo()
   3639         \\    else bar();
   3640         \\
   3641         \\    for (xs) |x|
   3642         \\        foo()
   3643         \\    else bar();
   3644         \\
   3645         \\    while (a) : (b) foo()
   3646         \\    else bar();
   3647         \\
   3648         \\    while (a) : (b)
   3649         \\        foo()
   3650         \\    else bar();
   3651         \\}
   3652         \\
   3653     ,
   3654         \\test {
   3655         \\    if (cond) a else b;
   3656         \\
   3657         \\    if (cond)
   3658         \\        a
   3659         \\    else
   3660         \\        b;
   3661         \\
   3662         \\    for (xs) |x| foo() else bar();
   3663         \\
   3664         \\    for (xs) |x|
   3665         \\        foo()
   3666         \\    else
   3667         \\        bar();
   3668         \\
   3669         \\    while (a) : (b) foo() else bar();
   3670         \\
   3671         \\    while (a) : (b)
   3672         \\        foo()
   3673         \\    else
   3674         \\        bar();
   3675         \\}
   3676         \\
   3677     );
   3678 }
   3679 
   3680 test "zig fmt: anon struct/array literal in if" {
   3681     try testCanonical(
   3682         \\test {
   3683         \\    const a = if (cond) .{
   3684         \\        1, 2,
   3685         \\        3, 4,
   3686         \\    } else .{
   3687         \\        1,
   3688         \\        2,
   3689         \\        3,
   3690         \\    };
   3691         \\
   3692         \\    const rl_and_tag: struct { rl: ResultLoc, tag: zir.Inst.Tag } = if (any_payload_is_ref) .{
   3693         \\        .rl = .ref,
   3694         \\        .tag = .switchbr_ref,
   3695         \\    } else .{
   3696         \\        .rl = .none,
   3697         \\        .tag = .switchbr,
   3698         \\    };
   3699         \\}
   3700         \\
   3701     );
   3702 }
   3703 
   3704 test "zig fmt: defer" {
   3705     try testCanonical(
   3706         \\test "defer" {
   3707         \\    var i: usize = 0;
   3708         \\    defer i = 1;
   3709         \\    defer {
   3710         \\        i += 2;
   3711         \\        i *= i;
   3712         \\    }
   3713         \\
   3714         \\    errdefer i += 3;
   3715         \\    errdefer {
   3716         \\        i += 2;
   3717         \\        i /= i;
   3718         \\    }
   3719         \\}
   3720         \\
   3721     );
   3722 }
   3723 
   3724 test "zig fmt: comptime" {
   3725     try testCanonical(
   3726         \\fn a() u8 {
   3727         \\    return 5;
   3728         \\}
   3729         \\
   3730         \\fn b(comptime i: u8) u8 {
   3731         \\    return i;
   3732         \\}
   3733         \\
   3734         \\const av = comptime a();
   3735         \\const av2 = comptime blk: {
   3736         \\    var res = a();
   3737         \\    res *= b(2);
   3738         \\    break :blk res;
   3739         \\};
   3740         \\
   3741         \\comptime {
   3742         \\    _ = a();
   3743         \\}
   3744         \\
   3745         \\test "comptime" {
   3746         \\    const av3 = comptime a();
   3747         \\    const av4 = comptime blk: {
   3748         \\        var res = a();
   3749         \\        res *= a();
   3750         \\        break :blk res;
   3751         \\    };
   3752         \\
   3753         \\    comptime var i = 0;
   3754         \\    comptime {
   3755         \\        i = a();
   3756         \\        i += b(i);
   3757         \\    }
   3758         \\}
   3759         \\
   3760     );
   3761 }
   3762 
   3763 test "zig fmt: fn type" {
   3764     try testCanonical(
   3765         \\fn a(i: u8) u8 {
   3766         \\    return i + 1;
   3767         \\}
   3768         \\
   3769         \\const a: fn (u8) u8 = undefined;
   3770         \\const b: fn (u8) callconv(.Naked) u8 = undefined;
   3771         \\const ap: fn (u8) u8 = a;
   3772         \\
   3773     );
   3774 }
   3775 
   3776 test "zig fmt: inline asm" {
   3777     try testCanonical(
   3778         \\pub fn syscall1(number: usize, arg1: usize) usize {
   3779         \\    return asm volatile ("syscall"
   3780         \\        : [ret] "={rax}" (-> usize),
   3781         \\        : [number] "{rax}" (number),
   3782         \\          [arg1] "{rdi}" (arg1),
   3783         \\        : "rcx", "r11"
   3784         \\    );
   3785         \\}
   3786         \\
   3787     );
   3788 }
   3789 
   3790 test "zig fmt: async functions" {
   3791     try testCanonical(
   3792         \\fn simpleAsyncFn() void {
   3793         \\    const a = async a.b();
   3794         \\    x += 1;
   3795         \\    suspend {}
   3796         \\    x += 1;
   3797         \\    suspend {}
   3798         \\    const p: anyframe->void = async simpleAsyncFn() catch unreachable;
   3799         \\    await p;
   3800         \\}
   3801         \\
   3802         \\test "suspend, resume, await" {
   3803         \\    const p: anyframe = async testAsyncSeq();
   3804         \\    resume p;
   3805         \\    await p;
   3806         \\}
   3807         \\
   3808     );
   3809 }
   3810 
   3811 test "zig fmt: nosuspend" {
   3812     try testCanonical(
   3813         \\const a = nosuspend foo();
   3814         \\
   3815     );
   3816 }
   3817 
   3818 test "zig fmt: Block after if" {
   3819     try testCanonical(
   3820         \\test {
   3821         \\    if (true) {
   3822         \\        const a = 0;
   3823         \\    }
   3824         \\
   3825         \\    {
   3826         \\        const a = 0;
   3827         \\    }
   3828         \\}
   3829         \\
   3830     );
   3831 }
   3832 
   3833 test "zig fmt: usingnamespace" {
   3834     try testCanonical(
   3835         \\usingnamespace @import("std");
   3836         \\pub usingnamespace @import("std");
   3837         \\
   3838     );
   3839 }
   3840 
   3841 test "zig fmt: string identifier" {
   3842     try testCanonical(
   3843         \\const @"a b" = @"c d".@"e f";
   3844         \\fn @"g h"() void {}
   3845         \\
   3846     );
   3847 }
   3848 
   3849 test "zig fmt: error return" {
   3850     try testCanonical(
   3851         \\fn err() anyerror {
   3852         \\    call();
   3853         \\    return error.InvalidArgs;
   3854         \\}
   3855         \\
   3856     );
   3857 }
   3858 
   3859 test "zig fmt: comptime block in container" {
   3860     try testCanonical(
   3861         \\pub fn container() type {
   3862         \\    return struct {
   3863         \\        comptime {
   3864         \\            if (false) {
   3865         \\                unreachable;
   3866         \\            }
   3867         \\        }
   3868         \\    };
   3869         \\}
   3870         \\
   3871     );
   3872 }
   3873 
   3874 test "zig fmt: inline asm parameter alignment" {
   3875     try testCanonical(
   3876         \\pub fn main() void {
   3877         \\    asm volatile (
   3878         \\        \\ foo
   3879         \\        \\ bar
   3880         \\    );
   3881         \\    asm volatile (
   3882         \\        \\ foo
   3883         \\        \\ bar
   3884         \\        : [_] "" (-> usize),
   3885         \\          [_] "" (-> usize),
   3886         \\    );
   3887         \\    asm volatile (
   3888         \\        \\ foo
   3889         \\        \\ bar
   3890         \\        :
   3891         \\        : [_] "" (0),
   3892         \\          [_] "" (0),
   3893         \\    );
   3894         \\    asm volatile (
   3895         \\        \\ foo
   3896         \\        \\ bar
   3897         \\        ::: "", "");
   3898         \\    asm volatile (
   3899         \\        \\ foo
   3900         \\        \\ bar
   3901         \\        : [_] "" (-> usize),
   3902         \\          [_] "" (-> usize),
   3903         \\        : [_] "" (0),
   3904         \\          [_] "" (0),
   3905         \\        : "", ""
   3906         \\    );
   3907         \\}
   3908         \\
   3909     );
   3910 }
   3911 
   3912 test "zig fmt: multiline string in array" {
   3913     try testCanonical(
   3914         \\const Foo = [][]const u8{
   3915         \\    \\aaa
   3916         \\    ,
   3917         \\    \\bbb
   3918         \\};
   3919         \\
   3920         \\fn bar() void {
   3921         \\    const Foo = [][]const u8{
   3922         \\        \\aaa
   3923         \\        ,
   3924         \\        \\bbb
   3925         \\    };
   3926         \\    const Bar = [][]const u8{ // comment here
   3927         \\        \\aaa
   3928         \\        \\
   3929         \\        , // and another comment can go here
   3930         \\        \\bbb
   3931         \\    };
   3932         \\}
   3933         \\
   3934     );
   3935 }
   3936 
   3937 test "zig fmt: if type expr" {
   3938     try testCanonical(
   3939         \\const mycond = true;
   3940         \\pub fn foo() if (mycond) i32 else void {
   3941         \\    if (mycond) {
   3942         \\        return 42;
   3943         \\    }
   3944         \\}
   3945         \\
   3946     );
   3947 }
   3948 test "zig fmt: file ends with struct field" {
   3949     try testCanonical(
   3950         \\a: bool
   3951         \\
   3952     );
   3953 }
   3954 
   3955 test "zig fmt: comment after empty comment" {
   3956     try testCanonical(
   3957         \\const x = true; //
   3958         \\//
   3959         \\//
   3960         \\//a
   3961         \\
   3962     );
   3963 }
   3964 
   3965 test "zig fmt: line comment in array" {
   3966     try testTransform(
   3967         \\test "a" {
   3968         \\    var arr = [_]u32{
   3969         \\        0
   3970         \\        // 1,
   3971         \\        // 2,
   3972         \\    };
   3973         \\}
   3974         \\
   3975     ,
   3976         \\test "a" {
   3977         \\    var arr = [_]u32{
   3978         \\        0,
   3979         \\        // 1,
   3980         \\        // 2,
   3981         \\    };
   3982         \\}
   3983         \\
   3984     );
   3985     try testCanonical(
   3986         \\test "a" {
   3987         \\    var arr = [_]u32{
   3988         \\        0,
   3989         \\        // 1,
   3990         \\        // 2,
   3991         \\    };
   3992         \\}
   3993         \\
   3994     );
   3995 }
   3996 
   3997 test "zig fmt: comment after params" {
   3998     try testTransform(
   3999         \\fn a(
   4000         \\    b: u32
   4001         \\    // c: u32,
   4002         \\    // d: u32,
   4003         \\) void {}
   4004         \\
   4005     ,
   4006         \\fn a(
   4007         \\    b: u32,
   4008         \\    // c: u32,
   4009         \\    // d: u32,
   4010         \\) void {}
   4011         \\
   4012     );
   4013     try testCanonical(
   4014         \\fn a(
   4015         \\    b: u32,
   4016         \\    // c: u32,
   4017         \\    // d: u32,
   4018         \\) void {}
   4019         \\
   4020     );
   4021 }
   4022 
   4023 test "zig fmt: comment in array initializer/access" {
   4024     try testCanonical(
   4025         \\test "a" {
   4026         \\    var a = x{ //aa
   4027         \\        //bb
   4028         \\    };
   4029         \\    var a = []x{ //aa
   4030         \\        //bb
   4031         \\    };
   4032         \\    var b = [ //aa
   4033         \\        _
   4034         \\    ]x{ //aa
   4035         \\        //bb
   4036         \\        9,
   4037         \\    };
   4038         \\    var c = b[ //aa
   4039         \\        0
   4040         \\    ];
   4041         \\    var d = [
   4042         \\        _
   4043         \\        //aa
   4044         \\        :
   4045         \\        0
   4046         \\    ]x{ //aa
   4047         \\        //bb
   4048         \\        9,
   4049         \\    };
   4050         \\    var e = d[
   4051         \\        0
   4052         \\        //aa
   4053         \\    ];
   4054         \\}
   4055         \\
   4056     );
   4057 }
   4058 
   4059 test "zig fmt: comments at several places in struct init" {
   4060     try testTransform(
   4061         \\var bar = Bar{
   4062         \\    .x = 10, // test
   4063         \\    .y = "test"
   4064         \\    // test
   4065         \\};
   4066         \\
   4067     ,
   4068         \\var bar = Bar{
   4069         \\    .x = 10, // test
   4070         \\    .y = "test",
   4071         \\    // test
   4072         \\};
   4073         \\
   4074     );
   4075 
   4076     try testCanonical(
   4077         \\var bar = Bar{ // test
   4078         \\    .x = 10, // test
   4079         \\    .y = "test",
   4080         \\    // test
   4081         \\};
   4082         \\
   4083     );
   4084 }
   4085 
   4086 test "zig fmt: container doc comments" {
   4087     try testCanonical(
   4088         \\//! tld 1
   4089         \\//! tld 2
   4090         \\//! tld 3
   4091         \\
   4092         \\// comment
   4093         \\
   4094         \\/// A doc
   4095         \\const A = struct {
   4096         \\    //! A tld 1
   4097         \\    //! A tld 2
   4098         \\    //! A tld 3
   4099         \\};
   4100         \\
   4101         \\/// B doc
   4102         \\const B = struct {
   4103         \\    //! B tld 1
   4104         \\    //! B tld 2
   4105         \\    //! B tld 3
   4106         \\
   4107         \\    /// B doc
   4108         \\    b: u32,
   4109         \\};
   4110         \\
   4111         \\/// C doc
   4112         \\const C = union(enum) { // comment
   4113         \\    //! C tld 1
   4114         \\    //! C tld 2
   4115         \\    //! C tld 3
   4116         \\};
   4117         \\
   4118         \\/// D doc
   4119         \\const D = union(Foo) {
   4120         \\    //! D tld 1
   4121         \\    //! D tld 2
   4122         \\    //! D tld 3
   4123         \\
   4124         \\    /// D doc
   4125         \\    b: u32,
   4126         \\};
   4127         \\
   4128     );
   4129     try testCanonical(
   4130         \\//! Top-level documentation.
   4131         \\
   4132         \\/// This is A
   4133         \\pub const A = usize;
   4134         \\
   4135     );
   4136     try testCanonical(
   4137         \\//! Nothing here
   4138         \\
   4139     );
   4140 }
   4141 
   4142 test "zig fmt: anytype struct field" {
   4143     try testError(
   4144         \\pub const Pointer = struct {
   4145         \\    sentinel: anytype,
   4146         \\};
   4147         \\
   4148     , &[_]Error{
   4149         .expected_type_expr,
   4150     });
   4151 }
   4152 
   4153 test "zig fmt: extern without container keyword returns error" {
   4154     try testError(
   4155         \\const container = extern {};
   4156         \\
   4157     , &[_]Error{
   4158         .expected_container,
   4159     });
   4160 }
   4161 
   4162 test "zig fmt: same line doc comment returns error" {
   4163     try testError(
   4164         \\const Foo = struct{
   4165         \\    bar: u32, /// comment
   4166         \\    foo: u32, /// comment
   4167         \\    /// commment
   4168         \\};
   4169         \\
   4170         \\const a = 42; /// comment
   4171         \\
   4172         \\extern fn foo() void; /// comment
   4173         \\
   4174         \\/// comment
   4175         \\
   4176     , &[_]Error{
   4177         .same_line_doc_comment,
   4178         .same_line_doc_comment,
   4179         .unattached_doc_comment,
   4180         .same_line_doc_comment,
   4181         .same_line_doc_comment,
   4182         .unattached_doc_comment,
   4183     });
   4184 }
   4185 
   4186 test "zig fmt: integer literals with underscore separators" {
   4187     try testTransform(
   4188         \\const
   4189         \\ x     =
   4190         \\ 1_234_567
   4191         \\ +(0b0_1-0o7_0+0xff_FF ) +  0_0;
   4192     ,
   4193         \\const x =
   4194         \\    1_234_567 + (0b0_1 - 0o7_0 + 0xff_FF) + 0_0;
   4195         \\
   4196     );
   4197 }
   4198 
   4199 test "zig fmt: hex literals with underscore separators" {
   4200     try testTransform(
   4201         \\pub fn orMask(a: [ 1_000 ]u64, b: [  1_000]  u64) [1_000]u64 {
   4202         \\    var c: [1_000]u64 =  [1]u64{ 0xFFFF_FFFF_FFFF_FFFF}**1_000;
   4203         \\    for (c [ 0_0 .. ]) |_, i| {
   4204         \\        c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
   4205         \\    }
   4206         \\    return c;
   4207         \\}
   4208         \\
   4209         \\
   4210     ,
   4211         \\pub fn orMask(a: [1_000]u64, b: [1_000]u64) [1_000]u64 {
   4212         \\    var c: [1_000]u64 = [1]u64{0xFFFF_FFFF_FFFF_FFFF} ** 1_000;
   4213         \\    for (c[0_0..]) |_, i| {
   4214         \\        c[i] = (a[i] | b[i]) & 0xCCAA_CCAA_CCAA_CCAA;
   4215         \\    }
   4216         \\    return c;
   4217         \\}
   4218         \\
   4219     );
   4220 }
   4221 
   4222 test "zig fmt: decimal float literals with underscore separators" {
   4223     try testTransform(
   4224         \\pub fn main() void {
   4225         \\    const a:f64=(10.0e-0+(10.0e+0))+10_00.00_00e-2+00_00.00_10e+4;
   4226         \\    const b:f64=010.0--0_10.0+0_1_0.0_0+1e2;
   4227         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4228         \\}
   4229     ,
   4230         \\pub fn main() void {
   4231         \\    const a: f64 = (10.0e-0 + (10.0e+0)) + 10_00.00_00e-2 + 00_00.00_10e+4;
   4232         \\    const b: f64 = 010.0 - -0_10.0 + 0_1_0.0_0 + 1e2;
   4233         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4234         \\}
   4235         \\
   4236     );
   4237 }
   4238 
   4239 test "zig fmt: hexadeciaml float literals with underscore separators" {
   4240     try testTransform(
   4241         \\pub fn main() void {
   4242         \\    const a: f64 = (0x10.0p-0+(0x10.0p+0))+0x10_00.00_00p-8+0x00_00.00_10p+16;
   4243         \\    const b: f64 = 0x0010.0--0x00_10.0+0x10.00+0x1p4;
   4244         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4245         \\}
   4246     ,
   4247         \\pub fn main() void {
   4248         \\    const a: f64 = (0x10.0p-0 + (0x10.0p+0)) + 0x10_00.00_00p-8 + 0x00_00.00_10p+16;
   4249         \\    const b: f64 = 0x0010.0 - -0x00_10.0 + 0x10.00 + 0x1p4;
   4250         \\    std.debug.warn("a: {}, b: {} -> a+b: {}\n", .{ a, b, a + b });
   4251         \\}
   4252         \\
   4253     );
   4254 }
   4255 
   4256 test "zig fmt: C var args" {
   4257     try testCanonical(
   4258         \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
   4259         \\
   4260     );
   4261 }
   4262 
   4263 test "zig fmt: Only indent multiline string literals in function calls" {
   4264     try testCanonical(
   4265         \\test "zig fmt:" {
   4266         \\    try testTransform(
   4267         \\        \\const X = struct {
   4268         \\        \\    foo: i32, bar: i8 };
   4269         \\    ,
   4270         \\        \\const X = struct {
   4271         \\        \\    foo: i32, bar: i8
   4272         \\        \\};
   4273         \\        \\
   4274         \\    );
   4275         \\}
   4276         \\
   4277     );
   4278 }
   4279 
   4280 test "zig fmt: Don't add extra newline after if" {
   4281     try testCanonical(
   4282         \\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
   4283         \\    if (cwd().symLink(existing_path, new_path, .{})) {
   4284         \\        return;
   4285         \\    }
   4286         \\}
   4287         \\
   4288     );
   4289 }
   4290 
   4291 test "zig fmt: comments in ternary ifs" {
   4292     try testCanonical(
   4293         \\const x = if (true) {
   4294         \\    1;
   4295         \\} else if (false)
   4296         \\    // Comment
   4297         \\    0;
   4298         \\const y = if (true)
   4299         \\    // Comment
   4300         \\    1
   4301         \\else
   4302         \\    // Comment
   4303         \\    0;
   4304         \\
   4305         \\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
   4306         \\
   4307     );
   4308 }
   4309 
   4310 test "zig fmt: while statement in blockless if" {
   4311     try testCanonical(
   4312         \\pub fn main() void {
   4313         \\    const zoom_node = if (focused_node == layout_first)
   4314         \\        while (it.next()) |node| {
   4315         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4316         \\        } else null
   4317         \\    else
   4318         \\        focused_node;
   4319         \\}
   4320         \\
   4321     );
   4322 }
   4323 
   4324 test "zig fmt: test comments in field access chain" {
   4325     try testCanonical(
   4326         \\pub const str = struct {
   4327         \\    pub const Thing = more.more //
   4328         \\        .more() //
   4329         \\        .more().more() //
   4330         \\        .more() //
   4331         \\    // .more() //
   4332         \\        .more() //
   4333         \\        .more();
   4334         \\    data: Data,
   4335         \\};
   4336         \\
   4337         \\pub const str = struct {
   4338         \\    pub const Thing = more.more //
   4339         \\        .more() //
   4340         \\    // .more() //
   4341         \\    // .more() //
   4342         \\    // .more() //
   4343         \\        .more() //
   4344         \\        .more();
   4345         \\    data: Data,
   4346         \\};
   4347         \\
   4348         \\pub const str = struct {
   4349         \\    pub const Thing = more //
   4350         \\        .more //
   4351         \\        .more() //
   4352         \\        .more();
   4353         \\    data: Data,
   4354         \\};
   4355         \\
   4356     );
   4357 }
   4358 
   4359 test "zig fmt: allow line break before field access" {
   4360     try testCanonical(
   4361         \\test {
   4362         \\    const w = foo.bar().zippy(zag).iguessthisisok();
   4363         \\
   4364         \\    const x = foo
   4365         \\        .bar()
   4366         \\        . // comment
   4367         \\    // comment
   4368         \\        swooop().zippy(zag)
   4369         \\        .iguessthisisok();
   4370         \\
   4371         \\    const y = view.output.root.server.input_manager.default_seat.wlr_seat.name;
   4372         \\
   4373         \\    const z = view.output.root.server
   4374         \\        .input_manager //
   4375         \\        .default_seat
   4376         \\        . // comment
   4377         \\    // another comment
   4378         \\        wlr_seat.name;
   4379         \\}
   4380         \\
   4381     );
   4382     try testTransform(
   4383         \\test {
   4384         \\    const x = foo.
   4385         \\        bar()
   4386         \\        .zippy(zag).iguessthisisok();
   4387         \\
   4388         \\    const z = view.output.root.server.
   4389         \\        input_manager.
   4390         \\        default_seat.wlr_seat.name;
   4391         \\}
   4392         \\
   4393     ,
   4394         \\test {
   4395         \\    const x = foo
   4396         \\        .bar()
   4397         \\        .zippy(zag).iguessthisisok();
   4398         \\
   4399         \\    const z = view.output.root.server
   4400         \\        .input_manager
   4401         \\        .default_seat.wlr_seat.name;
   4402         \\}
   4403         \\
   4404     );
   4405 }
   4406 
   4407 test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
   4408     try testCanonical(
   4409         \\fn foo() void {
   4410         \\    z.display_message_dialog(
   4411         \\        *const [323:0]u8,
   4412         \\        \\Message Text
   4413         \\        \\------------
   4414         \\        \\xxxxxxxxxxxx
   4415         \\        \\xxxxxxxxxxxx
   4416         \\    ,
   4417         \\        g.GtkMessageType.GTK_MESSAGE_WARNING,
   4418         \\        null,
   4419         \\    );
   4420         \\
   4421         \\    z.display_message_dialog(*const [323:0]u8,
   4422         \\        \\Message Text
   4423         \\        \\------------
   4424         \\        \\xxxxxxxxxxxx
   4425         \\        \\xxxxxxxxxxxx
   4426         \\    , g.GtkMessageType.GTK_MESSAGE_WARNING, null);
   4427         \\}
   4428         \\
   4429     );
   4430 }
   4431 
   4432 test "zig fmt: Control flow statement as body of blockless if" {
   4433     try testCanonical(
   4434         \\pub fn main() void {
   4435         \\    const zoom_node = if (focused_node == layout_first)
   4436         \\        if (it.next()) {
   4437         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4438         \\        } else null
   4439         \\    else
   4440         \\        focused_node;
   4441         \\
   4442         \\    const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
   4443         \\        if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4444         \\    } else null else focused_node;
   4445         \\
   4446         \\    const zoom_node = if (focused_node == layout_first)
   4447         \\        if (it.next()) {
   4448         \\            if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4449         \\        } else null;
   4450         \\
   4451         \\    const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
   4452         \\        if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
   4453         \\    };
   4454         \\
   4455         \\    const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
   4456         \\        break node;
   4457         \\    };
   4458         \\
   4459         \\    const zoom_node = if (focused_node == layout_first) switch (nodes) {
   4460         \\        0 => 0,
   4461         \\    } else focused_node;
   4462         \\}
   4463         \\
   4464     );
   4465 }
   4466 
   4467 test "zig fmt: regression test for #5722" {
   4468     try testCanonical(
   4469         \\pub fn sendViewTags(self: Self) void {
   4470         \\    var it = ViewStack(View).iterator(self.output.views.first, std.math.maxInt(u32));
   4471         \\    while (it.next()) |node|
   4472         \\        view_tags.append(node.view.current_tags) catch {
   4473         \\            c.wl_resource_post_no_memory(self.wl_resource);
   4474         \\            log.err(.river_status, "out of memory", .{});
   4475         \\            return;
   4476         \\        };
   4477         \\}
   4478         \\
   4479     );
   4480 }
   4481 
   4482 test "zig fmt: regression test for #8974" {
   4483     try testCanonical(
   4484         \\pub const VARIABLE;
   4485         \\
   4486     );
   4487 }
   4488 
   4489 test "zig fmt: allow trailing line comments to do manual array formatting" {
   4490     try testCanonical(
   4491         \\fn foo() void {
   4492         \\    self.code.appendSliceAssumeCapacity(&[_]u8{
   4493         \\        0x55, // push rbp
   4494         \\        0x48, 0x89, 0xe5, // mov rbp, rsp
   4495         \\        0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
   4496         \\    });
   4497         \\
   4498         \\    di_buf.appendAssumeCapacity(&[_]u8{
   4499         \\        1, DW.TAG_compile_unit, DW.CHILDREN_no, // header
   4500         \\        DW.AT_stmt_list, DW_FORM_data4, // form value pairs
   4501         \\        DW.AT_low_pc,    DW_FORM_addr,
   4502         \\        DW.AT_high_pc,   DW_FORM_addr,
   4503         \\        DW.AT_name,      DW_FORM_strp,
   4504         \\        DW.AT_comp_dir,  DW_FORM_strp,
   4505         \\        DW.AT_producer,  DW_FORM_strp,
   4506         \\        DW.AT_language,  DW_FORM_data2,
   4507         \\        0, 0, // sentinel
   4508         \\    });
   4509         \\
   4510         \\    self.code.appendSliceAssumeCapacity(&[_]u8{
   4511         \\        0x55, // push rbp
   4512         \\        0x48, 0x89, 0xe5, // mov rbp, rsp
   4513         \\        // How do we handle this?
   4514         \\        //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
   4515         \\        // Here's a blank line, should that be allowed?
   4516         \\
   4517         \\        0x48, 0x89, 0xe5,
   4518         \\        0x33, 0x45,
   4519         \\        // Now the comment breaks a single line -- how do we handle this?
   4520         \\        0x88,
   4521         \\    });
   4522         \\}
   4523         \\
   4524     );
   4525 }
   4526 
   4527 test "zig fmt: multiline string literals should play nice with array initializers" {
   4528     try testCanonical(
   4529         \\fn main() void {
   4530         \\    var a = .{.{.{.{.{.{.{.{
   4531         \\        0,
   4532         \\    }}}}}}}};
   4533         \\    myFunc(.{
   4534         \\        "aaaaaaa",                           "bbbbbb", "ccccc",
   4535         \\        "dddd",                              ("eee"),  ("fff"),
   4536         \\        ("gggg"),
   4537         \\        // Line comment
   4538         \\        \\Multiline String Literals can be quite long
   4539         \\        ,
   4540         \\        \\Multiline String Literals can be quite long
   4541         \\        \\Multiline String Literals can be quite long
   4542         \\        ,
   4543         \\        \\Multiline String Literals can be quite long
   4544         \\        \\Multiline String Literals can be quite long
   4545         \\        \\Multiline String Literals can be quite long
   4546         \\        \\Multiline String Literals can be quite long
   4547         \\        ,
   4548         \\        (
   4549         \\            \\Multiline String Literals can be quite long
   4550         \\        ),
   4551         \\        .{
   4552         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4553         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4554         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4555         \\        },
   4556         \\        .{(
   4557         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4558         \\        )},
   4559         \\        .{
   4560         \\            "xxxxxxx", "xxx",
   4561         \\            (
   4562         \\                \\ xxx
   4563         \\            ),
   4564         \\            "xxx",
   4565         \\            "xxx",
   4566         \\        },
   4567         \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
   4568         \\        .{ "xxxxxxx", "xxx", "xxx", "xxx" },
   4569         \\        "aaaaaaa", "bbbbbb", "ccccc", // -
   4570         \\        "dddd",    ("eee"),  ("fff"),
   4571         \\        .{
   4572         \\            "xxx",            "xxx",
   4573         \\            (
   4574         \\                \\ xxx
   4575         \\            ),
   4576         \\            "xxxxxxxxxxxxxx",
   4577         \\            "xxx",
   4578         \\        },
   4579         \\        .{
   4580         \\            (
   4581         \\                \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4582         \\            ),
   4583         \\            \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4584         \\        },
   4585         \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4586         \\        \\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   4587         \\    });
   4588         \\}
   4589         \\
   4590     );
   4591 }
   4592 
   4593 test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
   4594     try testCanonical(
   4595         \\pub fn makeMemUndefined(qzz: []u8) i1 {
   4596         \\    cases.add( // fixed bug foo
   4597         \\        "compile diagnostic string for top level decl type",
   4598         \\        \\export fn entry() void {
   4599         \\        \\    var foo: u32 = @This(){};
   4600         \\        \\}
   4601         \\    , &[_][]const u8{
   4602         \\        "tmp.zig:2:27: error: type 'u32' does not support array initialization",
   4603         \\    });
   4604         \\    @compileError(
   4605         \\        \\ unknown-length pointers and C pointers cannot be hashed deeply.
   4606         \\        \\ Consider providing your own hash function.
   4607         \\        \\ unknown-length pointers and C pointers cannot be hashed deeply.
   4608         \\        \\ Consider providing your own hash function.
   4609         \\    );
   4610         \\    return @intCast(i1, doMemCheckClientRequestExpr(0, // default return
   4611         \\        .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0));
   4612         \\}
   4613         \\
   4614         \\// This looks like garbage don't do this
   4615         \\const rparen = tree.prevToken(
   4616         \\// the first token for the annotation expressions is the left
   4617         \\// parenthesis, hence the need for two prevToken
   4618         \\if (fn_proto.getAlignExpr()) |align_expr|
   4619         \\    tree.prevToken(tree.prevToken(align_expr.firstToken()))
   4620         \\else if (fn_proto.getSectionExpr()) |section_expr|
   4621         \\    tree.prevToken(tree.prevToken(section_expr.firstToken()))
   4622         \\else if (fn_proto.getCallconvExpr()) |callconv_expr|
   4623         \\    tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
   4624         \\else switch (fn_proto.return_type) {
   4625         \\    .Explicit => |node| node.firstToken(),
   4626         \\    .InferErrorSet => |node| tree.prevToken(node.firstToken()),
   4627         \\    .Invalid => unreachable,
   4628         \\});
   4629         \\
   4630     );
   4631 }
   4632 
   4633 test "zig fmt: single argument trailing commas in @builtins()" {
   4634     try testCanonical(
   4635         \\pub fn foo(qzz: []u8) i1 {
   4636         \\    @panic(
   4637         \\        foo,
   4638         \\    );
   4639         \\    panic(
   4640         \\        foo,
   4641         \\    );
   4642         \\    @panic(
   4643         \\        foo,
   4644         \\        bar,
   4645         \\    );
   4646         \\}
   4647         \\
   4648     );
   4649 }
   4650 
   4651 test "zig fmt: trailing comma should force multiline 1 column" {
   4652     try testTransform(
   4653         \\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
   4654         \\
   4655     ,
   4656         \\pub const UUID_NULL: uuid_t = [16]u8{
   4657         \\    0,
   4658         \\    0,
   4659         \\    0,
   4660         \\    0,
   4661         \\};
   4662         \\
   4663     );
   4664 }
   4665 
   4666 test "zig fmt: function params should align nicely" {
   4667     try testCanonical(
   4668         \\pub fn foo() void {
   4669         \\    cases.addRuntimeSafety("slicing operator with sentinel",
   4670         \\        \\const std = @import("std");
   4671         \\    ++ check_panic_msg ++
   4672         \\        \\pub fn main() void {
   4673         \\        \\    var buf = [4]u8{'a','b','c',0};
   4674         \\        \\    const slice = buf[0..:0];
   4675         \\        \\}
   4676         \\    );
   4677         \\}
   4678         \\
   4679     );
   4680 }
   4681 
   4682 test "zig fmt: fn proto end with anytype and comma" {
   4683     try testCanonical(
   4684         \\pub fn format(
   4685         \\    out_stream: anytype,
   4686         \\) !void {}
   4687         \\
   4688     );
   4689 }
   4690 
   4691 test "zig fmt: space after top level doc comment" {
   4692     try testCanonical(
   4693         \\//! top level doc comment
   4694         \\
   4695         \\field: i32,
   4696         \\
   4697     );
   4698 }
   4699 
   4700 test "zig fmt: for loop with ptr payload and index" {
   4701     try testCanonical(
   4702         \\test {
   4703         \\    for (self.entries.items) |*item, i| {}
   4704         \\    for (self.entries.items) |*item, i|
   4705         \\        a = b;
   4706         \\    for (self.entries.items) |*item, i| a = b;
   4707         \\}
   4708         \\
   4709     );
   4710 }
   4711 
   4712 test "zig fmt: proper indent line comment after multi-line single expr while loop" {
   4713     try testCanonical(
   4714         \\test {
   4715         \\    while (a) : (b)
   4716         \\        foo();
   4717         \\
   4718         \\    // bar
   4719         \\    baz();
   4720         \\}
   4721         \\
   4722     );
   4723 }
   4724 
   4725 test "zig fmt: function with labeled block as return type" {
   4726     try testCanonical(
   4727         \\fn foo() t: {
   4728         \\    break :t bar;
   4729         \\} {
   4730         \\    baz();
   4731         \\}
   4732         \\
   4733     );
   4734 }
   4735 
   4736 test "zig fmt: extern function with missing param name" {
   4737     try testCanonical(
   4738         \\extern fn a(
   4739         \\    *b,
   4740         \\    c: *d,
   4741         \\) e;
   4742         \\extern fn f(*g, h: *i) j;
   4743         \\
   4744     );
   4745 }
   4746 
   4747 test "zig fmt: line comment after multiline single expr if statement with multiline string" {
   4748     try testCanonical(
   4749         \\test {
   4750         \\    if (foo)
   4751         \\        x =
   4752         \\            \\hello
   4753         \\            \\hello
   4754         \\            \\
   4755         \\        ;
   4756         \\
   4757         \\    // bar
   4758         \\    baz();
   4759         \\
   4760         \\    if (foo)
   4761         \\        x =
   4762         \\            \\hello
   4763         \\            \\hello
   4764         \\            \\
   4765         \\    else
   4766         \\        y =
   4767         \\            \\hello
   4768         \\            \\hello
   4769         \\            \\
   4770         \\        ;
   4771         \\
   4772         \\    // bar
   4773         \\    baz();
   4774         \\}
   4775         \\
   4776     );
   4777 }
   4778 
   4779 test "zig fmt: respect extra newline between fn and pub usingnamespace" {
   4780     try testCanonical(
   4781         \\fn foo() void {
   4782         \\    bar();
   4783         \\}
   4784         \\
   4785         \\pub usingnamespace baz;
   4786         \\
   4787     );
   4788 }
   4789 
   4790 test "zig fmt: respect extra newline between switch items" {
   4791     try testCanonical(
   4792         \\const a = switch (b) {
   4793         \\    .c => {},
   4794         \\
   4795         \\    .d,
   4796         \\    .e,
   4797         \\    => f,
   4798         \\};
   4799         \\
   4800     );
   4801 }
   4802 
   4803 test "zig fmt: assignment with inline for and inline while" {
   4804     try testCanonical(
   4805         \\const tmp = inline for (items) |item| {};
   4806         \\
   4807     );
   4808 
   4809     try testCanonical(
   4810         \\const tmp2 = inline while (true) {};
   4811         \\
   4812     );
   4813 }
   4814 
   4815 test "zig fmt: saturating arithmetic" {
   4816     try testCanonical(
   4817         \\test {
   4818         \\    const actual = switch (op) {
   4819         \\        .add => a +| b,
   4820         \\        .sub => a -| b,
   4821         \\        .mul => a *| b,
   4822         \\        .shl => a <<| b,
   4823         \\    };
   4824         \\    switch (op) {
   4825         \\        .add => actual +|= b,
   4826         \\        .sub => actual -|= b,
   4827         \\        .mul => actual *|= b,
   4828         \\        .shl => actual <<|= b,
   4829         \\    }
   4830         \\}
   4831         \\
   4832     );
   4833 }
   4834 
   4835 test "zig fmt: insert trailing comma if there are comments between switch values" {
   4836     try testTransform(
   4837         \\const a = switch (b) {
   4838         \\    .c => {},
   4839         \\
   4840         \\    .d, // foobar
   4841         \\    .e
   4842         \\    => f,
   4843         \\
   4844         \\    .g, .h
   4845         \\    // comment
   4846         \\    => i,
   4847         \\};
   4848         \\
   4849     ,
   4850         \\const a = switch (b) {
   4851         \\    .c => {},
   4852         \\
   4853         \\    .d, // foobar
   4854         \\    .e,
   4855         \\    => f,
   4856         \\
   4857         \\    .g,
   4858         \\    .h,
   4859         \\    // comment
   4860         \\    => i,
   4861         \\};
   4862         \\
   4863     );
   4864 }
   4865 
   4866 test "zig fmt: insert trailing comma if comments in array init" {
   4867     try testTransform(
   4868         \\var a = .{
   4869         \\    "foo", //
   4870         \\    "bar"
   4871         \\};
   4872         \\var a = .{
   4873         \\    "foo",
   4874         \\    "bar" //
   4875         \\};
   4876         \\var a = .{
   4877         \\    "foo",
   4878         \\    "//"
   4879         \\};
   4880         \\var a = .{
   4881         \\    "foo",
   4882         \\    "//" //
   4883         \\};
   4884         \\
   4885     ,
   4886         \\var a = .{
   4887         \\    "foo", //
   4888         \\    "bar",
   4889         \\};
   4890         \\var a = .{
   4891         \\    "foo",
   4892         \\    "bar", //
   4893         \\};
   4894         \\var a = .{ "foo", "//" };
   4895         \\var a = .{
   4896         \\    "foo",
   4897         \\    "//", //
   4898         \\};
   4899         \\
   4900     );
   4901 }
   4902 
   4903 test "zig fmt: make single-line if no trailing comma" {
   4904     try testTransform(
   4905         \\test "function call no trailing comma" {
   4906         \\    foo(
   4907         \\        1,
   4908         \\        2
   4909         \\    );
   4910         \\}
   4911         \\
   4912     ,
   4913         \\test "function call no trailing comma" {
   4914         \\    foo(1, 2);
   4915         \\}
   4916         \\
   4917     );
   4918 
   4919     try testTransform(
   4920         \\test "struct no trailing comma" {
   4921         \\    const a = .{
   4922         \\        .foo = 1,
   4923         \\        .bar = 2
   4924         \\    };
   4925         \\}
   4926         \\
   4927     ,
   4928         \\test "struct no trailing comma" {
   4929         \\    const a = .{ .foo = 1, .bar = 2 };
   4930         \\}
   4931         \\
   4932     );
   4933 
   4934     try testTransform(
   4935         \\test "array no trailing comma" {
   4936         \\    var stream = multiOutStream(.{
   4937         \\        fbs1.outStream(),
   4938         \\        fbs2.outStream()
   4939         \\    });
   4940         \\}
   4941         \\
   4942     ,
   4943         \\test "array no trailing comma" {
   4944         \\    var stream = multiOutStream(.{ fbs1.outStream(), fbs2.outStream() });
   4945         \\}
   4946         \\
   4947     );
   4948 }
   4949 
   4950 test "zig fmt: make single-line if no trailing comma" {
   4951     try testCanonical(
   4952         \\// Test trailing comma syntax
   4953         \\// zig fmt: off
   4954         \\
   4955         \\extern var a: c_int;
   4956         \\extern "c" var b: c_int;
   4957         \\export var c: c_int = 0;
   4958         \\threadlocal var d: c_int = 0;
   4959         \\extern threadlocal var e: c_int;
   4960         \\extern "c" threadlocal var f: c_int;
   4961         \\export threadlocal var g: c_int = 0;
   4962         \\
   4963         \\const struct_trailing_comma = struct { x: i32, y: i32, };
   4964         \\const struct_no_comma = struct { x: i32, y: i32 };
   4965         \\const struct_fn_no_comma = struct { fn m() void {} y: i32 };
   4966         \\
   4967         \\const enum_no_comma = enum { A, B };
   4968         \\
   4969         \\fn container_init() void {
   4970         \\    const S = struct { x: i32, y: i32 };
   4971         \\    _ = S { .x = 1, .y = 2 };
   4972         \\    _ = S { .x = 1, .y = 2, };
   4973         \\}
   4974         \\
   4975         \\fn type_expr_return1() if (true) A {}
   4976         \\fn type_expr_return2() for (true) |_| A {}
   4977         \\fn type_expr_return3() while (true) A {}
   4978         \\
   4979         \\fn switch_cases(x: i32) void {
   4980         \\    switch (x) {
   4981         \\        1,2,3 => {},
   4982         \\        4,5, => {},
   4983         \\        6...8, => {},
   4984         \\        else => {},
   4985         \\    }
   4986         \\}
   4987         \\
   4988         \\fn switch_prongs(x: i32) void {
   4989         \\    switch (x) {
   4990         \\        0 => {},
   4991         \\        else => {},
   4992         \\    }
   4993         \\    switch (x) {
   4994         \\        0 => {},
   4995         \\        else => {}
   4996         \\    }
   4997         \\}
   4998         \\
   4999         \\const fn_no_comma = fn(i32, i32)void;
   5000         \\const fn_trailing_comma = fn(i32, i32,)void;
   5001         \\
   5002         \\fn fn_calls() void {
   5003         \\    fn add(x: i32, y: i32,) i32 { x + y };
   5004         \\    _ = add(1, 2);
   5005         \\    _ = add(1, 2,);
   5006         \\}
   5007         \\
   5008         \\fn asm_lists() void {
   5009         \\    if (false) { // Build AST but don't analyze
   5010         \\        asm ("not real assembly"
   5011         \\            :[a] "x" (x),);
   5012         \\        asm ("not real assembly"
   5013         \\            :[a] "x" (->i32),:[a] "x" (1),);
   5014         \\        asm volatile ("still not real assembly"
   5015         \\            :::"a","b",);
   5016         \\    }
   5017         \\}
   5018     );
   5019 }
   5020 
   5021 test "zig fmt: while continue expr" {
   5022     try testCanonical(
   5023         \\test {
   5024         \\    while (i > 0)
   5025         \\        (i * 2);
   5026         \\}
   5027         \\
   5028     );
   5029     try testError(
   5030         \\test {
   5031         \\    while (i > 0) (i -= 1) {
   5032         \\        print("test123", .{});
   5033         \\    }
   5034         \\}
   5035     , &[_]Error{
   5036         .expected_continue_expr,
   5037     });
   5038 }
   5039 
   5040 test "zig fmt: error for invalid bit range" {
   5041     try testError(
   5042         \\var x: []align(0:0:0)u8 = bar;
   5043     , &[_]Error{
   5044         .invalid_bit_range,
   5045     });
   5046 }
   5047 
   5048 test "zig fmt: error for ptr mod on array child type" {
   5049     try testError(
   5050         \\var a: [10]align(10) u8 = e;
   5051         \\var b: [10]const u8 = f;
   5052         \\var c: [10]volatile u8 = g;
   5053         \\var d: [10]allowzero u8 = h;
   5054     , &[_]Error{
   5055         .ptr_mod_on_array_child_type,
   5056         .ptr_mod_on_array_child_type,
   5057         .ptr_mod_on_array_child_type,
   5058         .ptr_mod_on_array_child_type,
   5059     });
   5060 }
   5061 
   5062 test "recovery: top level" {
   5063     try testError(
   5064         \\test "" {inline}
   5065         \\test "" {inline}
   5066     , &[_]Error{
   5067         .expected_inlinable,
   5068         .expected_inlinable,
   5069     });
   5070 }
   5071 
   5072 test "recovery: block statements" {
   5073     try testError(
   5074         \\test "" {
   5075         \\    foo + +;
   5076         \\    inline;
   5077         \\}
   5078     , &[_]Error{
   5079         .expected_expr,
   5080         .expected_semi_after_stmt,
   5081         .expected_statement,
   5082         .expected_inlinable,
   5083     });
   5084 }
   5085 
   5086 test "recovery: missing comma" {
   5087     try testError(
   5088         \\test "" {
   5089         \\    switch (foo) {
   5090         \\        2 => {}
   5091         \\        3 => {}
   5092         \\        else => {
   5093         \\            foo && bar +;
   5094         \\        }
   5095         \\    }
   5096         \\}
   5097     , &[_]Error{
   5098         .expected_comma_after_switch_prong,
   5099         .expected_comma_after_switch_prong,
   5100         .expected_expr,
   5101     });
   5102 }
   5103 
   5104 test "recovery: non-associative operators" {
   5105     try testError(
   5106         \\const x = a == b == c;
   5107         \\const x = a == b != c;
   5108     , &[_]Error{
   5109         .chained_comparison_operators,
   5110         .chained_comparison_operators,
   5111     });
   5112 }
   5113 
   5114 test "recovery: extra qualifier" {
   5115     try testError(
   5116         \\const a: *const const u8;
   5117         \\test ""
   5118     , &[_]Error{
   5119         .extra_const_qualifier,
   5120         .expected_block,
   5121     });
   5122 }
   5123 
   5124 test "recovery: missing return type" {
   5125     try testError(
   5126         \\fn foo() {
   5127         \\    a && b;
   5128         \\}
   5129         \\test ""
   5130     , &[_]Error{
   5131         .expected_return_type,
   5132         .expected_block,
   5133     });
   5134 }
   5135 
   5136 test "recovery: continue after invalid decl" {
   5137     try testError(
   5138         \\fn foo {
   5139         \\    inline;
   5140         \\}
   5141         \\pub test "" {
   5142         \\    async a && b;
   5143         \\}
   5144     , &[_]Error{
   5145         .expected_token,
   5146         .expected_pub_item,
   5147         .expected_param_list,
   5148     });
   5149     try testError(
   5150         \\threadlocal test "" {
   5151         \\    @a && b;
   5152         \\}
   5153     , &[_]Error{
   5154         .expected_var_decl,
   5155         .expected_param_list,
   5156     });
   5157 }
   5158 
   5159 test "recovery: invalid extern/inline" {
   5160     try testError(
   5161         \\inline test "" { a && b; }
   5162     , &[_]Error{
   5163         .expected_fn,
   5164     });
   5165     try testError(
   5166         \\extern "" test "" { a && b; }
   5167     , &[_]Error{
   5168         .expected_var_decl_or_fn,
   5169     });
   5170 }
   5171 
   5172 test "recovery: missing semicolon" {
   5173     try testError(
   5174         \\test "" {
   5175         \\    comptime a && b
   5176         \\    c && d
   5177         \\    @foo
   5178         \\}
   5179     , &[_]Error{
   5180         .expected_semi_after_stmt,
   5181         .expected_semi_after_stmt,
   5182         .expected_param_list,
   5183         .expected_semi_after_stmt,
   5184     });
   5185 }
   5186 
   5187 test "recovery: invalid container members" {
   5188     try testError(
   5189         \\usingnamespace;
   5190         \\foo+
   5191         \\bar@,
   5192         \\while (a == 2) { test "" {}}
   5193         \\test "" {
   5194         \\    a && b
   5195         \\}
   5196     , &[_]Error{
   5197         .expected_expr,
   5198         .expected_comma_after_field,
   5199         .expected_container_members,
   5200         .expected_semi_after_stmt,
   5201     });
   5202 }
   5203 
   5204 // TODO after https://github.com/ziglang/zig/issues/35 is implemented,
   5205 // we should be able to recover from this *at any indentation level*,
   5206 // reporting a parse error and yet also parsing all the decls even
   5207 // inside structs.
   5208 test "recovery: extra '}' at top level" {
   5209     try testError(
   5210         \\}}}
   5211         \\test "" {
   5212         \\    a && b;
   5213         \\}
   5214     , &[_]Error{
   5215         .expected_token,
   5216     });
   5217 }
   5218 
   5219 test "recovery: mismatched bracket at top level" {
   5220     try testError(
   5221         \\const S = struct {
   5222         \\    arr: 128]?G
   5223         \\};
   5224     , &[_]Error{
   5225         .expected_comma_after_field,
   5226     });
   5227 }
   5228 
   5229 test "recovery: invalid global error set access" {
   5230     try testError(
   5231         \\test "" {
   5232         \\    error && foo;
   5233         \\}
   5234     , &[_]Error{
   5235         .expected_token,
   5236         .expected_token,
   5237     });
   5238 }
   5239 
   5240 test "recovery: invalid asterisk after pointer dereference" {
   5241     try testError(
   5242         \\test "" {
   5243         \\    var sequence = "repeat".*** 10;
   5244         \\}
   5245     , &[_]Error{
   5246         .asterisk_after_ptr_deref,
   5247     });
   5248     try testError(
   5249         \\test "" {
   5250         \\    var sequence = "repeat".** 10&&a;
   5251         \\}
   5252     , &[_]Error{
   5253         .asterisk_after_ptr_deref,
   5254     });
   5255 }
   5256 
   5257 test "recovery: missing semicolon after if, for, while stmt" {
   5258     try testError(
   5259         \\test "" {
   5260         \\    if (foo) bar
   5261         \\    for (foo) |a| bar
   5262         \\    while (foo) bar
   5263         \\    a && b;
   5264         \\}
   5265     , &[_]Error{
   5266         .expected_semi_or_else,
   5267         .expected_semi_or_else,
   5268         .expected_semi_or_else,
   5269     });
   5270 }
   5271 
   5272 test "recovery: invalid comptime" {
   5273     try testError(
   5274         \\comptime
   5275     , &[_]Error{
   5276         .expected_block_or_field,
   5277     });
   5278 }
   5279 
   5280 test "recovery: missing block after suspend" {
   5281     try testError(
   5282         \\fn foo() void {
   5283         \\    suspend;
   5284         \\    nosuspend;
   5285         \\}
   5286     , &[_]Error{
   5287         .expected_block_or_expr,
   5288         .expected_block_or_expr,
   5289     });
   5290 }
   5291 
   5292 test "recovery: missing block after for/while loops" {
   5293     try testError(
   5294         \\test "" { while (foo) }
   5295     , &[_]Error{
   5296         .expected_block_or_assignment,
   5297     });
   5298     try testError(
   5299         \\test "" { for (foo) |bar| }
   5300     , &[_]Error{
   5301         .expected_block_or_assignment,
   5302     });
   5303 }
   5304 
   5305 test "recovery: missing for payload" {
   5306     try testError(
   5307         \\comptime {
   5308         \\    const a = for(a) {};
   5309         \\    const a: for(a) blk: {};
   5310         \\    for(a) {}
   5311         \\}
   5312     , &[_]Error{
   5313         .expected_loop_payload,
   5314         .expected_loop_payload,
   5315         .expected_loop_payload,
   5316     });
   5317 }
   5318 
   5319 test "recovery: missing comma in params" {
   5320     try testError(
   5321         \\fn foo(comptime bool what what) void { }
   5322         \\fn bar(a: i32, b: i32 c) void { }
   5323         \\
   5324     , &[_]Error{
   5325         .expected_comma_after_param,
   5326         .expected_comma_after_param,
   5327         .expected_comma_after_param,
   5328     });
   5329 }
   5330 
   5331 test "recovery: missing while rbrace" {
   5332     try testError(
   5333         \\fn a() b {
   5334         \\    while (d) {
   5335         \\}
   5336     , &[_]Error{
   5337         .expected_statement,
   5338     });
   5339 }
   5340 
   5341 test "recovery: nonfinal varargs" {
   5342     try testError(
   5343         \\extern fn f(a: u32, ..., b: u32) void;
   5344         \\extern fn g(a: u32, ..., b: anytype) void;
   5345         \\extern fn h(a: u32, ..., ...) void;
   5346     , &[_]Error{
   5347         .varargs_nonfinal,
   5348         .varargs_nonfinal,
   5349         .varargs_nonfinal,
   5350     });
   5351 }
   5352 
   5353 test "recovery: eof in c pointer" {
   5354     try testError(
   5355         \\const Ptr = [*c
   5356     , &[_]Error{
   5357         .expected_token,
   5358     });
   5359 }
   5360 
   5361 const std = @import("std");
   5362 const mem = std.mem;
   5363 const print = std.debug.print;
   5364 const io = std.io;
   5365 const maxInt = std.math.maxInt;
   5366 
   5367 var fixed_buffer_mem: [100 * 1024]u8 = undefined;
   5368 
   5369 fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
   5370     const stderr = io.getStdErr().writer();
   5371 
   5372     var tree = try std.zig.parse(allocator, source);
   5373     defer tree.deinit(allocator);
   5374 
   5375     for (tree.errors) |parse_error| {
   5376         const loc = tree.tokenLocation(0, parse_error.token);
   5377         try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
   5378         try tree.renderError(parse_error, stderr);
   5379         try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
   5380         {
   5381             var i: usize = 0;
   5382             while (i < loc.column) : (i += 1) {
   5383                 try stderr.writeAll(" ");
   5384             }
   5385             try stderr.writeAll("^");
   5386         }
   5387         try stderr.writeAll("\n");
   5388     }
   5389     if (tree.errors.len != 0) {
   5390         return error.ParseError;
   5391     }
   5392 
   5393     const formatted = try tree.render(allocator);
   5394     anything_changed.* = !mem.eql(u8, formatted, source);
   5395     return formatted;
   5396 }
   5397 fn testTransform(source: [:0]const u8, expected_source: []const u8) !void {
   5398     const needed_alloc_count = x: {
   5399         // Try it once with unlimited memory, make sure it works
   5400         var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
   5401         var failing_allocator = std.testing.FailingAllocator.init(fixed_allocator.allocator(), maxInt(usize));
   5402         const allocator = failing_allocator.allocator();
   5403         var anything_changed: bool = undefined;
   5404         const result_source = try testParse(source, allocator, &anything_changed);
   5405         try std.testing.expectEqualStrings(expected_source, result_source);
   5406         const changes_expected = source.ptr != expected_source.ptr;
   5407         if (anything_changed != changes_expected) {
   5408             print("std.zig.render returned {} instead of {}\n", .{ anything_changed, changes_expected });
   5409             return error.TestFailed;
   5410         }
   5411         try std.testing.expect(anything_changed == changes_expected);
   5412         allocator.free(result_source);
   5413         break :x failing_allocator.index;
   5414     };
   5415 
   5416     var fail_index: usize = 0;
   5417     while (fail_index < needed_alloc_count) : (fail_index += 1) {
   5418         var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
   5419         var failing_allocator = std.testing.FailingAllocator.init(fixed_allocator.allocator(), fail_index);
   5420         var anything_changed: bool = undefined;
   5421         if (testParse(source, failing_allocator.allocator(), &anything_changed)) |_| {
   5422             return error.NondeterministicMemoryUsage;
   5423         } else |err| switch (err) {
   5424             error.OutOfMemory => {
   5425                 if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) {
   5426                     print(
   5427                         "\nfail_index: {d}/{d}\nallocated bytes: {d}\nfreed bytes: {d}\nallocations: {d}\ndeallocations: {d}\n",
   5428                         .{
   5429                             fail_index,
   5430                             needed_alloc_count,
   5431                             failing_allocator.allocated_bytes,
   5432                             failing_allocator.freed_bytes,
   5433                             failing_allocator.allocations,
   5434                             failing_allocator.deallocations,
   5435                         },
   5436                     );
   5437                     return error.MemoryLeakDetected;
   5438                 }
   5439             },
   5440             else => return err,
   5441         }
   5442     }
   5443 }
   5444 fn testCanonical(source: [:0]const u8) !void {
   5445     return testTransform(source, source);
   5446 }
   5447 
   5448 const Error = std.zig.Ast.Error.Tag;
   5449 
   5450 fn testError(source: [:0]const u8, expected_errors: []const Error) !void {
   5451     var tree = try std.zig.parse(std.testing.allocator, source);
   5452     defer tree.deinit(std.testing.allocator);
   5453 
   5454     try std.testing.expectEqual(expected_errors.len, tree.errors.len);
   5455     for (expected_errors) |expected, i| {
   5456         try std.testing.expectEqual(expected, tree.errors[i].tag);
   5457     }
   5458 }