| ... | @@ -714,37 +714,24 @@ fn renderExpression( | ... | @@ -714,37 +714,24 @@ fn renderExpression( |
| 714 | .node => |node| tree.nextToken(node.lastToken()), | 714 | .node => |node| tree.nextToken(node.lastToken()), |
| 715 | }; | 715 | }; |
| 716 | | 716 | |
| 717 | if (exprs.len == 0) { | 717 | switch (lhs) { |
| 718 | switch (lhs) { | 718 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), |
| 719 | .dot => |dot| try renderToken(tree, ais, dot, Space.None), | 719 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), |
| 720 | .node => |node| try renderExpression(allocator, ais, tree, node, Space.None), | 720 | } |
| 721 | } | | |
| 722 | | | |
| 723 | { | | |
| 724 | ais.pushIndent(); | | |
| 725 | defer ais.popIndent(); | | |
| 726 | try renderToken(tree, ais, lbrace, Space.None); | | |
| 727 | } | | |
| 728 | | 721 | |
| | 722 | if (exprs.len == 0) { |
| | 723 | try renderToken(tree, ais, lbrace, Space.None); |
| 729 | return renderToken(tree, ais, rtoken, space); | 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 | const expr = exprs[0]; | 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 | try renderToken(tree, ais, lbrace, Space.None); | 730 | try renderToken(tree, ais, lbrace, Space.None); |
| 739 | try renderExpression(allocator, ais, tree, expr, Space.None); | 731 | try renderExpression(allocator, ais, tree, expr, Space.None); |
| 740 | return renderToken(tree, ais, rtoken, space); | 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 | // scan to find row size | 735 | // scan to find row size |
| 749 | if (rowSize(tree, exprs, rtoken, false) != null) { | 736 | if (rowSize(tree, exprs, rtoken, false) != null) { |
| 750 | { | 737 | { |
| ... | @@ -763,11 +750,7 @@ fn renderExpression( | ... | @@ -763,11 +750,7 @@ fn renderExpression( |
| 763 | var expr_widths = widths[0 .. widths.len - row_size]; | 750 | var expr_widths = widths[0 .. widths.len - row_size]; |
| 764 | var column_widths = widths[widths.len - row_size ..]; | 751 | var column_widths = widths[widths.len - row_size ..]; |
| 765 | | 752 | |
| 766 | // Null stream for counting the printed length of each expression | 753 | // Find next row with trailing comment (if any) to end the current section |
| 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 | | |
| 771 | var section_end = sec_end: { | 754 | var section_end = sec_end: { |
| 772 | var this_line_first_expr: usize = 0; | 755 | var this_line_first_expr: usize = 0; |
| 773 | var this_line_size = rowSize(tree, row_exprs, rtoken, true); | 756 | var this_line_size = rowSize(tree, row_exprs, rtoken, true); |
| ... | @@ -779,12 +762,15 @@ fn renderExpression( | ... | @@ -779,12 +762,15 @@ fn renderExpression( |
| 779 | this_line_first_expr = i; | 762 | this_line_first_expr = i; |
| 780 | this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rtoken, true); | 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) { | 765 | |
| 783 | if (tree.token_ids[expr.lastToken() + 1] == .Comma and | 766 | const maybe_comma = expr.lastToken() + 1; |
| 784 | tree.token_ids[expr.lastToken() + 2] == .LineComment and | 767 | const maybe_comment = expr.lastToken() + 2; |
| 785 | tree.tokensOnSameLine(expr.lastToken(), 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 | const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2; | 774 | const comment_is_empty = mem.trimRight(u8, tree.tokenSliceLoc(comment_token_loc), " ").len == 2; |
| 789 | if (!comment_is_empty) { | 775 | if (!comment_is_empty) { |
| 790 | // Found row ending in comment | 776 | // Found row ending in comment |
| ... | @@ -799,18 +785,56 @@ fn renderExpression( | ... | @@ -799,18 +785,56 @@ fn renderExpression( |
| 799 | | 785 | |
| 800 | const section_exprs = row_exprs[0..section_end]; | 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 | // Calculate size of columns in current section | 793 | // Calculate size of columns in current section |
| | 794 | var c: usize = 0; |
| | 795 | var single_line = true; |
| 803 | for (section_exprs) |expr, i| { | 796 | for (section_exprs) |expr, i| { |
| 804 | counting_stream.bytes_written = 0; | 797 | if (i + 1 < section_exprs.len) { |
| 805 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); | 798 | counting_stream.bytes_written = 0; |
| 806 | const width = @intCast(usize, counting_stream.bytes_written); | 799 | line_find_stream.byte_found = false; |
| 807 | const col = i % row_size; | 800 | try renderExpression(allocator, &auto_indenting_stream, tree, expr, Space.None); |
| 808 | column_widths[col] = std.math.max(column_widths[col], width); | 801 | const width = @intCast(usize, counting_stream.bytes_written); |
| 809 | expr_widths[i] = width; | 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 | // Render exprs in current section | 835 | // Render exprs in current section |
| 813 | var col: usize = 1; | 836 | c = 0; |
| | 837 | var last_col_index: usize = row_size - 1; |
| 814 | for (section_exprs) |expr, i| { | 838 | for (section_exprs) |expr, i| { |
| 815 | if (i + 1 < section_exprs.len) { | 839 | if (i + 1 < section_exprs.len) { |
| 816 | const next_expr = section_exprs[i + 1]; | 840 | const next_expr = section_exprs[i + 1]; |
| ... | @@ -818,23 +842,28 @@ fn renderExpression( | ... | @@ -818,23 +842,28 @@ fn renderExpression( |
| 818 | | 842 | |
| 819 | const comma = tree.nextToken(expr.*.lastToken()); | 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 | try renderToken(tree, ais, comma, Space.Space); // , | 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 | continue; | 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 | try renderExtraNewline(tree, ais, next_expr); | 867 | try renderExtraNewline(tree, ais, next_expr); |
| 839 | } else { | 868 | } else { |
| 840 | const maybe_comma = tree.nextToken(expr.*.lastToken()); | 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,13 +2623,13 @@ fn rowSize(tree: *ast.Tree, exprs: []*ast.Node, rtoken: ast.TokenIndex, force: b |
| 2594 | for (exprs) |expr, i| { | 2623 | for (exprs) |expr, i| { |
| 2595 | if (i + 1 < exprs.len) { | 2624 | if (i + 1 < exprs.len) { |
| 2596 | const expr_last_token = expr.lastToken() + 1; | 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 | if (loc.line != 0) return count; | 2627 | if (loc.line != 0) return count; |
| 2599 | count += 1; | 2628 | count += 1; |
| 2600 | } else { | 2629 | } else { |
| 2601 | if (force) return count; | 2630 | if (force) return count; |
| 2602 | const expr_last_token = expr.lastToken(); | 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 | if (loc.line == 0) { | 2633 | if (loc.line == 0) { |
| 2605 | // all on one line | 2634 | // all on one line |
| 2606 | const src_has_trailing_comma = trailblk: { | 2635 | const src_has_trailing_comma = trailblk: { |