| ... | ... | @@ -596,6 +596,28 @@ fn renderExpression( |
| 596 | 596 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| 597 | 597 | } |
| 598 | 598 | |
| 599 | const src_has_trailing_comma = blk: { |
| 600 | const maybe_comma = tree.prevToken(suffix_op.rtoken); |
| 601 | break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; |
| 602 | }; |
| 603 | |
| 604 | const src_same_line = blk: { |
| 605 | const loc = tree.tokenLocation(tree.tokens.at(lbrace).end, suffix_op.rtoken); |
| 606 | break :blk loc.line == 0; |
| 607 | }; |
| 608 | |
| 609 | const expr_outputs_one_line = blk: { |
| 610 | // render field expressions until a LF is found |
| 611 | var it = field_inits.iterator(0); |
| 612 | while (it.next()) |field_init| { |
| 613 | var find_stream = FindByteOutStream.init('\n'); |
| 614 | var dummy_col: usize = 0; |
| 615 | try renderExpression(allocator, &find_stream.stream, tree, 0, &dummy_col, field_init.*, Space.None); |
| 616 | if (find_stream.byte_found) break :blk false; |
| 617 | } |
| 618 | break :blk true; |
| 619 | }; |
| 620 | |
| 599 | 621 | if (field_inits.len == 1) blk: { |
| 600 | 622 | const field_init = field_inits.at(0).*.cast(ast.Node.FieldInitializer).?; |
| 601 | 623 | |
| ... | ... | @@ -605,23 +627,18 @@ fn renderExpression( |
| 605 | 627 | } |
| 606 | 628 | } |
| 607 | 629 | |
| 630 | // if the expression outputs to multiline, make this struct multiline |
| 631 | if (!expr_outputs_one_line or src_has_trailing_comma) { |
| 632 | break :blk; |
| 633 | } |
| 634 | |
| 608 | 635 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); |
| 609 | 636 | try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); |
| 610 | 637 | try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space); |
| 611 | 638 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); |
| 612 | 639 | } |
| 613 | 640 | |
| 614 | | const src_has_trailing_comma = blk: { |
| 615 | | const maybe_comma = tree.prevToken(suffix_op.rtoken); |
| 616 | | break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; |
| 617 | | }; |
| 618 | | |
| 619 | | const src_same_line = blk: { |
| 620 | | const loc = tree.tokenLocation(tree.tokens.at(lbrace).end, suffix_op.rtoken); |
| 621 | | break :blk loc.line == 0; |
| 622 | | }; |
| 623 | | |
| 624 | | if (!src_has_trailing_comma and src_same_line) { |
| 641 | if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) { |
| 625 | 642 | // render all on one line, no trailing comma |
| 626 | 643 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); |
| 627 | 644 | try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); |
| ... | ... | @@ -2092,3 +2109,33 @@ fn nodeCausesSliceOpSpace(base: *ast.Node) bool { |
| 2092 | 2109 | else => true, |
| 2093 | 2110 | }; |
| 2094 | 2111 | } |
| 2112 | |
| 2113 | // An OutStream that returns whether the given character has been written to it. |
| 2114 | // The contents are not written to anything. |
| 2115 | const FindByteOutStream = struct { |
| 2116 | const Self = FindByteOutStream; |
| 2117 | pub const Error = error{}; |
| 2118 | pub const Stream = std.io.OutStream(Error); |
| 2119 | |
| 2120 | pub stream: Stream, |
| 2121 | pub byte_found: bool, |
| 2122 | byte: u8, |
| 2123 | |
| 2124 | pub fn init(byte: u8) Self { |
| 2125 | return Self{ |
| 2126 | .stream = Stream{ .writeFn = writeFn }, |
| 2127 | .byte = byte, |
| 2128 | .byte_found = false, |
| 2129 | }; |
| 2130 | } |
| 2131 | |
| 2132 | fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void { |
| 2133 | const self = @fieldParentPtr(Self, "stream", out_stream); |
| 2134 | if (self.byte_found) return; |
| 2135 | self.byte_found = blk: { |
| 2136 | for (bytes) |b| |
| 2137 | if (b == self.byte) break :blk true; |
| 2138 | break :blk false; |
| 2139 | }; |
| 2140 | } |
| 2141 | }; |