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