| ... | ... | @@ -102,7 +102,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i |
| 102 | 102 | } |
| 103 | 103 | try renderToken(tree, stream, field.name_token, indent, Space.None); // name |
| 104 | 104 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // : |
| 105 | | try renderTrailingComma(allocator, stream, tree, indent, field.type_expr, Space.Newline); // type, |
| 105 | try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.Comma); // type, |
| 106 | 106 | }, |
| 107 | 107 | |
| 108 | 108 | ast.Node.Id.UnionTag => { |
| ... | ... | @@ -111,7 +111,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i |
| 111 | 111 | try renderDocComments(tree, stream, tag, indent); |
| 112 | 112 | |
| 113 | 113 | if (tag.type_expr == null and tag.value_expr == null) { |
| 114 | | return renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name, |
| 114 | return renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name, |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | if (tag.type_expr == null) { |
| ... | ... | @@ -124,7 +124,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i |
| 124 | 124 | try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // : |
| 125 | 125 | |
| 126 | 126 | if (tag.value_expr == null) { |
| 127 | | return renderTrailingComma(allocator, stream, tree, indent, type_expr, Space.Newline); // type, |
| 127 | return renderExpression(allocator, stream, tree, indent, type_expr, Space.Comma); // type, |
| 128 | 128 | } else { |
| 129 | 129 | try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type |
| 130 | 130 | } |
| ... | ... | @@ -132,7 +132,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i |
| 132 | 132 | |
| 133 | 133 | const value_expr = ??tag.value_expr; |
| 134 | 134 | try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // = |
| 135 | | try renderTrailingComma(allocator, stream, tree, indent, value_expr, Space.Newline); // value, |
| 135 | try renderExpression(allocator, stream, tree, indent, value_expr, Space.Comma); // value, |
| 136 | 136 | }, |
| 137 | 137 | |
| 138 | 138 | ast.Node.Id.EnumTag => { |
| ... | ... | @@ -144,9 +144,9 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i |
| 144 | 144 | try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name |
| 145 | 145 | |
| 146 | 146 | try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // = |
| 147 | | try renderTrailingComma(allocator, stream, tree, indent, value, Space.Newline); |
| 147 | try renderExpression(allocator, stream, tree, indent, value, Space.Comma); |
| 148 | 148 | } else { |
| 149 | | try renderTokenAndTrailingComma(tree, stream, tag.name_token, indent, Space.Newline); // name |
| 149 | try renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name |
| 150 | 150 | } |
| 151 | 151 | }, |
| 152 | 152 | |
| ... | ... | @@ -413,7 +413,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 413 | 413 | try renderToken(tree, stream, comma, new_indent, Space.Newline); // , |
| 414 | 414 | try renderExtraNewline(tree, stream, next_node.*); |
| 415 | 415 | } else { |
| 416 | | try renderTrailingComma(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Newline); |
| 416 | try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Comma); |
| 417 | 417 | try stream.writeByteNTimes(' ', indent); |
| 418 | 418 | try renderToken(tree, stream, suffix_op.rtoken, indent, space); |
| 419 | 419 | return; |
| ... | ... | @@ -540,7 +540,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 540 | 540 | |
| 541 | 541 | try renderExtraNewline(tree, stream, next_field_init.*); |
| 542 | 542 | } else { |
| 543 | | try renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline); |
| 543 | try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.Comma); |
| 544 | 544 | } |
| 545 | 545 | } |
| 546 | 546 | |
| ... | ... | @@ -625,7 +625,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 625 | 625 | try renderExtraNewline(tree, stream, next_expr.*); |
| 626 | 626 | try stream.writeByteNTimes(' ', new_indent); |
| 627 | 627 | } else { |
| 628 | | try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); // , |
| 628 | try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.Comma); // , |
| 629 | 629 | } |
| 630 | 630 | } |
| 631 | 631 | try stream.writeByteNTimes(' ', indent); |
| ... | ... | @@ -892,7 +892,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 892 | 892 | |
| 893 | 893 | try renderExtraNewline(tree, stream, next_node.*); |
| 894 | 894 | } else { |
| 895 | | try renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline); |
| 895 | try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); |
| 896 | 896 | } |
| 897 | 897 | } |
| 898 | 898 | |
| ... | ... | @@ -976,29 +976,55 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 976 | 976 | try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space); |
| 977 | 977 | } |
| 978 | 978 | |
| 979 | | if (fn_proto.name_token) |name_token| blk: { |
| 979 | const lparen = if (fn_proto.name_token) |name_token| blk: { |
| 980 | 980 | try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn |
| 981 | 981 | try renderToken(tree, stream, name_token, indent, Space.None); // name |
| 982 | | try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // ( |
| 982 | break :blk tree.nextToken(name_token); |
| 983 | 983 | } else blk: { |
| 984 | 984 | try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn |
| 985 | | try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // ( |
| 986 | | } |
| 987 | | |
| 988 | | var it = fn_proto.params.iterator(0); |
| 989 | | while (it.next()) |param_decl_node| { |
| 990 | | try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*); |
| 991 | | |
| 992 | | if (it.peek() != null) { |
| 993 | | const comma = tree.nextToken(param_decl_node.*.lastToken()); |
| 994 | | try renderToken(tree, stream, comma, indent, Space.Space); // , |
| 995 | | } |
| 996 | | } |
| 985 | break :blk tree.nextToken(fn_proto.fn_token); |
| 986 | }; |
| 997 | 987 | |
| 998 | 988 | const rparen = tree.prevToken(switch (fn_proto.return_type) { |
| 999 | 989 | ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(), |
| 1000 | 990 | ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()), |
| 1001 | 991 | }); |
| 992 | |
| 993 | const src_params_trailing_comma = blk: { |
| 994 | const maybe_comma = tree.prevToken(rparen); |
| 995 | break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; |
| 996 | }; |
| 997 | const src_params_same_line = blk: { |
| 998 | const loc = tree.tokenLocation(tree.tokens.at(lparen).end, rparen); |
| 999 | break :blk loc.line == 0; |
| 1000 | }; |
| 1001 | |
| 1002 | if (!src_params_trailing_comma and src_params_same_line) { |
| 1003 | try renderToken(tree, stream, lparen, indent, Space.None); // ( |
| 1004 | |
| 1005 | // render all on one line, no trailing comma |
| 1006 | var it = fn_proto.params.iterator(0); |
| 1007 | while (it.next()) |param_decl_node| { |
| 1008 | try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.None); |
| 1009 | |
| 1010 | if (it.peek() != null) { |
| 1011 | const comma = tree.nextToken(param_decl_node.*.lastToken()); |
| 1012 | try renderToken(tree, stream, comma, indent, Space.Space); // , |
| 1013 | } |
| 1014 | } |
| 1015 | } else { |
| 1016 | // one param per line |
| 1017 | const new_indent = indent + indent_delta; |
| 1018 | try renderToken(tree, stream, lparen, new_indent, Space.Newline); // ( |
| 1019 | |
| 1020 | var it = fn_proto.params.iterator(0); |
| 1021 | while (it.next()) |param_decl_node| { |
| 1022 | try stream.writeByteNTimes(' ', new_indent); |
| 1023 | try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.Comma); |
| 1024 | } |
| 1025 | try stream.writeByteNTimes(' ', indent); |
| 1026 | } |
| 1027 | |
| 1002 | 1028 | try renderToken(tree, stream, rparen, indent, Space.Space); // ) |
| 1003 | 1029 | |
| 1004 | 1030 | if (fn_proto.align_expr) |align_expr| { |
| ... | ... | @@ -1064,7 +1090,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1064 | 1090 | var it = switch_node.cases.iterator(0); |
| 1065 | 1091 | while (it.next()) |node| { |
| 1066 | 1092 | try stream.writeByteNTimes(' ', new_indent); |
| 1067 | | try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Newline); |
| 1093 | try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma); |
| 1068 | 1094 | |
| 1069 | 1095 | if (it.peek()) |next_node| { |
| 1070 | 1096 | try renderExtraNewline(tree, stream, next_node.*); |
| ... | ... | @@ -1110,7 +1136,8 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1110 | 1136 | try renderExtraNewline(tree, stream, next_node.*); |
| 1111 | 1137 | try stream.writeByteNTimes(' ', indent); |
| 1112 | 1138 | } else { |
| 1113 | | try renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space); |
| 1139 | try renderExpression(allocator, stream, tree, indent, node.*, Space.Comma); |
| 1140 | try stream.writeByteNTimes(' ', indent); |
| 1114 | 1141 | break; |
| 1115 | 1142 | } |
| 1116 | 1143 | } |
| ... | ... | @@ -1122,7 +1149,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1122 | 1149 | try renderExpression(allocator, stream, tree, indent, payload, Space.Space); |
| 1123 | 1150 | } |
| 1124 | 1151 | |
| 1125 | | try renderTrailingComma(allocator, stream, tree, indent, switch_case.expr, space); |
| 1152 | try renderExpression(allocator, stream, tree, indent, switch_case.expr, space); |
| 1126 | 1153 | }, |
| 1127 | 1154 | ast.Node.Id.SwitchElse => { |
| 1128 | 1155 | const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); |
| ... | ... | @@ -1543,7 +1570,7 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent |
| 1543 | 1570 | try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline); |
| 1544 | 1571 | } |
| 1545 | 1572 | |
| 1546 | | fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { |
| 1573 | fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void { |
| 1547 | 1574 | const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); |
| 1548 | 1575 | |
| 1549 | 1576 | if (param_decl.comptime_token) |comptime_token| { |
| ... | ... | @@ -1557,9 +1584,9 @@ fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde |
| 1557 | 1584 | try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // : |
| 1558 | 1585 | } |
| 1559 | 1586 | if (param_decl.var_args_token) |var_args_token| { |
| 1560 | | try renderToken(tree, stream, var_args_token, indent, Space.None); |
| 1587 | try renderToken(tree, stream, var_args_token, indent, space); |
| 1561 | 1588 | } else { |
| 1562 | | try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None); |
| 1589 | try renderExpression(allocator, stream, tree, indent, param_decl.type_node, space); |
| 1563 | 1590 | } |
| 1564 | 1591 | } |
| 1565 | 1592 | |
| ... | ... | @@ -1586,6 +1613,7 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde |
| 1586 | 1613 | const Space = enum { |
| 1587 | 1614 | None, |
| 1588 | 1615 | Newline, |
| 1616 | Comma, |
| 1589 | 1617 | Space, |
| 1590 | 1618 | NoNewline, |
| 1591 | 1619 | NoIndent, |
| ... | ... | @@ -1596,9 +1624,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent |
| 1596 | 1624 | var token = tree.tokens.at(token_index); |
| 1597 | 1625 | try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " ")); |
| 1598 | 1626 | |
| 1599 | | if (space == Space.NoComment) return; |
| 1600 | | |
| 1601 | 1627 | var next_token = tree.tokens.at(token_index + 1); |
| 1628 | |
| 1629 | switch (space) { |
| 1630 | Space.NoComment => return, |
| 1631 | Space.Comma => switch (next_token.id) { |
| 1632 | Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, Space.Newline), |
| 1633 | Token.Id.LineComment => { |
| 1634 | try stream.write(", "); |
| 1635 | return renderToken(tree, stream, token_index + 1, indent, Space.Newline); |
| 1636 | }, |
| 1637 | else => { |
| 1638 | if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) { |
| 1639 | return stream.write(","); |
| 1640 | } else { |
| 1641 | return stream.write(",\n"); |
| 1642 | } |
| 1643 | }, |
| 1644 | }, |
| 1645 | else => {}, |
| 1646 | } |
| 1647 | |
| 1602 | 1648 | if (next_token.id != Token.Id.LineComment) { |
| 1603 | 1649 | switch (space) { |
| 1604 | 1650 | Space.None, Space.NoNewline, Space.NoIndent => return, |
| ... | ... | @@ -1610,7 +1656,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent |
| 1610 | 1656 | } |
| 1611 | 1657 | }, |
| 1612 | 1658 | Space.Space => return stream.writeByte(' '), |
| 1613 | | Space.NoComment => unreachable, |
| 1659 | Space.NoComment, Space.Comma => unreachable, |
| 1614 | 1660 | } |
| 1615 | 1661 | } |
| 1616 | 1662 | |
| ... | ... | @@ -1648,7 +1694,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent |
| 1648 | 1694 | } |
| 1649 | 1695 | }, |
| 1650 | 1696 | Space.NoNewline => {}, |
| 1651 | | Space.NoComment => unreachable, |
| 1697 | Space.NoComment, Space.Comma => unreachable, |
| 1652 | 1698 | } |
| 1653 | 1699 | return; |
| 1654 | 1700 | } |
| ... | ... | @@ -1685,7 +1731,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent |
| 1685 | 1731 | try stream.writeByteNTimes(' ', next_line_indent); |
| 1686 | 1732 | }, |
| 1687 | 1733 | Space.NoNewline => {}, |
| 1688 | | Space.NoComment => unreachable, |
| 1734 | Space.NoComment, Space.Comma => unreachable, |
| 1689 | 1735 | } |
| 1690 | 1736 | return; |
| 1691 | 1737 | } |
| ... | ... | @@ -1701,45 +1747,3 @@ fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@t |
| 1701 | 1747 | try stream.writeByteNTimes(' ', indent); |
| 1702 | 1748 | } |
| 1703 | 1749 | } |
| 1704 | | |
| 1705 | | fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, |
| 1706 | | space: Space) (@typeOf(stream).Child.Error || Error)!void |
| 1707 | | { |
| 1708 | | const end_token = base.lastToken() + 1; |
| 1709 | | switch (tree.tokens.at(end_token).id) { |
| 1710 | | Token.Id.Comma => { |
| 1711 | | try renderExpression(allocator, stream, tree, indent, base, Space.None); |
| 1712 | | try renderToken(tree, stream, end_token, indent, space); // , |
| 1713 | | }, |
| 1714 | | Token.Id.LineComment => { |
| 1715 | | try renderExpression(allocator, stream, tree, indent, base, Space.NoComment); |
| 1716 | | try stream.write(", "); |
| 1717 | | try renderToken(tree, stream, end_token, indent, space); |
| 1718 | | }, |
| 1719 | | else => { |
| 1720 | | try renderExpression(allocator, stream, tree, indent, base, Space.None); |
| 1721 | | try stream.write(",\n"); |
| 1722 | | assert(space == Space.Newline); |
| 1723 | | }, |
| 1724 | | } |
| 1725 | | } |
| 1726 | | |
| 1727 | | fn renderTokenAndTrailingComma(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void { |
| 1728 | | const end_token = token_index + 1; |
| 1729 | | switch (tree.tokens.at(end_token).id) { |
| 1730 | | Token.Id.Comma => { |
| 1731 | | try renderToken(tree, stream, token_index, indent, Space.None); |
| 1732 | | try renderToken(tree, stream, end_token, indent, space); // , |
| 1733 | | }, |
| 1734 | | Token.Id.LineComment => { |
| 1735 | | try renderToken(tree, stream, token_index, indent, Space.NoComment); |
| 1736 | | try stream.write(", "); |
| 1737 | | try renderToken(tree, stream, end_token, indent, space); |
| 1738 | | }, |
| 1739 | | else => { |
| 1740 | | try renderToken(tree, stream, token_index, indent, Space.None); |
| 1741 | | try stream.write(",\n"); |
| 1742 | | assert(space == Space.Newline); |
| 1743 | | }, |
| 1744 | | } |
| 1745 | | } |