authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-29 19:23:19-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-29 19:23:19-04:00
log3235eb03f979cbcc38cbe8b69d55761079e6d864
treeaa890cfcf494377b2e9830498a279445a00717c5
parent3fa0bed985b8de950859d4c482efe9cb30fdaf27

zig fmt: preserve same line comment after struct field


2 files changed, 1039 insertions(+), 1005 deletions(-)

std/zig/parser.zig+64-1005
......@@ -376,7 +376,7 @@ pub const Parser = struct {
376376 .body_node = &block.base,
377377 });
378378 try root_node.decls.append(&test_node.base);
379 stack.append(State { .Block = block }) catch unreachable;
379 try stack.append(State { .Block = block });
380380 try stack.append(State {
381381 .ExpectTokenSave = ExpectTokenSave {
382382 .id = Token.Id.LBrace,
......@@ -616,14 +616,18 @@ pub const Parser = struct {
616616 State.TopLevelExternOrField => |ctx| {
617617 if (self.eatToken(Token.Id.Identifier)) |identifier| {
618618 std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct);
619 const node = try self.createAttachNode(arena, &ctx.container_decl.fields_and_decls, ast.Node.StructField,
620 ast.Node.StructField {
621 .base = undefined,
622 .visib_token = ctx.visib_token,
623 .name_token = identifier,
624 .type_expr = undefined,
625 }
626 );
619 const node = try arena.construct(ast.Node.StructField {
620 .base = ast.Node {
621 .id = ast.Node.Id.StructField,
622 .before_comments = null,
623 .same_line_comment = null,
624 },
625 .visib_token = ctx.visib_token,
626 .name_token = identifier,
627 .type_expr = undefined,
628 });
629 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
630 *node_ptr = &node.base;
627631
628632 stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
629633 try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } });
......@@ -706,16 +710,20 @@ pub const Parser = struct {
706710 Token.Id.Identifier => {
707711 switch (container_decl.kind) {
708712 ast.Node.ContainerDecl.Kind.Struct => {
709 const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.Node.StructField,
710 ast.Node.StructField {
711 .base = undefined,
712 .visib_token = null,
713 .name_token = token,
714 .type_expr = undefined,
715 }
716 );
713 const node = try arena.construct(ast.Node.StructField {
714 .base = ast.Node {
715 .id = ast.Node.Id.StructField,
716 .before_comments = null,
717 .same_line_comment = null,
718 },
719 .visib_token = null,
720 .name_token = token,
721 .type_expr = undefined,
722 });
723 const node_ptr = try container_decl.fields_and_decls.addOne();
724 *node_ptr = &node.base;
717725
718 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
726 try stack.append(State { .FieldListCommaOrEnd = container_decl });
719727 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } });
720728 try stack.append(State { .ExpectToken = Token.Id.Colon });
721729 continue;
......@@ -1336,23 +1344,7 @@ pub const Parser = struct {
13361344 },
13371345
13381346 State.LookForSameLineComment => |node_ptr| {
1339 const node = *node_ptr;
1340 const node_last_token = node.lastToken();
1341
1342 const line_comment_token = self.getNextToken();
1343 if (line_comment_token.id != Token.Id.LineComment) {
1344 self.putBackToken(line_comment_token);
1345 continue;
1346 }
1347
1348 const offset_loc = self.tokenizer.getTokenLocation(node_last_token.end, line_comment_token);
1349 const different_line = offset_loc.line != 0;
1350 if (different_line) {
1351 self.putBackToken(line_comment_token);
1352 continue;
1353 }
1354
1355 node.same_line_comment = try arena.construct(line_comment_token);
1347 try self.lookForSameLineComment(arena, *node_ptr);
13561348 continue;
13571349 },
13581350
......@@ -1463,14 +1455,16 @@ pub const Parser = struct {
14631455 continue;
14641456 }
14651457
1466 const node = try self.createNode(arena, ast.Node.FieldInitializer,
1467 ast.Node.FieldInitializer {
1468 .base = undefined,
1469 .period_token = undefined,
1470 .name_token = undefined,
1471 .expr = undefined,
1472 }
1473 );
1458 const node = try arena.construct(ast.Node.FieldInitializer {
1459 .base = ast.Node {
1460 .id = ast.Node.Id.FieldInitializer,
1461 .before_comments = null,
1462 .same_line_comment = null,
1463 },
1464 .period_token = undefined,
1465 .name_token = undefined,
1466 .expr = undefined,
1467 });
14741468 try list_state.list.append(node);
14751469
14761470 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
......@@ -1504,7 +1498,8 @@ pub const Parser = struct {
15041498 container_decl.rbrace_token = end;
15051499 continue;
15061500 } else {
1507 stack.append(State { .ContainerDecl = container_decl }) catch unreachable;
1501 try self.lookForSameLineComment(arena, container_decl.fields_and_decls.toSlice()[container_decl.fields_and_decls.len - 1]);
1502 try stack.append(State { .ContainerDecl = container_decl });
15081503 continue;
15091504 }
15101505 },
......@@ -2908,6 +2903,25 @@ pub const Parser = struct {
29082903 }
29092904 }
29102905
2906 fn lookForSameLineComment(self: &Parser, arena: &mem.Allocator, node: &ast.Node) !void {
2907 const node_last_token = node.lastToken();
2908
2909 const line_comment_token = self.getNextToken();
2910 if (line_comment_token.id != Token.Id.LineComment) {
2911 self.putBackToken(line_comment_token);
2912 return;
2913 }
2914
2915 const offset_loc = self.tokenizer.getTokenLocation(node_last_token.end, line_comment_token);
2916 const different_line = offset_loc.line != 0;
2917 if (different_line) {
2918 self.putBackToken(line_comment_token);
2919 return;
2920 }
2921
2922 node.same_line_comment = try arena.construct(line_comment_token);
2923 }
2924
29112925 fn parseStringLiteral(self: &Parser, arena: &mem.Allocator, token: &const Token) !?&ast.Node {
29122926 switch (token.id) {
29132927 Token.Id.StringLiteral => {
......@@ -3341,6 +3355,7 @@ pub const Parser = struct {
33413355 while (stack.popOrNull()) |state| {
33423356 switch (state) {
33433357 RenderState.TopLevelDecl => |decl| {
3358 try stack.append(RenderState { .PrintSameLineComment = decl.same_line_comment } );
33443359 switch (decl.id) {
33453360 ast.Node.Id.FnProto => {
33463361 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
......@@ -3383,12 +3398,14 @@ pub const Parser = struct {
33833398 try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
33843399 }
33853400 try stream.print("{}: ", self.tokenizer.getTokenSlice(field.name_token));
3401 try stack.append(RenderState { .Text = "," });
33863402 try stack.append(RenderState { .Expression = field.type_expr});
33873403 },
33883404 ast.Node.Id.UnionTag => {
33893405 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
33903406 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
33913407
3408 try stack.append(RenderState { .Text = "," });
33923409 if (tag.type_expr) |type_expr| {
33933410 try stream.print(": ");
33943411 try stack.append(RenderState { .Expression = type_expr});
......@@ -3398,6 +3415,7 @@ pub const Parser = struct {
33983415 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
33993416 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
34003417
3418 try stack.append(RenderState { .Text = "," });
34013419 if (tag.value) |value| {
34023420 try stream.print(" = ");
34033421 try stack.append(RenderState { .Expression = value});
......@@ -3899,14 +3917,6 @@ pub const Parser = struct {
38993917 while (i != 0) {
39003918 i -= 1;
39013919 const node = fields_and_decls[i];
3902 switch (node.id) {
3903 ast.Node.Id.StructField,
3904 ast.Node.Id.UnionTag,
3905 ast.Node.Id.EnumTag => {
3906 try stack.append(RenderState { .Text = "," });
3907 },
3908 else => { }
3909 }
39103920 try stack.append(RenderState { .TopLevelDecl = node});
39113921 try stack.append(RenderState.PrintIndent);
39123922 try stack.append(RenderState {
......@@ -4466,957 +4476,6 @@ pub const Parser = struct {
44664476
44674477};
44684478
4469var fixed_buffer_mem: [100 * 1024]u8 = undefined;
4470
4471fn testParse(source: []const u8, allocator: &mem.Allocator) ![]u8 {
4472 var tokenizer = Tokenizer.init(source);
4473 var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");
4474 defer parser.deinit();
4475
4476 var tree = try parser.parse();
4477 defer tree.deinit();
4478
4479 var buffer = try std.Buffer.initSize(allocator, 0);
4480 errdefer buffer.deinit();
4481
4482 var buffer_out_stream = io.BufferOutStream.init(&buffer);
4483 try parser.renderSource(&buffer_out_stream.stream, tree.root_node);
4484 return buffer.toOwnedSlice();
4485}
4486
4487fn testCanonical(source: []const u8) !void {
4488 const needed_alloc_count = x: {
4489 // Try it once with unlimited memory, make sure it works
4490 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
4491 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
4492 const result_source = try testParse(source, &failing_allocator.allocator);
4493 if (!mem.eql(u8, result_source, source)) {
4494 warn("\n====== expected this output: =========\n");
4495 warn("{}", source);
4496 warn("\n======== instead found this: =========\n");
4497 warn("{}", result_source);
4498 warn("\n======================================\n");
4499 return error.TestFailed;
4500 }
4501 failing_allocator.allocator.free(result_source);
4502 break :x failing_allocator.index;
4503 };
4504
4505 var fail_index: usize = 0;
4506 while (fail_index < needed_alloc_count) : (fail_index += 1) {
4507 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
4508 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
4509 if (testParse(source, &failing_allocator.allocator)) |_| {
4510 return error.NondeterministicMemoryUsage;
4511 } else |err| switch (err) {
4512 error.OutOfMemory => {
4513 if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) {
4514 warn("\nfail_index: {}/{}\nallocated bytes: {}\nfreed bytes: {}\nallocations: {}\ndeallocations: {}\n",
4515 fail_index, needed_alloc_count,
4516 failing_allocator.allocated_bytes, failing_allocator.freed_bytes,
4517 failing_allocator.index, failing_allocator.deallocations);
4518 return error.MemoryLeakDetected;
4519 }
4520 },
4521 error.ParseError => @panic("test failed"),
4522 }
4523 }
4524}
4525
4526test "zig fmt: array literal with 1 item on 1 line" {
4527 try testCanonical(
4528 \\var s = []const u64 {0} ** 25;
4529 \\
4530 );
4531}
4532
4533test "zig fmt: preserve same-line comment after a statement" {
4534 try testCanonical(
4535 \\test "" {
4536 \\ a = b;
4537 \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
4538 \\ a = b;
4539 \\}
4540 \\
4541 );
4542}
4543
4544test "zig fmt: preserve comments before global variables" {
4545 try testCanonical(
4546 \\/// Foo copies keys and values before they go into the map, and
4547 \\/// frees them when they get removed.
4548 \\pub const Foo = struct {};
4549 \\
4550 );
4551}
4552
4553test "zig fmt: preserve comments before statements" {
4554 try testCanonical(
4555 \\test "std" {
4556 \\ // statement comment
4557 \\ _ = @import("foo/bar.zig");
4558 \\}
4559 \\
4560 );
4561}
4562
4563test "zig fmt: preserve top level comments" {
4564 try testCanonical(
4565 \\// top level comment
4566 \\test "hi" {}
4567 \\
4568 );
4569}
4570
4571test "zig fmt: get stdout or fail" {
4572 try testCanonical(
4573 \\const std = @import("std");
4574 \\
4575 \\pub fn main() !void {
4576 \\ // If this program is run without stdout attached, exit with an error.
4577 \\ // another comment
4578 \\ var stdout_file = try std.io.getStdOut;
4579 \\}
4580 \\
4581 );
4582}
4583
4584test "zig fmt: preserve spacing" {
4585 try testCanonical(
4586 \\const std = @import("std");
4587 \\
4588 \\pub fn main() !void {
4589 \\ var stdout_file = try std.io.getStdOut;
4590 \\ var stdout_file = try std.io.getStdOut;
4591 \\
4592 \\ var stdout_file = try std.io.getStdOut;
4593 \\ var stdout_file = try std.io.getStdOut;
4594 \\}
4595 \\
4596 );
4597}
4598
4599test "zig fmt: return types" {
4600 try testCanonical(
4601 \\pub fn main() !void {}
4602 \\pub fn main() var {}
4603 \\pub fn main() i32 {}
4604 \\
4605 );
4606}
4607
4608test "zig fmt: imports" {
4609 try testCanonical(
4610 \\const std = @import("std");
4611 \\const std = @import();
4612 \\
4613 );
4614}
4615
4616test "zig fmt: global declarations" {
4617 try testCanonical(
4618 \\const a = b;
4619 \\pub const a = b;
4620 \\var a = b;
4621 \\pub var a = b;
4622 \\const a: i32 = b;
4623 \\pub const a: i32 = b;
4624 \\var a: i32 = b;
4625 \\pub var a: i32 = b;
4626 \\extern const a: i32 = b;
4627 \\pub extern const a: i32 = b;
4628 \\extern var a: i32 = b;
4629 \\pub extern var a: i32 = b;
4630 \\extern "a" const a: i32 = b;
4631 \\pub extern "a" const a: i32 = b;
4632 \\extern "a" var a: i32 = b;
4633 \\pub extern "a" var a: i32 = b;
4634 \\
4635 );
4636}
4637
4638test "zig fmt: extern declaration" {
4639 try testCanonical(
4640 \\extern var foo: c_int;
4641 \\
4642 );
4643}
4644
4645test "zig fmt: alignment" {
4646 try testCanonical(
4647 \\var foo: c_int align(1);
4648 \\
4649 );
4650}
4651
4652test "zig fmt: C main" {
4653 try testCanonical(
4654 \\fn main(argc: c_int, argv: &&u8) c_int {
4655 \\ const a = b;
4656 \\}
4657 \\
4658 );
4659}
4660
4661test "zig fmt: return" {
4662 try testCanonical(
4663 \\fn foo(argc: c_int, argv: &&u8) c_int {
4664 \\ return 0;
4665 \\}
4666 \\
4667 \\fn bar() void {
4668 \\ return;
4669 \\}
4670 \\
4671 );
4672}
4673
4674test "zig fmt: pointer attributes" {
4675 try testCanonical(
4676 \\extern fn f1(s: &align(&u8) u8) c_int;
4677 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
4678 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
4679 \\extern fn f4(s: &align(1) const volatile u8) c_int;
4680 \\
4681 );
4682}
4683
4684test "zig fmt: slice attributes" {
4685 try testCanonical(
4686 \\extern fn f1(s: &align(&u8) u8) c_int;
4687 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
4688 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
4689 \\extern fn f4(s: &align(1) const volatile u8) c_int;
4690 \\
4691 );
4692}
4693
4694test "zig fmt: test declaration" {
4695 try testCanonical(
4696 \\test "test name" {
4697 \\ const a = 1;
4698 \\ var b = 1;
4699 \\}
4700 \\
4701 );
4702}
4703
4704test "zig fmt: infix operators" {
4705 try testCanonical(
4706 \\test "infix operators" {
4707 \\ var i = undefined;
4708 \\ i = 2;
4709 \\ i *= 2;
4710 \\ i |= 2;
4711 \\ i ^= 2;
4712 \\ i <<= 2;
4713 \\ i >>= 2;
4714 \\ i &= 2;
4715 \\ i *= 2;
4716 \\ i *%= 2;
4717 \\ i -= 2;
4718 \\ i -%= 2;
4719 \\ i += 2;
4720 \\ i +%= 2;
4721 \\ i /= 2;
4722 \\ i %= 2;
4723 \\ _ = i == i;
4724 \\ _ = i != i;
4725 \\ _ = i != i;
4726 \\ _ = i.i;
4727 \\ _ = i || i;
4728 \\ _ = i!i;
4729 \\ _ = i ** i;
4730 \\ _ = i ++ i;
4731 \\ _ = i ?? i;
4732 \\ _ = i % i;
4733 \\ _ = i / i;
4734 \\ _ = i *% i;
4735 \\ _ = i * i;
4736 \\ _ = i -% i;
4737 \\ _ = i - i;
4738 \\ _ = i +% i;
4739 \\ _ = i + i;
4740 \\ _ = i << i;
4741 \\ _ = i >> i;
4742 \\ _ = i & i;
4743 \\ _ = i ^ i;
4744 \\ _ = i | i;
4745 \\ _ = i >= i;
4746 \\ _ = i <= i;
4747 \\ _ = i > i;
4748 \\ _ = i < i;
4749 \\ _ = i and i;
4750 \\ _ = i or i;
4751 \\}
4752 \\
4753 );
4754}
4755
4756test "zig fmt: precedence" {
4757 try testCanonical(
4758 \\test "precedence" {
4759 \\ a!b();
4760 \\ (a!b)();
4761 \\ !a!b;
4762 \\ !(a!b);
4763 \\ !a{};
4764 \\ !(a{});
4765 \\ a + b{};
4766 \\ (a + b){};
4767 \\ a << b + c;
4768 \\ (a << b) + c;
4769 \\ a & b << c;
4770 \\ (a & b) << c;
4771 \\ a ^ b & c;
4772 \\ (a ^ b) & c;
4773 \\ a | b ^ c;
4774 \\ (a | b) ^ c;
4775 \\ a == b | c;
4776 \\ (a == b) | c;
4777 \\ a and b == c;
4778 \\ (a and b) == c;
4779 \\ a or b and c;
4780 \\ (a or b) and c;
4781 \\ (a or b) and c;
4782 \\}
4783 \\
4784 );
4785}
4786
4787test "zig fmt: prefix operators" {
4788 try testCanonical(
4789 \\test "prefix operators" {
4790 \\ try return --%~??!*&0;
4791 \\}
4792 \\
4793 );
4794}
4795
4796test "zig fmt: call expression" {
4797 try testCanonical(
4798 \\test "test calls" {
4799 \\ a();
4800 \\ a(1);
4801 \\ a(1, 2);
4802 \\ a(1, 2) + a(1, 2);
4803 \\}
4804 \\
4805 );
4806}
4807
4808test "zig fmt: var args" {
4809 try testCanonical(
4810 \\fn print(args: ...) void {}
4811 \\
4812 );
4813}
4814
4815test "zig fmt: var type" {
4816 try testCanonical(
4817 \\fn print(args: var) var {}
4818 \\const Var = var;
4819 \\const i: var = 0;
4820 \\
4821 );
4822}
4823
4824test "zig fmt: functions" {
4825 try testCanonical(
4826 \\extern fn puts(s: &const u8) c_int;
4827 \\extern "c" fn puts(s: &const u8) c_int;
4828 \\export fn puts(s: &const u8) c_int;
4829 \\inline fn puts(s: &const u8) c_int;
4830 \\pub extern fn puts(s: &const u8) c_int;
4831 \\pub extern "c" fn puts(s: &const u8) c_int;
4832 \\pub export fn puts(s: &const u8) c_int;
4833 \\pub inline fn puts(s: &const u8) c_int;
4834 \\pub extern fn puts(s: &const u8) align(2 + 2) c_int;
4835 \\pub extern "c" fn puts(s: &const u8) align(2 + 2) c_int;
4836 \\pub export fn puts(s: &const u8) align(2 + 2) c_int;
4837 \\pub inline fn puts(s: &const u8) align(2 + 2) c_int;
4838 \\
4839 );
4840}
4841
4842test "zig fmt: multiline string" {
4843 try testCanonical(
4844 \\const s =
4845 \\ \\ something
4846 \\ \\ something else
4847 \\ ;
4848 \\
4849 );
4850}
4851
4852test "zig fmt: values" {
4853 try testCanonical(
4854 \\test "values" {
4855 \\ 1;
4856 \\ 1.0;
4857 \\ "string";
4858 \\ c"cstring";
4859 \\ 'c';
4860 \\ true;
4861 \\ false;
4862 \\ null;
4863 \\ undefined;
4864 \\ error;
4865 \\ this;
4866 \\ unreachable;
4867 \\}
4868 \\
4869 );
4870}
4871
4872test "zig fmt: indexing" {
4873 try testCanonical(
4874 \\test "test index" {
4875 \\ a[0];
4876 \\ a[0 + 5];
4877 \\ a[0..];
4878 \\ a[0..5];
4879 \\ a[a[0]];
4880 \\ a[a[0..]];
4881 \\ a[a[0..5]];
4882 \\ a[a[0]..];
4883 \\ a[a[0..5]..];
4884 \\ a[a[0]..a[0]];
4885 \\ a[a[0..5]..a[0]];
4886 \\ a[a[0..5]..a[0..5]];
4887 \\}
4888 \\
4889 );
4890}
4891
4892test "zig fmt: struct declaration" {
4893 try testCanonical(
4894 \\const S = struct {
4895 \\ const Self = this;
4896 \\ f1: u8,
4897 \\ pub f3: u8,
4898 \\
4899 \\ fn method(self: &Self) Self {
4900 \\ return *self;
4901 \\ }
4902 \\
4903 \\ f2: u8,
4904 \\};
4905 \\
4906 \\const Ps = packed struct {
4907 \\ a: u8,
4908 \\ pub b: u8,
4909 \\
4910 \\ c: u8,
4911 \\};
4912 \\
4913 \\const Es = extern struct {
4914 \\ a: u8,
4915 \\ pub b: u8,
4916 \\
4917 \\ c: u8,
4918 \\};
4919 \\
4920 );
4921}
4922
4923test "zig fmt: enum declaration" {
4924 try testCanonical(
4925 \\const E = enum {
4926 \\ Ok,
4927 \\ SomethingElse = 0,
4928 \\};
4929 \\
4930 \\const E2 = enum(u8) {
4931 \\ Ok,
4932 \\ SomethingElse = 255,
4933 \\ SomethingThird,
4934 \\};
4935 \\
4936 \\const Ee = extern enum {
4937 \\ Ok,
4938 \\ SomethingElse,
4939 \\ SomethingThird,
4940 \\};
4941 \\
4942 \\const Ep = packed enum {
4943 \\ Ok,
4944 \\ SomethingElse,
4945 \\ SomethingThird,
4946 \\};
4947 \\
4948 );
4949}
4950
4951test "zig fmt: union declaration" {
4952 try testCanonical(
4953 \\const U = union {
4954 \\ Int: u8,
4955 \\ Float: f32,
4956 \\ None,
4957 \\ Bool: bool,
4958 \\};
4959 \\
4960 \\const Ue = union(enum) {
4961 \\ Int: u8,
4962 \\ Float: f32,
4963 \\ None,
4964 \\ Bool: bool,
4965 \\};
4966 \\
4967 \\const E = enum {
4968 \\ Int,
4969 \\ Float,
4970 \\ None,
4971 \\ Bool,
4972 \\};
4973 \\
4974 \\const Ue2 = union(E) {
4975 \\ Int: u8,
4976 \\ Float: f32,
4977 \\ None,
4978 \\ Bool: bool,
4979 \\};
4980 \\
4981 \\const Eu = extern union {
4982 \\ Int: u8,
4983 \\ Float: f32,
4984 \\ None,
4985 \\ Bool: bool,
4986 \\};
4987 \\
4988 );
4989}
4990
4991test "zig fmt: error set declaration" {
4992 try testCanonical(
4993 \\const E = error {
4994 \\ A,
4995 \\ B,
4996 \\
4997 \\ C,
4998 \\};
4999 \\
5000 );
5001}
5002
5003test "zig fmt: arrays" {
5004 try testCanonical(
5005 \\test "test array" {
5006 \\ const a: [2]u8 = [2]u8 {
5007 \\ 1,
5008 \\ 2,
5009 \\ };
5010 \\ const a: [2]u8 = []u8 {
5011 \\ 1,
5012 \\ 2,
5013 \\ };
5014 \\ const a: [0]u8 = []u8{};
5015 \\}
5016 \\
5017 );
5018}
5019
5020test "zig fmt: container initializers" {
5021 try testCanonical(
5022 \\const a1 = []u8{};
5023 \\const a2 = []u8 {
5024 \\ 1,
5025 \\ 2,
5026 \\ 3,
5027 \\ 4,
5028 \\};
5029 \\const s1 = S{};
5030 \\const s2 = S {
5031 \\ .a = 1,
5032 \\ .b = 2,
5033 \\};
5034 \\
5035 );
5036}
5037
5038test "zig fmt: catch" {
5039 try testCanonical(
5040 \\test "catch" {
5041 \\ const a: error!u8 = 0;
5042 \\ _ = a catch return;
5043 \\ _ = a catch |err| return;
5044 \\}
5045 \\
5046 );
5047}
5048
5049test "zig fmt: blocks" {
5050 try testCanonical(
5051 \\test "blocks" {
5052 \\ {
5053 \\ const a = 0;
5054 \\ const b = 0;
5055 \\ }
5056 \\
5057 \\ blk: {
5058 \\ const a = 0;
5059 \\ const b = 0;
5060 \\ }
5061 \\
5062 \\ const r = blk: {
5063 \\ const a = 0;
5064 \\ const b = 0;
5065 \\ };
5066 \\}
5067 \\
5068 );
5069}
5070
5071test "zig fmt: switch" {
5072 try testCanonical(
5073 \\test "switch" {
5074 \\ switch (0) {
5075 \\ 0 => {},
5076 \\ 1 => unreachable,
5077 \\ 2,
5078 \\ 3 => {},
5079 \\ 4 ... 7 => {},
5080 \\ 1 + 4 * 3 + 22 => {},
5081 \\ else => {
5082 \\ const a = 1;
5083 \\ const b = a;
5084 \\ },
5085 \\ }
5086 \\
5087 \\ const res = switch (0) {
5088 \\ 0 => 0,
5089 \\ 1 => 2,
5090 \\ 1 => a = 4,
5091 \\ else => 4,
5092 \\ };
5093 \\
5094 \\ const Union = union(enum) {
5095 \\ Int: i64,
5096 \\ Float: f64,
5097 \\ };
5098 \\
5099 \\ const u = Union {
5100 \\ .Int = 0,
5101 \\ };
5102 \\ switch (u) {
5103 \\ Union.Int => |int| {},
5104 \\ Union.Float => |*float| unreachable,
5105 \\ }
5106 \\}
5107 \\
5108 );
5109}
5110
5111test "zig fmt: while" {
5112 try testCanonical(
5113 \\test "while" {
5114 \\ while (10 < 1) {
5115 \\ unreachable;
5116 \\ }
5117 \\
5118 \\ while (10 < 1)
5119 \\ unreachable;
5120 \\
5121 \\ var i: usize = 0;
5122 \\ while (i < 10) : (i += 1) {
5123 \\ continue;
5124 \\ }
5125 \\
5126 \\ i = 0;
5127 \\ while (i < 10) : (i += 1)
5128 \\ continue;
5129 \\
5130 \\ i = 0;
5131 \\ var j: usize = 0;
5132 \\ while (i < 10) : ({
5133 \\ i += 1;
5134 \\ j += 1;
5135 \\ }) {
5136 \\ continue;
5137 \\ }
5138 \\
5139 \\ var a: ?u8 = 2;
5140 \\ while (a) |v| : (a = null) {
5141 \\ continue;
5142 \\ }
5143 \\
5144 \\ while (a) |v| : (a = null)
5145 \\ unreachable;
5146 \\
5147 \\ label: while (10 < 0) {
5148 \\ unreachable;
5149 \\ }
5150 \\
5151 \\ const res = while (0 < 10) {
5152 \\ break 7;
5153 \\ } else {
5154 \\ unreachable;
5155 \\ };
5156 \\
5157 \\ const res = while (0 < 10)
5158 \\ break 7
5159 \\ else
5160 \\ unreachable;
5161 \\
5162 \\ var a: error!u8 = 0;
5163 \\ while (a) |v| {
5164 \\ a = error.Err;
5165 \\ } else |err| {
5166 \\ i = 1;
5167 \\ }
5168 \\
5169 \\ comptime var k: usize = 0;
5170 \\ inline while (i < 10) : (i += 1)
5171 \\ j += 2;
5172 \\}
5173 \\
5174 );
5175}
5176
5177test "zig fmt: for" {
5178 try testCanonical(
5179 \\test "for" {
5180 \\ const a = []u8 {
5181 \\ 1,
5182 \\ 2,
5183 \\ 3,
5184 \\ };
5185 \\ for (a) |v| {
5186 \\ continue;
5187 \\ }
5188 \\
5189 \\ for (a) |v|
5190 \\ continue;
5191 \\
5192 \\ for (a) |*v|
5193 \\ continue;
5194 \\
5195 \\ for (a) |v, i| {
5196 \\ continue;
5197 \\ }
5198 \\
5199 \\ for (a) |v, i|
5200 \\ continue;
5201 \\
5202 \\ const res = for (a) |v, i| {
5203 \\ break v;
5204 \\ } else {
5205 \\ unreachable;
5206 \\ };
5207 \\
5208 \\ var num: usize = 0;
5209 \\ inline for (a) |v, i| {
5210 \\ num += v;
5211 \\ num += i;
5212 \\ }
5213 \\}
5214 \\
5215 );
5216}
5217
5218test "zig fmt: if" {
5219 try testCanonical(
5220 \\test "if" {
5221 \\ if (10 < 0) {
5222 \\ unreachable;
5223 \\ }
5224 \\
5225 \\ if (10 < 0) unreachable;
5226 \\
5227 \\ if (10 < 0) {
5228 \\ unreachable;
5229 \\ } else {
5230 \\ const a = 20;
5231 \\ }
5232 \\
5233 \\ if (10 < 0) {
5234 \\ unreachable;
5235 \\ } else if (5 < 0) {
5236 \\ unreachable;
5237 \\ } else {
5238 \\ const a = 20;
5239 \\ }
5240 \\
5241 \\ const is_world_broken = if (10 < 0) true else false;
5242 \\ const some_number = 1 + if (10 < 0) 2 else 3;
5243 \\
5244 \\ const a: ?u8 = 10;
5245 \\ const b: ?u8 = null;
5246 \\ if (a) |v| {
5247 \\ const some = v;
5248 \\ } else if (b) |*v| {
5249 \\ unreachable;
5250 \\ } else {
5251 \\ const some = 10;
5252 \\ }
5253 \\
5254 \\ const non_null_a = if (a) |v| v else 0;
5255 \\
5256 \\ const a_err: error!u8 = 0;
5257 \\ if (a_err) |v| {
5258 \\ const p = v;
5259 \\ } else |err| {
5260 \\ unreachable;
5261 \\ }
5262 \\}
5263 \\
5264 );
5265}
5266
5267test "zig fmt: defer" {
5268 try testCanonical(
5269 \\test "defer" {
5270 \\ var i: usize = 0;
5271 \\ defer i = 1;
5272 \\ defer {
5273 \\ i += 2;
5274 \\ i *= i;
5275 \\ }
5276 \\
5277 \\ errdefer i += 3;
5278 \\ errdefer {
5279 \\ i += 2;
5280 \\ i /= i;
5281 \\ }
5282 \\}
5283 \\
5284 );
5285}
5286
5287test "zig fmt: comptime" {
5288 try testCanonical(
5289 \\fn a() u8 {
5290 \\ return 5;
5291 \\}
5292 \\
5293 \\fn b(comptime i: u8) u8 {
5294 \\ return i;
5295 \\}
5296 \\
5297 \\const av = comptime a();
5298 \\const av2 = comptime blk: {
5299 \\ var res = a();
5300 \\ res *= b(2);
5301 \\ break :blk res;
5302 \\};
5303 \\
5304 \\comptime {
5305 \\ _ = a();
5306 \\}
5307 \\
5308 \\test "comptime" {
5309 \\ const av3 = comptime a();
5310 \\ const av4 = comptime blk: {
5311 \\ var res = a();
5312 \\ res *= a();
5313 \\ break :blk res;
5314 \\ };
5315 \\
5316 \\ comptime var i = 0;
5317 \\ comptime {
5318 \\ i = a();
5319 \\ i += b(i);
5320 \\ }
5321 \\}
5322 \\
5323 );
5324}
5325
5326test "zig fmt: fn type" {
5327 try testCanonical(
5328 \\fn a(i: u8) u8 {
5329 \\ return i + 1;
5330 \\}
5331 \\
5332 \\const a: fn(u8) u8 = undefined;
5333 \\const b: extern fn(u8) u8 = undefined;
5334 \\const c: nakedcc fn(u8) u8 = undefined;
5335 \\const ap: fn(u8) u8 = a;
5336 \\
5337 );
5338}
5339
5340test "zig fmt: inline asm" {
5341 try testCanonical(
5342 \\pub fn syscall1(number: usize, arg1: usize) usize {
5343 \\ return asm volatile ("syscall"
5344 \\ : [ret] "={rax}" (-> usize)
5345 \\ : [number] "{rax}" (number),
5346 \\ [arg1] "{rdi}" (arg1)
5347 \\ : "rcx", "r11");
5348 \\}
5349 \\
5350 );
5351}
5352
5353test "zig fmt: coroutines" {
5354 try testCanonical(
5355 \\async fn simpleAsyncFn() void {
5356 \\ const a = async a.b();
5357 \\ x += 1;
5358 \\ suspend;
5359 \\ x += 1;
5360 \\ suspend |p| {}
5361 \\ const p = async simpleAsyncFn() catch unreachable;
5362 \\ await p;
5363 \\}
5364 \\
5365 \\test "coroutine suspend, resume, cancel" {
5366 \\ const p = try async<std.debug.global_allocator> testAsyncSeq();
5367 \\ resume p;
5368 \\ cancel p;
5369 \\}
5370 \\
5371 );
5372}
5373
5374test "zig fmt: Block after if" {
5375 try testCanonical(
5376 \\test "Block after if" {
5377 \\ if (true) {
5378 \\ const a = 0;
5379 \\ }
5380 \\
5381 \\ {
5382 \\ const a = 0;
5383 \\ }
5384 \\}
5385 \\
5386 );
5387}
5388
5389test "zig fmt: use" {
5390 try testCanonical(
5391 \\use @import("std");
5392 \\pub use @import("std");
5393 \\
5394 );
5395}
5396
5397test "zig fmt: string identifier" {
5398 try testCanonical(
5399 \\const @"a b" = @"c d".@"e f";
5400 \\fn @"g h"() void {}
5401 \\
5402 );
5403}
5404
5405test "zig fmt: error return" {
5406 try testCanonical(
5407 \\fn err() error {
5408 \\ call();
5409 \\ return error.InvalidArgs;
5410 \\}
5411 \\
5412 );
5413}
5414
5415test "zig fmt: struct literals with fields on each line" {
5416 try testCanonical(
5417 \\var self = BufSet {
5418 \\ .hash_map = BufSetHashMap.init(a),
5419 \\};
5420 \\
5421 );
4479test "std.zig.parser" {
4480 _ = @import("parser_test.zig");
54224481}
std/zig/parser_test.zig created+975
......@@ -0,0 +1,975 @@
1test "zig fmt: line comment after field decl" {
2 try testCanonical(
3 \\pub const dirent = extern struct {
4 \\ d_name: u8,
5 \\ d_name: u8, // comment 1
6 \\ d_name: u8,
7 \\ d_name: u8, // comment 2
8 \\ d_name: u8,
9 \\};
10 \\
11 );
12}
13
14test "zig fmt: array literal with 1 item on 1 line" {
15 try testCanonical(
16 \\var s = []const u64 {0} ** 25;
17 \\
18 );
19}
20
21test "zig fmt: preserve same-line comment after a statement" {
22 try testCanonical(
23 \\test "" {
24 \\ a = b;
25 \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption
26 \\ a = b;
27 \\}
28 \\
29 );
30}
31
32test "zig fmt: preserve comments before global variables" {
33 try testCanonical(
34 \\/// Foo copies keys and values before they go into the map, and
35 \\/// frees them when they get removed.
36 \\pub const Foo = struct {};
37 \\
38 );
39}
40
41test "zig fmt: preserve comments before statements" {
42 try testCanonical(
43 \\test "std" {
44 \\ // statement comment
45 \\ _ = @import("foo/bar.zig");
46 \\}
47 \\
48 );
49}
50
51test "zig fmt: preserve top level comments" {
52 try testCanonical(
53 \\// top level comment
54 \\test "hi" {}
55 \\
56 );
57}
58
59test "zig fmt: get stdout or fail" {
60 try testCanonical(
61 \\const std = @import("std");
62 \\
63 \\pub fn main() !void {
64 \\ // If this program is run without stdout attached, exit with an error.
65 \\ // another comment
66 \\ var stdout_file = try std.io.getStdOut;
67 \\}
68 \\
69 );
70}
71
72test "zig fmt: preserve spacing" {
73 try testCanonical(
74 \\const std = @import("std");
75 \\
76 \\pub fn main() !void {
77 \\ var stdout_file = try std.io.getStdOut;
78 \\ var stdout_file = try std.io.getStdOut;
79 \\
80 \\ var stdout_file = try std.io.getStdOut;
81 \\ var stdout_file = try std.io.getStdOut;
82 \\}
83 \\
84 );
85}
86
87test "zig fmt: return types" {
88 try testCanonical(
89 \\pub fn main() !void {}
90 \\pub fn main() var {}
91 \\pub fn main() i32 {}
92 \\
93 );
94}
95
96test "zig fmt: imports" {
97 try testCanonical(
98 \\const std = @import("std");
99 \\const std = @import();
100 \\
101 );
102}
103
104test "zig fmt: global declarations" {
105 try testCanonical(
106 \\const a = b;
107 \\pub const a = b;
108 \\var a = b;
109 \\pub var a = b;
110 \\const a: i32 = b;
111 \\pub const a: i32 = b;
112 \\var a: i32 = b;
113 \\pub var a: i32 = b;
114 \\extern const a: i32 = b;
115 \\pub extern const a: i32 = b;
116 \\extern var a: i32 = b;
117 \\pub extern var a: i32 = b;
118 \\extern "a" const a: i32 = b;
119 \\pub extern "a" const a: i32 = b;
120 \\extern "a" var a: i32 = b;
121 \\pub extern "a" var a: i32 = b;
122 \\
123 );
124}
125
126test "zig fmt: extern declaration" {
127 try testCanonical(
128 \\extern var foo: c_int;
129 \\
130 );
131}
132
133test "zig fmt: alignment" {
134 try testCanonical(
135 \\var foo: c_int align(1);
136 \\
137 );
138}
139
140test "zig fmt: C main" {
141 try testCanonical(
142 \\fn main(argc: c_int, argv: &&u8) c_int {
143 \\ const a = b;
144 \\}
145 \\
146 );
147}
148
149test "zig fmt: return" {
150 try testCanonical(
151 \\fn foo(argc: c_int, argv: &&u8) c_int {
152 \\ return 0;
153 \\}
154 \\
155 \\fn bar() void {
156 \\ return;
157 \\}
158 \\
159 );
160}
161
162test "zig fmt: pointer attributes" {
163 try testCanonical(
164 \\extern fn f1(s: &align(&u8) u8) c_int;
165 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
166 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
167 \\extern fn f4(s: &align(1) const volatile u8) c_int;
168 \\
169 );
170}
171
172test "zig fmt: slice attributes" {
173 try testCanonical(
174 \\extern fn f1(s: &align(&u8) u8) c_int;
175 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
176 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
177 \\extern fn f4(s: &align(1) const volatile u8) c_int;
178 \\
179 );
180}
181
182test "zig fmt: test declaration" {
183 try testCanonical(
184 \\test "test name" {
185 \\ const a = 1;
186 \\ var b = 1;
187 \\}
188 \\
189 );
190}
191
192test "zig fmt: infix operators" {
193 try testCanonical(
194 \\test "infix operators" {
195 \\ var i = undefined;
196 \\ i = 2;
197 \\ i *= 2;
198 \\ i |= 2;
199 \\ i ^= 2;
200 \\ i <<= 2;
201 \\ i >>= 2;
202 \\ i &= 2;
203 \\ i *= 2;
204 \\ i *%= 2;
205 \\ i -= 2;
206 \\ i -%= 2;
207 \\ i += 2;
208 \\ i +%= 2;
209 \\ i /= 2;
210 \\ i %= 2;
211 \\ _ = i == i;
212 \\ _ = i != i;
213 \\ _ = i != i;
214 \\ _ = i.i;
215 \\ _ = i || i;
216 \\ _ = i!i;
217 \\ _ = i ** i;
218 \\ _ = i ++ i;
219 \\ _ = i ?? i;
220 \\ _ = i % i;
221 \\ _ = i / i;
222 \\ _ = i *% i;
223 \\ _ = i * i;
224 \\ _ = i -% i;
225 \\ _ = i - i;
226 \\ _ = i +% i;
227 \\ _ = i + i;
228 \\ _ = i << i;
229 \\ _ = i >> i;
230 \\ _ = i & i;
231 \\ _ = i ^ i;
232 \\ _ = i | i;
233 \\ _ = i >= i;
234 \\ _ = i <= i;
235 \\ _ = i > i;
236 \\ _ = i < i;
237 \\ _ = i and i;
238 \\ _ = i or i;
239 \\}
240 \\
241 );
242}
243
244test "zig fmt: precedence" {
245 try testCanonical(
246 \\test "precedence" {
247 \\ a!b();
248 \\ (a!b)();
249 \\ !a!b;
250 \\ !(a!b);
251 \\ !a{};
252 \\ !(a{});
253 \\ a + b{};
254 \\ (a + b){};
255 \\ a << b + c;
256 \\ (a << b) + c;
257 \\ a & b << c;
258 \\ (a & b) << c;
259 \\ a ^ b & c;
260 \\ (a ^ b) & c;
261 \\ a | b ^ c;
262 \\ (a | b) ^ c;
263 \\ a == b | c;
264 \\ (a == b) | c;
265 \\ a and b == c;
266 \\ (a and b) == c;
267 \\ a or b and c;
268 \\ (a or b) and c;
269 \\ (a or b) and c;
270 \\}
271 \\
272 );
273}
274
275test "zig fmt: prefix operators" {
276 try testCanonical(
277 \\test "prefix operators" {
278 \\ try return --%~??!*&0;
279 \\}
280 \\
281 );
282}
283
284test "zig fmt: call expression" {
285 try testCanonical(
286 \\test "test calls" {
287 \\ a();
288 \\ a(1);
289 \\ a(1, 2);
290 \\ a(1, 2) + a(1, 2);
291 \\}
292 \\
293 );
294}
295
296test "zig fmt: var args" {
297 try testCanonical(
298 \\fn print(args: ...) void {}
299 \\
300 );
301}
302
303test "zig fmt: var type" {
304 try testCanonical(
305 \\fn print(args: var) var {}
306 \\const Var = var;
307 \\const i: var = 0;
308 \\
309 );
310}
311
312test "zig fmt: functions" {
313 try testCanonical(
314 \\extern fn puts(s: &const u8) c_int;
315 \\extern "c" fn puts(s: &const u8) c_int;
316 \\export fn puts(s: &const u8) c_int;
317 \\inline fn puts(s: &const u8) c_int;
318 \\pub extern fn puts(s: &const u8) c_int;
319 \\pub extern "c" fn puts(s: &const u8) c_int;
320 \\pub export fn puts(s: &const u8) c_int;
321 \\pub inline fn puts(s: &const u8) c_int;
322 \\pub extern fn puts(s: &const u8) align(2 + 2) c_int;
323 \\pub extern "c" fn puts(s: &const u8) align(2 + 2) c_int;
324 \\pub export fn puts(s: &const u8) align(2 + 2) c_int;
325 \\pub inline fn puts(s: &const u8) align(2 + 2) c_int;
326 \\
327 );
328}
329
330test "zig fmt: multiline string" {
331 try testCanonical(
332 \\const s =
333 \\ \\ something
334 \\ \\ something else
335 \\ ;
336 \\
337 );
338}
339
340test "zig fmt: values" {
341 try testCanonical(
342 \\test "values" {
343 \\ 1;
344 \\ 1.0;
345 \\ "string";
346 \\ c"cstring";
347 \\ 'c';
348 \\ true;
349 \\ false;
350 \\ null;
351 \\ undefined;
352 \\ error;
353 \\ this;
354 \\ unreachable;
355 \\}
356 \\
357 );
358}
359
360test "zig fmt: indexing" {
361 try testCanonical(
362 \\test "test index" {
363 \\ a[0];
364 \\ a[0 + 5];
365 \\ a[0..];
366 \\ a[0..5];
367 \\ a[a[0]];
368 \\ a[a[0..]];
369 \\ a[a[0..5]];
370 \\ a[a[0]..];
371 \\ a[a[0..5]..];
372 \\ a[a[0]..a[0]];
373 \\ a[a[0..5]..a[0]];
374 \\ a[a[0..5]..a[0..5]];
375 \\}
376 \\
377 );
378}
379
380test "zig fmt: struct declaration" {
381 try testCanonical(
382 \\const S = struct {
383 \\ const Self = this;
384 \\ f1: u8,
385 \\ pub f3: u8,
386 \\
387 \\ fn method(self: &Self) Self {
388 \\ return *self;
389 \\ }
390 \\
391 \\ f2: u8,
392 \\};
393 \\
394 \\const Ps = packed struct {
395 \\ a: u8,
396 \\ pub b: u8,
397 \\
398 \\ c: u8,
399 \\};
400 \\
401 \\const Es = extern struct {
402 \\ a: u8,
403 \\ pub b: u8,
404 \\
405 \\ c: u8,
406 \\};
407 \\
408 );
409}
410
411test "zig fmt: enum declaration" {
412 try testCanonical(
413 \\const E = enum {
414 \\ Ok,
415 \\ SomethingElse = 0,
416 \\};
417 \\
418 \\const E2 = enum(u8) {
419 \\ Ok,
420 \\ SomethingElse = 255,
421 \\ SomethingThird,
422 \\};
423 \\
424 \\const Ee = extern enum {
425 \\ Ok,
426 \\ SomethingElse,
427 \\ SomethingThird,
428 \\};
429 \\
430 \\const Ep = packed enum {
431 \\ Ok,
432 \\ SomethingElse,
433 \\ SomethingThird,
434 \\};
435 \\
436 );
437}
438
439test "zig fmt: union declaration" {
440 try testCanonical(
441 \\const U = union {
442 \\ Int: u8,
443 \\ Float: f32,
444 \\ None,
445 \\ Bool: bool,
446 \\};
447 \\
448 \\const Ue = union(enum) {
449 \\ Int: u8,
450 \\ Float: f32,
451 \\ None,
452 \\ Bool: bool,
453 \\};
454 \\
455 \\const E = enum {
456 \\ Int,
457 \\ Float,
458 \\ None,
459 \\ Bool,
460 \\};
461 \\
462 \\const Ue2 = union(E) {
463 \\ Int: u8,
464 \\ Float: f32,
465 \\ None,
466 \\ Bool: bool,
467 \\};
468 \\
469 \\const Eu = extern union {
470 \\ Int: u8,
471 \\ Float: f32,
472 \\ None,
473 \\ Bool: bool,
474 \\};
475 \\
476 );
477}
478
479test "zig fmt: error set declaration" {
480 try testCanonical(
481 \\const E = error {
482 \\ A,
483 \\ B,
484 \\
485 \\ C,
486 \\};
487 \\
488 );
489}
490
491test "zig fmt: arrays" {
492 try testCanonical(
493 \\test "test array" {
494 \\ const a: [2]u8 = [2]u8 {
495 \\ 1,
496 \\ 2,
497 \\ };
498 \\ const a: [2]u8 = []u8 {
499 \\ 1,
500 \\ 2,
501 \\ };
502 \\ const a: [0]u8 = []u8{};
503 \\}
504 \\
505 );
506}
507
508test "zig fmt: container initializers" {
509 try testCanonical(
510 \\const a1 = []u8{};
511 \\const a2 = []u8 {
512 \\ 1,
513 \\ 2,
514 \\ 3,
515 \\ 4,
516 \\};
517 \\const s1 = S{};
518 \\const s2 = S {
519 \\ .a = 1,
520 \\ .b = 2,
521 \\};
522 \\
523 );
524}
525
526test "zig fmt: catch" {
527 try testCanonical(
528 \\test "catch" {
529 \\ const a: error!u8 = 0;
530 \\ _ = a catch return;
531 \\ _ = a catch |err| return;
532 \\}
533 \\
534 );
535}
536
537test "zig fmt: blocks" {
538 try testCanonical(
539 \\test "blocks" {
540 \\ {
541 \\ const a = 0;
542 \\ const b = 0;
543 \\ }
544 \\
545 \\ blk: {
546 \\ const a = 0;
547 \\ const b = 0;
548 \\ }
549 \\
550 \\ const r = blk: {
551 \\ const a = 0;
552 \\ const b = 0;
553 \\ };
554 \\}
555 \\
556 );
557}
558
559test "zig fmt: switch" {
560 try testCanonical(
561 \\test "switch" {
562 \\ switch (0) {
563 \\ 0 => {},
564 \\ 1 => unreachable,
565 \\ 2,
566 \\ 3 => {},
567 \\ 4 ... 7 => {},
568 \\ 1 + 4 * 3 + 22 => {},
569 \\ else => {
570 \\ const a = 1;
571 \\ const b = a;
572 \\ },
573 \\ }
574 \\
575 \\ const res = switch (0) {
576 \\ 0 => 0,
577 \\ 1 => 2,
578 \\ 1 => a = 4,
579 \\ else => 4,
580 \\ };
581 \\
582 \\ const Union = union(enum) {
583 \\ Int: i64,
584 \\ Float: f64,
585 \\ };
586 \\
587 \\ const u = Union {
588 \\ .Int = 0,
589 \\ };
590 \\ switch (u) {
591 \\ Union.Int => |int| {},
592 \\ Union.Float => |*float| unreachable,
593 \\ }
594 \\}
595 \\
596 );
597}
598
599test "zig fmt: while" {
600 try testCanonical(
601 \\test "while" {
602 \\ while (10 < 1) {
603 \\ unreachable;
604 \\ }
605 \\
606 \\ while (10 < 1)
607 \\ unreachable;
608 \\
609 \\ var i: usize = 0;
610 \\ while (i < 10) : (i += 1) {
611 \\ continue;
612 \\ }
613 \\
614 \\ i = 0;
615 \\ while (i < 10) : (i += 1)
616 \\ continue;
617 \\
618 \\ i = 0;
619 \\ var j: usize = 0;
620 \\ while (i < 10) : ({
621 \\ i += 1;
622 \\ j += 1;
623 \\ }) {
624 \\ continue;
625 \\ }
626 \\
627 \\ var a: ?u8 = 2;
628 \\ while (a) |v| : (a = null) {
629 \\ continue;
630 \\ }
631 \\
632 \\ while (a) |v| : (a = null)
633 \\ unreachable;
634 \\
635 \\ label: while (10 < 0) {
636 \\ unreachable;
637 \\ }
638 \\
639 \\ const res = while (0 < 10) {
640 \\ break 7;
641 \\ } else {
642 \\ unreachable;
643 \\ };
644 \\
645 \\ const res = while (0 < 10)
646 \\ break 7
647 \\ else
648 \\ unreachable;
649 \\
650 \\ var a: error!u8 = 0;
651 \\ while (a) |v| {
652 \\ a = error.Err;
653 \\ } else |err| {
654 \\ i = 1;
655 \\ }
656 \\
657 \\ comptime var k: usize = 0;
658 \\ inline while (i < 10) : (i += 1)
659 \\ j += 2;
660 \\}
661 \\
662 );
663}
664
665test "zig fmt: for" {
666 try testCanonical(
667 \\test "for" {
668 \\ const a = []u8 {
669 \\ 1,
670 \\ 2,
671 \\ 3,
672 \\ };
673 \\ for (a) |v| {
674 \\ continue;
675 \\ }
676 \\
677 \\ for (a) |v|
678 \\ continue;
679 \\
680 \\ for (a) |*v|
681 \\ continue;
682 \\
683 \\ for (a) |v, i| {
684 \\ continue;
685 \\ }
686 \\
687 \\ for (a) |v, i|
688 \\ continue;
689 \\
690 \\ const res = for (a) |v, i| {
691 \\ break v;
692 \\ } else {
693 \\ unreachable;
694 \\ };
695 \\
696 \\ var num: usize = 0;
697 \\ inline for (a) |v, i| {
698 \\ num += v;
699 \\ num += i;
700 \\ }
701 \\}
702 \\
703 );
704}
705
706test "zig fmt: if" {
707 try testCanonical(
708 \\test "if" {
709 \\ if (10 < 0) {
710 \\ unreachable;
711 \\ }
712 \\
713 \\ if (10 < 0) unreachable;
714 \\
715 \\ if (10 < 0) {
716 \\ unreachable;
717 \\ } else {
718 \\ const a = 20;
719 \\ }
720 \\
721 \\ if (10 < 0) {
722 \\ unreachable;
723 \\ } else if (5 < 0) {
724 \\ unreachable;
725 \\ } else {
726 \\ const a = 20;
727 \\ }
728 \\
729 \\ const is_world_broken = if (10 < 0) true else false;
730 \\ const some_number = 1 + if (10 < 0) 2 else 3;
731 \\
732 \\ const a: ?u8 = 10;
733 \\ const b: ?u8 = null;
734 \\ if (a) |v| {
735 \\ const some = v;
736 \\ } else if (b) |*v| {
737 \\ unreachable;
738 \\ } else {
739 \\ const some = 10;
740 \\ }
741 \\
742 \\ const non_null_a = if (a) |v| v else 0;
743 \\
744 \\ const a_err: error!u8 = 0;
745 \\ if (a_err) |v| {
746 \\ const p = v;
747 \\ } else |err| {
748 \\ unreachable;
749 \\ }
750 \\}
751 \\
752 );
753}
754
755test "zig fmt: defer" {
756 try testCanonical(
757 \\test "defer" {
758 \\ var i: usize = 0;
759 \\ defer i = 1;
760 \\ defer {
761 \\ i += 2;
762 \\ i *= i;
763 \\ }
764 \\
765 \\ errdefer i += 3;
766 \\ errdefer {
767 \\ i += 2;
768 \\ i /= i;
769 \\ }
770 \\}
771 \\
772 );
773}
774
775test "zig fmt: comptime" {
776 try testCanonical(
777 \\fn a() u8 {
778 \\ return 5;
779 \\}
780 \\
781 \\fn b(comptime i: u8) u8 {
782 \\ return i;
783 \\}
784 \\
785 \\const av = comptime a();
786 \\const av2 = comptime blk: {
787 \\ var res = a();
788 \\ res *= b(2);
789 \\ break :blk res;
790 \\};
791 \\
792 \\comptime {
793 \\ _ = a();
794 \\}
795 \\
796 \\test "comptime" {
797 \\ const av3 = comptime a();
798 \\ const av4 = comptime blk: {
799 \\ var res = a();
800 \\ res *= a();
801 \\ break :blk res;
802 \\ };
803 \\
804 \\ comptime var i = 0;
805 \\ comptime {
806 \\ i = a();
807 \\ i += b(i);
808 \\ }
809 \\}
810 \\
811 );
812}
813
814test "zig fmt: fn type" {
815 try testCanonical(
816 \\fn a(i: u8) u8 {
817 \\ return i + 1;
818 \\}
819 \\
820 \\const a: fn(u8) u8 = undefined;
821 \\const b: extern fn(u8) u8 = undefined;
822 \\const c: nakedcc fn(u8) u8 = undefined;
823 \\const ap: fn(u8) u8 = a;
824 \\
825 );
826}
827
828test "zig fmt: inline asm" {
829 try testCanonical(
830 \\pub fn syscall1(number: usize, arg1: usize) usize {
831 \\ return asm volatile ("syscall"
832 \\ : [ret] "={rax}" (-> usize)
833 \\ : [number] "{rax}" (number),
834 \\ [arg1] "{rdi}" (arg1)
835 \\ : "rcx", "r11");
836 \\}
837 \\
838 );
839}
840
841test "zig fmt: coroutines" {
842 try testCanonical(
843 \\async fn simpleAsyncFn() void {
844 \\ const a = async a.b();
845 \\ x += 1;
846 \\ suspend;
847 \\ x += 1;
848 \\ suspend |p| {}
849 \\ const p = async simpleAsyncFn() catch unreachable;
850 \\ await p;
851 \\}
852 \\
853 \\test "coroutine suspend, resume, cancel" {
854 \\ const p = try async<std.debug.global_allocator> testAsyncSeq();
855 \\ resume p;
856 \\ cancel p;
857 \\}
858 \\
859 );
860}
861
862test "zig fmt: Block after if" {
863 try testCanonical(
864 \\test "Block after if" {
865 \\ if (true) {
866 \\ const a = 0;
867 \\ }
868 \\
869 \\ {
870 \\ const a = 0;
871 \\ }
872 \\}
873 \\
874 );
875}
876
877test "zig fmt: use" {
878 try testCanonical(
879 \\use @import("std");
880 \\pub use @import("std");
881 \\
882 );
883}
884
885test "zig fmt: string identifier" {
886 try testCanonical(
887 \\const @"a b" = @"c d".@"e f";
888 \\fn @"g h"() void {}
889 \\
890 );
891}
892
893test "zig fmt: error return" {
894 try testCanonical(
895 \\fn err() error {
896 \\ call();
897 \\ return error.InvalidArgs;
898 \\}
899 \\
900 );
901}
902
903test "zig fmt: struct literals with fields on each line" {
904 try testCanonical(
905 \\var self = BufSet {
906 \\ .hash_map = BufSetHashMap.init(a),
907 \\};
908 \\
909 );
910}
911
912const std = @import("std");
913const mem = std.mem;
914const warn = std.debug.warn;
915const Tokenizer = std.zig.Tokenizer;
916const Parser = std.zig.Parser;
917const io = std.io;
918
919var fixed_buffer_mem: [100 * 1024]u8 = undefined;
920
921fn testParse(source: []const u8, allocator: &mem.Allocator) ![]u8 {
922 var tokenizer = Tokenizer.init(source);
923 var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");
924 defer parser.deinit();
925
926 var tree = try parser.parse();
927 defer tree.deinit();
928
929 var buffer = try std.Buffer.initSize(allocator, 0);
930 errdefer buffer.deinit();
931
932 var buffer_out_stream = io.BufferOutStream.init(&buffer);
933 try parser.renderSource(&buffer_out_stream.stream, tree.root_node);
934 return buffer.toOwnedSlice();
935}
936
937fn testCanonical(source: []const u8) !void {
938 const needed_alloc_count = x: {
939 // Try it once with unlimited memory, make sure it works
940 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
941 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
942 const result_source = try testParse(source, &failing_allocator.allocator);
943 if (!mem.eql(u8, result_source, source)) {
944 warn("\n====== expected this output: =========\n");
945 warn("{}", source);
946 warn("\n======== instead found this: =========\n");
947 warn("{}", result_source);
948 warn("\n======================================\n");
949 return error.TestFailed;
950 }
951 failing_allocator.allocator.free(result_source);
952 break :x failing_allocator.index;
953 };
954
955 var fail_index: usize = 0;
956 while (fail_index < needed_alloc_count) : (fail_index += 1) {
957 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
958 var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index);
959 if (testParse(source, &failing_allocator.allocator)) |_| {
960 return error.NondeterministicMemoryUsage;
961 } else |err| switch (err) {
962 error.OutOfMemory => {
963 if (failing_allocator.allocated_bytes != failing_allocator.freed_bytes) {
964 warn("\nfail_index: {}/{}\nallocated bytes: {}\nfreed bytes: {}\nallocations: {}\ndeallocations: {}\n",
965 fail_index, needed_alloc_count,
966 failing_allocator.allocated_bytes, failing_allocator.freed_bytes,
967 failing_allocator.index, failing_allocator.deallocations);
968 return error.MemoryLeakDetected;
969 }
970 },
971 error.ParseError => @panic("test failed"),
972 }
973 }
974}
975