authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-02-10 19:16:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-10 11:53:53-08:00
log5df7fc36c6e5d7caf7b5b5437bf40fec77a2b971
treea8a4539ba9abe8681729ccab0f9b4c30b5819ac1
parent928f6f48a62b4b356a0031ba54e247dbbcde4256

zig fmt: implement Tree.lastToken() for struct init


4 files changed, 98 insertions(+), 61 deletions(-)

lib/std/zig/ast.zig+31-15
...@@ -259,6 +259,7 @@ pub const Tree = struct {...@@ -259,6 +259,7 @@ pub const Tree = struct {
259 .ArrayInitDotTwo,259 .ArrayInitDotTwo,
260 .ArrayInitDotTwoComma,260 .ArrayInitDotTwoComma,
261 .StructInitDot,261 .StructInitDot,
262 .StructInitDotComma,
262 .StructInitDotTwo,263 .StructInitDotTwo,
263 .StructInitDotTwoComma,264 .StructInitDotTwoComma,
264 .EnumLiteral,265 .EnumLiteral,
...@@ -316,7 +317,9 @@ pub const Tree = struct {...@@ -316,7 +317,9 @@ pub const Tree = struct {
316 .ArrayInit,317 .ArrayInit,
317 .ArrayInitComma,318 .ArrayInitComma,
318 .StructInitOne,319 .StructInitOne,
320 .StructInitOneComma,
319 .StructInit,321 .StructInit,
322 .StructInitComma,
320 .CallOne,323 .CallOne,
321 .CallOneComma,324 .CallOneComma,
322 .Call,325 .Call,
...@@ -607,13 +610,16 @@ pub const Tree = struct {...@@ -607,13 +610,16 @@ pub const Tree = struct {
607 const extra = tree.extraData(datas[n].rhs, Node.Asm);610 const extra = tree.extraData(datas[n].rhs, Node.Asm);
608 return extra.rparen + end_offset;611 return extra.rparen + end_offset;
609 },612 },
610 .ArrayInit => {613 .ArrayInit,
614 .StructInit,
615 => {
611 const elements = tree.extraData(datas[n].rhs, Node.SubRange);616 const elements = tree.extraData(datas[n].rhs, Node.SubRange);
612 assert(elements.end - elements.start > 0);617 assert(elements.end - elements.start > 0);
613 end_offset += 1; // for the rbrace618 end_offset += 1; // for the rbrace
614 n = tree.extra_data[elements.end - 1]; // last element619 n = tree.extra_data[elements.end - 1]; // last element
615 },620 },
616 .ArrayInitComma,621 .ArrayInitComma,
622 .StructInitComma,
617 .ContainerDeclArgComma,623 .ContainerDeclArgComma,
618 .SwitchComma,624 .SwitchComma,
619 => {625 => {
...@@ -623,6 +629,7 @@ pub const Tree = struct {...@@ -623,6 +629,7 @@ pub const Tree = struct {
623 n = tree.extra_data[members.end - 1]; // last parameter629 n = tree.extra_data[members.end - 1]; // last parameter
624 },630 },
625 .ArrayInitDot,631 .ArrayInitDot,
632 .StructInitDot,
626 .Block,633 .Block,
627 .ContainerDecl,634 .ContainerDecl,
628 .TaggedUnion,635 .TaggedUnion,
...@@ -633,6 +640,7 @@ pub const Tree = struct {...@@ -633,6 +640,7 @@ pub const Tree = struct {
633 n = tree.extra_data[datas[n].rhs - 1]; // last statement640 n = tree.extra_data[datas[n].rhs - 1]; // last statement
634 },641 },
635 .ArrayInitDotComma,642 .ArrayInitDotComma,
643 .StructInitDotComma,
636 .BlockSemicolon,644 .BlockSemicolon,
637 .ContainerDeclComma,645 .ContainerDeclComma,
638 .TaggedUnionComma,646 .TaggedUnionComma,
...@@ -784,7 +792,9 @@ pub const Tree = struct {...@@ -784,7 +792,9 @@ pub const Tree = struct {
784 }792 }
785 },793 },
786794
787 .ArrayInitOne => {795 .ArrayInitOne,
796 .StructInitOne,
797 => {
788 end_offset += 1; // rbrace798 end_offset += 1; // rbrace
789 n = datas[n].rhs;799 n = datas[n].rhs;
790 assert(n != 0);800 assert(n != 0);
...@@ -793,6 +803,7 @@ pub const Tree = struct {...@@ -793,6 +803,7 @@ pub const Tree = struct {
793 .CallOneComma,803 .CallOneComma,
794 .AsyncCallOneComma,804 .AsyncCallOneComma,
795 .ArrayInitOneComma,805 .ArrayInitOneComma,
806 .StructInitOneComma,
796 => {807 => {
797 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen808 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
798 n = datas[n].rhs;809 n = datas[n].rhs;
...@@ -929,14 +940,6 @@ pub const Tree = struct {...@@ -929,14 +940,6 @@ pub const Tree = struct {
929 n = extra.elem_type;940 n = extra.elem_type;
930 },941 },
931942
932 // These are not supported by lastToken() because implementation would
933 // require recursion due to the optional comma followed by rbrace.
934 // TODO follow the pattern set by StructInitDotTwoComma which will allow
935 // lastToken to work for all of these.
936 .StructInit => unreachable, // TODO
937 .StructInitOne => unreachable, // TODO
938 .StructInitDot => unreachable, // TODO
939
940 .TaggedUnionEnumTag => unreachable, // TODO943 .TaggedUnionEnumTag => unreachable, // TODO
941 .TaggedUnionEnumTagComma => unreachable, // TODO944 .TaggedUnionEnumTagComma => unreachable, // TODO
942 .SwitchRange => unreachable, // TODO945 .SwitchRange => unreachable, // TODO
...@@ -1118,7 +1121,8 @@ pub const Tree = struct {...@@ -1118,7 +1121,8 @@ pub const Tree = struct {
1118 }1121 }
11191122
1120 pub fn structInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {1123 pub fn structInitOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {
1121 assert(tree.nodes.items(.tag)[node] == .StructInitOne);1124 assert(tree.nodes.items(.tag)[node] == .StructInitOne or
1125 tree.nodes.items(.tag)[node] == .StructInitOneComma);
1122 const data = tree.nodes.items(.data)[node];1126 const data = tree.nodes.items(.data)[node];
1123 buffer[0] = data.rhs;1127 buffer[0] = data.rhs;
1124 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];1128 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
...@@ -1148,7 +1152,8 @@ pub const Tree = struct {...@@ -1148,7 +1152,8 @@ pub const Tree = struct {
1148 }1152 }
11491153
1150 pub fn structInitDot(tree: Tree, node: Node.Index) full.StructInit {1154 pub fn structInitDot(tree: Tree, node: Node.Index) full.StructInit {
1151 assert(tree.nodes.items(.tag)[node] == .StructInitDot);1155 assert(tree.nodes.items(.tag)[node] == .StructInitDot or
1156 tree.nodes.items(.tag)[node] == .StructInitDotComma);
1152 const data = tree.nodes.items(.data)[node];1157 const data = tree.nodes.items(.data)[node];
1153 return tree.fullStructInit(.{1158 return tree.fullStructInit(.{
1154 .lbrace = tree.nodes.items(.main_token)[node],1159 .lbrace = tree.nodes.items(.main_token)[node],
...@@ -1158,7 +1163,8 @@ pub const Tree = struct {...@@ -1158,7 +1163,8 @@ pub const Tree = struct {
1158 }1163 }
11591164
1160 pub fn structInit(tree: Tree, node: Node.Index) full.StructInit {1165 pub fn structInit(tree: Tree, node: Node.Index) full.StructInit {
1161 assert(tree.nodes.items(.tag)[node] == .StructInit);1166 assert(tree.nodes.items(.tag)[node] == .StructInit or
1167 tree.nodes.items(.tag)[node] == .StructInitComma);
1162 const data = tree.nodes.items(.data)[node];1168 const data = tree.nodes.items(.data)[node];
1163 const fields_range = tree.extraData(data.rhs, Node.SubRange);1169 const fields_range = tree.extraData(data.rhs, Node.SubRange);
1164 return tree.fullStructInit(.{1170 return tree.fullStructInit(.{
...@@ -2281,6 +2287,8 @@ pub const Node = struct {...@@ -2281,6 +2287,8 @@ pub const Node = struct {
2281 assert(@sizeOf(Tag) == 1);2287 assert(@sizeOf(Tag) == 1);
2282 }2288 }
22832289
2290 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of
2291 /// Tree.lastToken()
2284 pub const Tag = enum {2292 pub const Tag = enum {
2285 /// sub_list[lhs...rhs]2293 /// sub_list[lhs...rhs]
2286 Root,2294 Root,
...@@ -2477,21 +2485,29 @@ pub const Node = struct {...@@ -2477,21 +2485,29 @@ pub const Node = struct {
2477 /// `lhs{.a = rhs}`. rhs can be omitted making it empty.2485 /// `lhs{.a = rhs}`. rhs can be omitted making it empty.
2478 /// main_token is the lbrace.2486 /// main_token is the lbrace.
2479 StructInitOne,2487 StructInitOne,
2488 /// `lhs{.a = rhs,}`. rhs can *not* be omitted.
2489 /// main_token is the lbrace.
2490 StructInitOneComma,
2480 /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted.2491 /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted.
2481 /// main_token is the lbrace.2492 /// main_token is the lbrace.
2482 /// No trailing comma before the rbrace.2493 /// No trailing comma before the rbrace.
2483 StructInitDotTwo,2494 StructInitDotTwo,
2484 /// Same as `StructInitDotTwo` except there is known to be a trailing comma2495 /// Same as `StructInitDotTwo` except there is known to be a trailing comma
2485 /// before the final rbrace. This tag exists to facilitate lastToken() implemented2496 /// before the final rbrace.
2486 /// without recursion.
2487 StructInitDotTwoComma,2497 StructInitDotTwoComma,
2488 /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`.2498 /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`.
2489 /// main_token is the lbrace.2499 /// main_token is the lbrace.
2490 StructInitDot,2500 StructInitDot,
2501 /// Same as `StructInitDot` except there is known to be a trailing comma
2502 /// before the final rbrace.
2503 StructInitDotComma,
2491 /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`.2504 /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`.
2492 /// lhs can be omitted which means `.{.a = b, .c = d}`.2505 /// lhs can be omitted which means `.{.a = b, .c = d}`.
2493 /// main_token is the lbrace.2506 /// main_token is the lbrace.
2494 StructInit,2507 StructInit,
2508 /// Same as `StructInit` except there is known to be a trailing comma
2509 /// before the final rbrace.
2510 StructInitComma,
2495 /// `lhs(rhs)`. rhs can be omitted.2511 /// `lhs(rhs)`. rhs can be omitted.
2496 CallOne,2512 CallOne,
2497 /// `lhs(rhs,)`. rhs can be omitted.2513 /// `lhs(rhs,)`. rhs can be omitted.
lib/std/zig/parse.zig+6-13
...@@ -2147,7 +2147,7 @@ const Parser = struct {...@@ -2147,7 +2147,7 @@ const Parser = struct {
2147 const comma_one = p.eatToken(.Comma);2147 const comma_one = p.eatToken(.Comma);
2148 if (p.eatToken(.RBrace)) |_| {2148 if (p.eatToken(.RBrace)) |_| {
2149 return p.addNode(.{2149 return p.addNode(.{
2150 .tag = .StructInitOne,2150 .tag = if (comma_one != null) .StructInitOneComma else .StructInitOne,
2151 .main_token = lbrace,2151 .main_token = lbrace,
2152 .data = .{2152 .data = .{
2153 .lhs = lhs,2153 .lhs = lhs,
...@@ -2192,7 +2192,7 @@ const Parser = struct {...@@ -2192,7 +2192,7 @@ const Parser = struct {
2192 }2192 }
2193 const span = try p.listToSpan(init_list.items);2193 const span = try p.listToSpan(init_list.items);
2194 return p.addNode(.{2194 return p.addNode(.{
2195 .tag = .StructInit,2195 .tag = if (p.token_tags[p.tok_i - 2] == .Comma) .StructInitComma else .StructInit,
2196 .main_token = lbrace,2196 .main_token = lbrace,
2197 .data = .{2197 .data = .{
2198 .lhs = lhs,2198 .lhs = lhs,
...@@ -2709,12 +2709,8 @@ const Parser = struct {...@@ -2709,12 +2709,8 @@ const Parser = struct {
2709 if (field_init_one != 0) {2709 if (field_init_one != 0) {
2710 const comma_one = p.eatToken(.Comma);2710 const comma_one = p.eatToken(.Comma);
2711 if (p.eatToken(.RBrace)) |_| {2711 if (p.eatToken(.RBrace)) |_| {
2712 const tag: Node.Tag = if (comma_one != null)
2713 .StructInitDotTwoComma
2714 else
2715 .StructInitDotTwo;
2716 return p.addNode(.{2712 return p.addNode(.{
2717 .tag = tag,2713 .tag = if (comma_one != null) .StructInitDotTwoComma else .StructInitDotTwo,
2718 .main_token = lbrace,2714 .main_token = lbrace,
2719 .data = .{2715 .data = .{
2720 .lhs = field_init_one,2716 .lhs = field_init_one,
...@@ -2730,12 +2726,8 @@ const Parser = struct {...@@ -2730,12 +2726,8 @@ const Parser = struct {
2730 const field_init_two = try p.expectFieldInit();2726 const field_init_two = try p.expectFieldInit();
2731 const comma_two = p.eatToken(.Comma);2727 const comma_two = p.eatToken(.Comma);
2732 if (p.eatToken(.RBrace)) |_| {2728 if (p.eatToken(.RBrace)) |_| {
2733 const tag: Node.Tag = if (comma_two != null)
2734 .StructInitDotTwoComma
2735 else
2736 .StructInitDotTwo;
2737 return p.addNode(.{2729 return p.addNode(.{
2738 .tag = tag,2730 .tag = if (comma_two != null) .StructInitDotTwoComma else .StructInitDotTwo,
2739 .main_token = lbrace,2731 .main_token = lbrace,
2740 .data = .{2732 .data = .{
2741 .lhs = field_init_one,2733 .lhs = field_init_one,
...@@ -2784,8 +2776,9 @@ const Parser = struct {...@@ -2784,8 +2776,9 @@ const Parser = struct {
2784 }2776 }
2785 }2777 }
2786 const span = try p.listToSpan(init_list.items);2778 const span = try p.listToSpan(init_list.items);
2779 const trailing_comma = p.token_tags[p.tok_i - 2] == .Comma;
2787 return p.addNode(.{2780 return p.addNode(.{
2788 .tag = .StructInitDot,2781 .tag = if (trailing_comma) .StructInitDotComma else .StructInitDot,
2789 .main_token = lbrace,2782 .main_token = lbrace,
2790 .data = .{2783 .data = .{
2791 .lhs = span.start,2784 .lhs = span.start,
lib/std/zig/parser_test.zig+54-30
...@@ -466,102 +466,126 @@ test "zig fmt: anon literal in array" {...@@ -466,102 +466,126 @@ test "zig fmt: anon literal in array" {
466466
467test "zig fmt: anon struct literal 1 element" {467test "zig fmt: anon struct literal 1 element" {
468 try testCanonical(468 try testCanonical(
469 \\const x = .{ .a = b };469 \\test {
470 \\ const x = .{ .a = b };
471 \\}
470 \\472 \\
471 );473 );
472}474}
473475
474test "zig fmt: anon struct literal 1 element comma" {476test "zig fmt: anon struct literal 1 element comma" {
475 try testCanonical(477 try testCanonical(
476 \\const x = .{478 \\test {
477 \\ .a = b,479 \\ const x = .{
478 \\};480 \\ .a = b,
481 \\ };
482 \\}
479 \\483 \\
480 );484 );
481}485}
482486
483test "zig fmt: anon struct literal 2 element" {487test "zig fmt: anon struct literal 2 element" {
484 try testCanonical(488 try testCanonical(
485 \\const x = .{ .a = b, .c = d };489 \\test {
490 \\ const x = .{ .a = b, .c = d };
491 \\}
486 \\492 \\
487 );493 );
488}494}
489495
490test "zig fmt: anon struct literal 2 element comma" {496test "zig fmt: anon struct literal 2 element comma" {
491 try testCanonical(497 try testCanonical(
492 \\const x = .{498 \\test {
493 \\ .a = b,499 \\ const x = .{
494 \\ .c = d,500 \\ .a = b,
495 \\};501 \\ .c = d,
502 \\ };
503 \\}
496 \\504 \\
497 );505 );
498}506}
499507
500test "zig fmt: anon struct literal 3 element" {508test "zig fmt: anon struct literal 3 element" {
501 try testCanonical(509 try testCanonical(
502 \\const x = .{ .a = b, .c = d, .e = f };510 \\test {
511 \\ const x = .{ .a = b, .c = d, .e = f };
512 \\}
503 \\513 \\
504 );514 );
505}515}
506516
507test "zig fmt: anon struct literal 3 element comma" {517test "zig fmt: anon struct literal 3 element comma" {
508 try testCanonical(518 try testCanonical(
509 \\const x = .{519 \\test {
510 \\ .a = b,520 \\ const x = .{
511 \\ .c = d,521 \\ .a = b,
512 \\ .e = f,522 \\ .c = d,
513 \\};523 \\ .e = f,
524 \\ };
525 \\}
514 \\526 \\
515 );527 );
516}528}
517529
518test "zig fmt: struct literal 1 element" {530test "zig fmt: struct literal 1 element" {
519 try testCanonical(531 try testCanonical(
520 \\const x = X{ .a = b };532 \\test {
533 \\ const x = X{ .a = b };
534 \\}
521 \\535 \\
522 );536 );
523}537}
524538
525test "zig fmt: struct literal 1 element comma" {539test "zig fmt: struct literal 1 element comma" {
526 try testCanonical(540 try testCanonical(
527 \\const x = X{541 \\test {
528 \\ .a = b,542 \\ const x = X{
529 \\};543 \\ .a = b,
544 \\ };
545 \\}
530 \\546 \\
531 );547 );
532}548}
533549
534test "zig fmt: struct literal 2 element" {550test "zig fmt: struct literal 2 element" {
535 try testCanonical(551 try testCanonical(
536 \\const x = X{ .a = b, .c = d };552 \\test {
553 \\ const x = X{ .a = b, .c = d };
554 \\}
537 \\555 \\
538 );556 );
539}557}
540558
541test "zig fmt: struct literal 2 element comma" {559test "zig fmt: struct literal 2 element comma" {
542 try testCanonical(560 try testCanonical(
543 \\const x = X{561 \\test {
544 \\ .a = b,562 \\ const x = X{
545 \\ .c = d,563 \\ .a = b,
546 \\};564 \\ .c = d,
565 \\ };
566 \\}
547 \\567 \\
548 );568 );
549}569}
550570
551test "zig fmt: struct literal 3 element" {571test "zig fmt: struct literal 3 element" {
552 try testCanonical(572 try testCanonical(
553 \\const x = X{ .a = b, .c = d, .e = f };573 \\test {
574 \\ const x = X{ .a = b, .c = d, .e = f };
575 \\}
554 \\576 \\
555 );577 );
556}578}
557579
558test "zig fmt: struct literal 3 element comma" {580test "zig fmt: struct literal 3 element comma" {
559 try testCanonical(581 try testCanonical(
560 \\const x = X{582 \\test {
561 \\ .a = b,583 \\ const x = X{
562 \\ .c = d,584 \\ .a = b,
563 \\ .e = f,585 \\ .c = d,
564 \\};586 \\ .e = f,
587 \\ };
588 \\}
565 \\589 \\
566 );590 );
567}591}
lib/std/zig/render.zig+7-3
...@@ -405,7 +405,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -405,7 +405,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
405 .ArrayInitComma,405 .ArrayInitComma,
406 => return renderArrayInit(ais, tree, tree.arrayInit(node), space),406 => return renderArrayInit(ais, tree, tree.arrayInit(node), space),
407407
408 .StructInitOne => {408 .StructInitOne, .StructInitOneComma => {
409 var fields: [1]ast.Node.Index = undefined;409 var fields: [1]ast.Node.Index = undefined;
410 return renderStructInit(ais, tree, tree.structInitOne(&fields, node), space);410 return renderStructInit(ais, tree, tree.structInitOne(&fields, node), space);
411 },411 },
...@@ -413,8 +413,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -413,8 +413,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
413 var fields: [2]ast.Node.Index = undefined;413 var fields: [2]ast.Node.Index = undefined;
414 return renderStructInit(ais, tree, tree.structInitDotTwo(&fields, node), space);414 return renderStructInit(ais, tree, tree.structInitDotTwo(&fields, node), space);
415 },415 },
416 .StructInitDot => return renderStructInit(ais, tree, tree.structInitDot(node), space),416 .StructInitDot,
417 .StructInit => return renderStructInit(ais, tree, tree.structInit(node), space),417 .StructInitDotComma,
418 => return renderStructInit(ais, tree, tree.structInitDot(node), space),
419 .StructInit,
420 .StructInitComma,
421 => return renderStructInit(ais, tree, tree.structInit(node), space),
418422
419 .CallOne, .CallOneComma, .AsyncCallOne, .AsyncCallOneComma => {423 .CallOne, .CallOneComma, .AsyncCallOne, .AsyncCallOneComma => {
420 var params: [1]ast.Node.Index = undefined;424 var params: [1]ast.Node.Index = undefined;