| ... | ... | @@ -714,37 +714,24 @@ fn renderExpression( |
| 714 | 714 | .node => |node| tree.nextToken(node.lastToken()), |
| 715 | 715 | }; |
| 716 | 716 | |
| 717 | | if (exprs.len == 0) { |
| 718 | | switch (lhs) { |
| 719 | | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 720 | | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 721 | | } |
| 722 | | |
| 723 | | { |
| 724 | | ais.pushIndent(); |
| 725 | | defer ais.popIndent(); |
| 726 | | try renderToken(tree, ais, lbrace, Space.None); |
| 727 | | } |
| 717 | switch (lhs) { |
| 718 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 719 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 720 | } |
| 728 | 721 | |
| 722 | if (exprs.len == 0) { |
| 723 | try renderToken(tree, ais, lbrace, Space.None); |
| 729 | 724 | return renderToken(tree, ais, rtoken, space); |
| 730 | 725 | } |
| 731 | | if (exprs.len == 1 and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) { |
| 726 | |
| 727 | if (exprs.len == 1 and exprs[0].tag != .MultilineStringLiteral and tree.token_ids[exprs[0].*.lastToken() + 1] == .RBrace) { |
| 732 | 728 | const expr = exprs[0]; |
| 733 | 729 | |
| 734 | | switch (lhs) { |
| 735 | | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 736 | | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 737 | | } |
| 738 | 730 | try renderToken(tree, ais, lbrace, Space.None); |
| 739 | 731 | try renderExpression(allocator, ais, tree, expr, Space.None); |
| 740 | 732 | return renderToken(tree, ais, rtoken, space); |
| 741 | 733 | } |
| 742 | 734 | |
| 743 | | switch (lhs) { |
| 744 | | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 745 | | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 746 | | } |
| 747 | | |
| 748 | 735 | // scan to find row size |
| 749 | 736 | if (rowSize(tree, exprs, rtoken, false) != null) { |
| 750 | 737 | { |
| ... | ... | @@ -763,11 +750,7 @@ fn renderExpression( |
| 763 | 750 | var expr_widths = widths[0 .. widths.len - row_size]; |
| 764 | 751 | var column_widths = widths[widths.len - row_size ..]; |
| 765 | 752 | |
| 766 | | // Null stream for counting the printed length of each expression |
| 767 | | var counting_stream = std.io.countingOutStream(std.io.null_out_stream); |
| 768 | | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer()); |
| 769 | | |
| 770 | | // Find next row with trailing comment (if any) to end the current section then |
| 753 | // Find next row with trailing comment (if any) to end the current section |
| 771 | 754 | var section_end = sec_end: { |
| 772 | 755 | var this_line_first_expr: usize = 0; |
| 773 | 756 | var this_line_size = rowSize(tree, row_exprs, rtoken, true); |
| ... | ... | @@ -779,12 +762,15 @@ fn renderExpression( |
| 779 | 762 | this_line_first_expr = i; |
| 780 | 763 | this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken, true); |
| 781 | 764 | } |
| 782 | | if (expr.lastToken() + 2 < tree.token_ids.len) { |
| 783 | | if (tree.token_ids[expr.lastToken() + 1] == .Comma and |
| 784 | | tree.token_ids[expr.lastToken() + 2] == .LineComment and |
| 785 | | tree.tokensOnSameLine(expr.lastToken(), expr.lastToken() + 2)) |
| 765 | |
| 766 | const maybe_comma = expr.lastToken() + 1; |
| 767 | const maybe_comment = expr.lastToken() + 2; |
| 768 | if (maybe_comment < tree.token_ids.len) { |
| 769 | if (tree.token_ids[maybe_comma] == .Comma and |
| 770 | tree.token_ids[maybe_comment] == .LineComment and |
| 771 | tree.tokensOnSameLine(expr.lastToken(), maybe_comment)) |
| 786 | 772 | { |
| 787 | | var comment_token_loc = tree.token_locs[expr.lastToken() + 2]; |
| 773 | var comment_token_loc = tree.token_locs[maybe_comment]; |
| 788 | 774 | const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2; |
| 789 | 775 | if (!comment_is_empty) { |
| 790 | 776 | // Found row ending in comment |
| ... | ... | @@ -799,18 +785,56 @@ fn renderExpression( |
| 799 | 785 | |
| 800 | 786 | const section_exprs = row_exprs[0..section_end]; |
| 801 | 787 | |
| 788 | // Null stream for counting the printed length of each expression |
| 789 | var line_find_stream = std.io.findByteOutStream('\n', std.io.null_out_stream); |
| 790 | var counting_stream = std.io.countingOutStream(line_find_stream.writer()); |
| 791 | var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, counting_stream.writer()); |
| 792 | |
| 802 | 793 | // Calculate size of columns in current section |
| 794 | var c: usize = 0; |
| 795 | var single_line = true; |
| 803 | 796 | for (section_exprs) |expr, i| { |
| 804 | | counting_stream.bytes_written = 0; |
| 805 | | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); |
| 806 | | const width = @intCast(usize, counting_stream.bytes_written); |
| 807 | | const col = i % row_size; |
| 808 | | column_widths[col] = std.math.max(column_widths[col], width); |
| 809 | | expr_widths[i] = width; |
| 797 | if (i + 1 < section_exprs.len) { |
| 798 | counting_stream.bytes_written = 0; |
| 799 | line_find_stream.byte_found = false; |
| 800 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); |
| 801 | const width = @intCast(usize, counting_stream.bytes_written); |
| 802 | expr_widths[i] = width; |
| 803 | |
| 804 | if (!line_find_stream.byte_found) { |
| 805 | const col = c % row_size; |
| 806 | column_widths[col] = std.math.max(column_widths[col], width); |
| 807 | |
| 808 | const expr_last_token = expr.*.lastToken() + 1; |
| 809 | const next_expr = section_exprs[i + 1]; |
| 810 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, next_expr.*.firstToken()); |
| 811 | if (loc.line == 0) { |
| 812 | c += 1; |
| 813 | } else { |
| 814 | single_line = false; |
| 815 | c = 0; |
| 816 | } |
| 817 | } else { |
| 818 | single_line = false; |
| 819 | c = 0; |
| 820 | } |
| 821 | } else { |
| 822 | counting_stream.bytes_written = 0; |
| 823 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); |
| 824 | const width = @intCast(usize, counting_stream.bytes_written); |
| 825 | expr_widths[i] = width; |
| 826 | |
| 827 | if (!line_find_stream.byte_found) { |
| 828 | const col = c % row_size; |
| 829 | column_widths[col] = std.math.max(column_widths[col], width); |
| 830 | } |
| 831 | break; |
| 832 | } |
| 810 | 833 | } |
| 811 | 834 | |
| 812 | 835 | // Render exprs in current section |
| 813 | | var col: usize = 1; |
| 836 | c = 0; |
| 837 | var last_col_index: usize = row_size - 1; |
| 814 | 838 | for (section_exprs) |expr, i| { |
| 815 | 839 | if (i + 1 < section_exprs.len) { |
| 816 | 840 | const next_expr = section_exprs[i + 1]; |
| ... | ... | @@ -818,23 +842,28 @@ fn renderExpression( |
| 818 | 842 | |
| 819 | 843 | const comma = tree.nextToken(expr.*.lastToken()); |
| 820 | 844 | |
| 821 | | if (col != row_size) { |
| 845 | if (c != last_col_index) { |
| 846 | line_find_stream.byte_found = false; |
| 847 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); |
| 848 | try renderExpression(allocator, &auto_indenting_stream, tree, next_expr, Space.None); |
| 849 | if (!line_find_stream.byte_found) { |
| 850 | // Neither the current or next expression is multiline |
| 851 | try renderToken(tree, ais, comma, Space.Space); // , |
| 852 | assert(column_widths[c % row_size] >= expr_widths[i]); |
| 853 | const padding = column_widths[c % row_size] - expr_widths[i]; |
| 854 | try ais.writer().writeByteNTimes(' ', padding); |
| 855 | |
| 856 | c += 1; |
| 857 | continue; |
| 858 | } |
| 859 | } |
| 860 | if (single_line) { |
| 822 | 861 | try renderToken(tree, ais, comma, Space.Space); // , |
| 823 | | |
| 824 | | const padding = column_widths[i % row_size] - expr_widths[i]; |
| 825 | | try ais.writer().writeByteNTimes(' ', padding); |
| 826 | | |
| 827 | | col += 1; |
| 828 | 862 | continue; |
| 829 | 863 | } |
| 830 | | col = 1; |
| 831 | | |
| 832 | | if (tree.token_ids[tree.nextToken(comma)] != .MultilineStringLiteralLine) { |
| 833 | | try renderToken(tree, ais, comma, Space.Newline); // , |
| 834 | | } else { |
| 835 | | try renderToken(tree, ais, comma, Space.None); // , |
| 836 | | } |
| 837 | 864 | |
| 865 | c = 0; |
| 866 | try renderToken(tree, ais, comma, Space.Newline); // , |
| 838 | 867 | try renderExtraNewline(tree, ais, next_expr); |
| 839 | 868 | } else { |
| 840 | 869 | const maybe_comma = tree.nextToken(expr.*.lastToken()); |
| ... | ... | @@ -2594,13 +2623,13 @@ fn rowSize(tree: *ast.Tree, exprs: []*ast.Node, rtoken: ast.TokenIndex, force: b |
| 2594 | 2623 | for (exprs) |expr, i| { |
| 2595 | 2624 | if (i + 1 < exprs.len) { |
| 2596 | 2625 | const expr_last_token = expr.lastToken() + 1; |
| 2597 | | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].end, exprs[i + 1].firstToken()); |
| 2626 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, exprs[i + 1].firstToken()); |
| 2598 | 2627 | if (loc.line != 0) return count; |
| 2599 | 2628 | count += 1; |
| 2600 | 2629 | } else { |
| 2601 | 2630 | if (force) return count; |
| 2602 | 2631 | const expr_last_token = expr.lastToken(); |
| 2603 | | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].end, rtoken); |
| 2632 | const loc = tree.tokenLocation(tree.token_locs[expr_last_token].start, rtoken); |
| 2604 | 2633 | if (loc.line == 0) { |
| 2605 | 2634 | // all on one line |
| 2606 | 2635 | const src_has_trailing_comma = trailblk: { |