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 }