authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-29 03:15:12-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-29 03:15:12-04:00
logeda6898c5b253367174172db909ee23013f32733
tree855b7f50c1207fdf5087e773dac9d76ed02c883c
parent530d17542207151f768a14a0cc8311181599b9b9

zig fmt: handle if and while indentation better


3 files changed, 658 insertions(+), 535 deletions(-)

std/zig/ast.zig+16-8
...@@ -68,6 +68,14 @@ pub const Tree = struct {...@@ -68,6 +68,14 @@ pub const Tree = struct {
68 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));68 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));
69 }69 }
7070
71 pub fn tokensOnSameLine(self: &Tree, token1_index: TokenIndex, token2_index: TokenIndex) bool {
72 return self.tokensOnSameLinePtr(self.tokens.at(token1_index), self.tokens.at(token2_index));
73 }
74
75 pub fn tokensOnSameLinePtr(self: &Tree, token1: &const Token, token2: &const Token) bool {
76 return mem.indexOfScalar(u8, self.source[token1.end..token2.start], '\n') == null;
77 }
78
71 pub fn dump(self: &Tree) void {79 pub fn dump(self: &Tree) void {
72 self.root_node.base.dump(0);80 self.root_node.base.dump(0);
73 }81 }
...@@ -1529,14 +1537,14 @@ pub const Node = struct {...@@ -1529,14 +1537,14 @@ pub const Node = struct {
15291537
1530 switch (self.op) {1538 switch (self.op) {
1531 Op.SliceType => |addr_of_info| {1539 Op.SliceType => |addr_of_info| {
1532 if (addr_of_info.align_expr) |align_expr| {1540 if (addr_of_info.align_info) |align_info| {
1533 if (i < 1) return align_expr;1541 if (i < 1) return align_info.node;
1534 i -= 1;1542 i -= 1;
1535 }1543 }
1536 },1544 },
1537 Op.AddrOf => |addr_of_info| {1545 Op.AddrOf => |addr_of_info| {
1538 if (addr_of_info.align_expr) |align_expr| {1546 if (addr_of_info.align_info) |align_info| {
1539 if (i < 1) return align_expr;1547 if (i < 1) return align_info.node;
1540 i -= 1;1548 i -= 1;
1541 }1549 }
1542 },1550 },
...@@ -1553,7 +1561,9 @@ pub const Node = struct {...@@ -1553,7 +1561,9 @@ pub const Node = struct {
1553 Op.NegationWrap,1561 Op.NegationWrap,
1554 Op.Try,1562 Op.Try,
1555 Op.Resume,1563 Op.Resume,
1556 Op.UnwrapMaybe => {},1564 Op.UnwrapMaybe,
1565 Op.PointerType,
1566 => {},
1557 }1567 }
15581568
1559 if (i < 1) return self.rhs;1569 if (i < 1) return self.rhs;
...@@ -1656,6 +1666,7 @@ pub const Node = struct {...@@ -1656,6 +1666,7 @@ pub const Node = struct {
1656 if (i < fields.len) return fields.at(i).*;1666 if (i < fields.len) return fields.at(i).*;
1657 i -= fields.len;1667 i -= fields.len;
1658 },1668 },
1669 Op.Deref => {},
1659 }1670 }
16601671
1661 return null;1672 return null;
...@@ -2082,9 +2093,6 @@ pub const Node = struct {...@@ -2082,9 +2093,6 @@ pub const Node = struct {
2082 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;2093 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;
2083 i -= self.inputs.len;2094 i -= self.inputs.len;
20842095
2085 if (i < self.clobbers.len) return self.clobbers.at(index).*;
2086 i -= self.clobbers.len;
2087
2088 return null;2096 return null;
2089 }2097 }
20902098
std/zig/parser_test.zig+92
...@@ -1,3 +1,95 @@...@@ -1,3 +1,95 @@
1test "zig fmt: if condition wraps" {
2 try testTransform(
3 \\comptime {
4 \\ if (cond and
5 \\ cond) {
6 \\ return x;
7 \\ }
8 \\ while (cond and
9 \\ cond) {
10 \\ return x;
11 \\ }
12 \\ if (a == b and
13 \\ c) {
14 \\ a = b;
15 \\ }
16 \\ while (a == b and
17 \\ c) {
18 \\ a = b;
19 \\ }
20 \\ if ((cond and
21 \\ cond)) {
22 \\ return x;
23 \\ }
24 \\ while ((cond and
25 \\ cond)) {
26 \\ return x;
27 \\ }
28 \\ var a = if (a) |*f| x: {
29 \\ break :x &a.b;
30 \\ } else |err| err;
31 \\}
32 ,
33 \\comptime {
34 \\ if (cond and
35 \\ cond)
36 \\ {
37 \\ return x;
38 \\ }
39 \\ while (cond and
40 \\ cond)
41 \\ {
42 \\ return x;
43 \\ }
44 \\ if (a == b and
45 \\ c)
46 \\ {
47 \\ a = b;
48 \\ }
49 \\ while (a == b and
50 \\ c)
51 \\ {
52 \\ a = b;
53 \\ }
54 \\ if ((cond and
55 \\ cond))
56 \\ {
57 \\ return x;
58 \\ }
59 \\ while ((cond and
60 \\ cond))
61 \\ {
62 \\ return x;
63 \\ }
64 \\ var a = if (a) |*f| x: {
65 \\ break :x &a.b;
66 \\ } else |err| err;
67 \\}
68 \\
69 );
70}
71
72test "zig fmt: if condition has line break but must not wrap" {
73 try testCanonical(
74 \\comptime {
75 \\ if (self.user_input_options.put(name, UserInputOption{
76 \\ .name = name,
77 \\ .used = false,
78 \\ }) catch unreachable) |*prev_value| {
79 \\ foo();
80 \\ bar();
81 \\ }
82 \\ if (put(
83 \\ a,
84 \\ b,
85 \\ )) {
86 \\ foo();
87 \\ }
88 \\}
89 \\
90 );
91}
92
1test "zig fmt: same-line doc comment on variable declaration" {93test "zig fmt: same-line doc comment on variable declaration" {
2 try testTransform(94 try testTransform(
3 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space95 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
std/zig/render.zig+550-527
...@@ -28,17 +28,17 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(...@@ -28,17 +28,17 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
28 }28 }
29 }29 }
3030
3131 var start_col: usize = 0;
32 var it = tree.root_node.decls.iterator(0);32 var it = tree.root_node.decls.iterator(0);
33 while (it.next()) |decl| {33 while (it.next()) |decl| {
34 try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);34 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
35 if (it.peek()) |next_decl| {35 if (it.peek()) |next_decl| {
36 try renderExtraNewline(tree, stream, next_decl.*);36 try renderExtraNewline(tree, stream, &start_col, next_decl.*);
37 }37 }
38 }38 }
39}39}
4040
41fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {41fn renderExtraNewline(tree: &ast.Tree, stream: var, start_col: &usize, node: &ast.Node) !void {
42 const first_token = node.firstToken();42 const first_token = node.firstToken();
43 var prev_token = first_token;43 var prev_token = first_token;
44 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {44 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {
...@@ -48,22 +48,23 @@ fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {...@@ -48,22 +48,23 @@ fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {
48 const loc = tree.tokenLocation(prev_token_end, first_token);48 const loc = tree.tokenLocation(prev_token_end, first_token);
49 if (loc.line >= 2) {49 if (loc.line >= 2) {
50 try stream.writeByte('\n');50 try stream.writeByte('\n');
51 start_col.* = 0;
51 }52 }
52}53}
5354
54fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {55fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
55 switch (decl.id) {56 switch (decl.id) {
56 ast.Node.Id.FnProto => {57 ast.Node.Id.FnProto => {
57 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);58 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
5859
59 try renderDocComments(tree, stream, fn_proto, indent);60 try renderDocComments(tree, stream, fn_proto, indent, start_col);
6061
61 if (fn_proto.body_node) |body_node| {62 if (fn_proto.body_node) |body_node| {
62 try renderExpression(allocator, stream, tree, indent, decl, Space.Space);63 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space);
63 try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline);64 try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline);
64 } else {65 } else {
65 try renderExpression(allocator, stream, tree, indent, decl, Space.None);66 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None);
66 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline);67 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline);
67 }68 }
68 },69 },
6970
...@@ -71,153 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i...@@ -71,153 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i
71 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);72 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
7273
73 if (use_decl.visib_token) |visib_token| {74 if (use_decl.visib_token) |visib_token| {
74 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub75 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
75 }76 }
76 try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use77 try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use
77 try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None);78 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);
78 try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ;79 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;
79 },80 },
8081
81 ast.Node.Id.VarDecl => {82 ast.Node.Id.VarDecl => {
82 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);83 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
8384
84 try renderDocComments(tree, stream, var_decl, indent);85 try renderDocComments(tree, stream, var_decl, indent, start_col);
85 try renderVarDecl(allocator, stream, tree, indent, var_decl);86 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
86 },87 },
8788
88 ast.Node.Id.TestDecl => {89 ast.Node.Id.TestDecl => {
89 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);90 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
9091
91 try renderDocComments(tree, stream, test_decl, indent);92 try renderDocComments(tree, stream, test_decl, indent, start_col);
92 try renderToken(tree, stream, test_decl.test_token, indent, Space.Space);93 try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space);
93 try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space);94 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space);
94 try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline);95 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);
95 },96 },
9697
97 ast.Node.Id.StructField => {98 ast.Node.Id.StructField => {
98 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);99 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);
99100
100 try renderDocComments(tree, stream, field, indent);101 try renderDocComments(tree, stream, field, indent, start_col);
101 if (field.visib_token) |visib_token| {102 if (field.visib_token) |visib_token| {
102 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub103 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
103 }104 }
104 try renderToken(tree, stream, field.name_token, indent, Space.None); // name105 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
105 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // :106 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
106 try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.Comma); // type,107 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type,
107 },108 },
108109
109 ast.Node.Id.UnionTag => {110 ast.Node.Id.UnionTag => {
110 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);111 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
111112
112 try renderDocComments(tree, stream, tag, indent);113 try renderDocComments(tree, stream, tag, indent, start_col);
113114
114 if (tag.type_expr == null and tag.value_expr == null) {115 if (tag.type_expr == null and tag.value_expr == null) {
115 return renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name,116 return renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name,
116 }117 }
117118
118 if (tag.type_expr == null) {119 if (tag.type_expr == null) {
119 try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name120 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
120 } else {121 } else {
121 try renderToken(tree, stream, tag.name_token, indent, Space.None); // name122 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name
122 }123 }
123124
124 if (tag.type_expr) |type_expr| {125 if (tag.type_expr) |type_expr| {
125 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // :126 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // :
126127
127 if (tag.value_expr == null) {128 if (tag.value_expr == null) {
128 return renderExpression(allocator, stream, tree, indent, type_expr, Space.Comma); // type,129 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Comma); // type,
130 return;
129 } else {131 } else {
130 try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type132 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Space); // type
131 }133 }
132 }134 }
133135
134 const value_expr = ??tag.value_expr;136 const value_expr = ??tag.value_expr;
135 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // =137 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // =
136 try renderExpression(allocator, stream, tree, indent, value_expr, Space.Comma); // value,138 try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value,
137 },139 },
138140
139 ast.Node.Id.EnumTag => {141 ast.Node.Id.EnumTag => {
140 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);142 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
141143
142 try renderDocComments(tree, stream, tag, indent);144 try renderDocComments(tree, stream, tag, indent, start_col);
143145
144 if (tag.value) |value| {146 if (tag.value) |value| {
145 try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name147 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
146148
147 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // =149 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // =
148 try renderExpression(allocator, stream, tree, indent, value, Space.Comma);150 try renderExpression(allocator, stream, tree, indent, start_col, value, Space.Comma);
149 } else {151 } else {
150 try renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name152 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name
151 }153 }
152 },154 },
153155
154 ast.Node.Id.Comptime => {156 ast.Node.Id.Comptime => {
155 assert(!decl.requireSemiColon());157 assert(!decl.requireSemiColon());
156 try renderExpression(allocator, stream, tree, indent, decl, Space.Newline);158 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline);
157 },159 },
158 else => unreachable,160 else => unreachable,
159 }161 }
160}162}
161163
162fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void {164fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node, space: Space,) (@typeOf(stream).Child.Error || Error)!void {
163 switch (base.id) {165 switch (base.id) {
164 ast.Node.Id.Identifier => {166 ast.Node.Id.Identifier => {
165 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);167 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
166 try renderToken(tree, stream, identifier.token, indent, space);168 return renderToken(tree, stream, identifier.token, indent, start_col, space);
167 },169 },
168 ast.Node.Id.Block => {170 ast.Node.Id.Block => {
169 const block = @fieldParentPtr(ast.Node.Block, "base", base);171 const block = @fieldParentPtr(ast.Node.Block, "base", base);
170172
171 if (block.label) |label| {173 if (block.label) |label| {
172 try renderToken(tree, stream, label, indent, Space.None);174 try renderToken(tree, stream, label, indent, start_col, Space.None);
173 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);175 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
174 }176 }
175177
176 if (block.statements.len == 0) {178 if (block.statements.len == 0) {
177 try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None);179 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
178 try renderToken(tree, stream, block.rbrace, indent, space);180 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
179 } else {181 } else {
180 const block_indent = indent + indent_delta;182 const block_indent = indent + indent_delta;
181 try renderToken(tree, stream, block.lbrace, block_indent, Space.Newline);183 try renderToken(tree, stream, block.lbrace, block_indent, start_col, Space.Newline);
182184
183 var it = block.statements.iterator(0);185 var it = block.statements.iterator(0);
184 while (it.next()) |statement| {186 while (it.next()) |statement| {
185 try stream.writeByteNTimes(' ', block_indent);187 try stream.writeByteNTimes(' ', block_indent);
186 try renderStatement(allocator, stream, tree, block_indent, statement.*);188 try renderStatement(allocator, stream, tree, block_indent, start_col, statement.*);
187189
188 if (it.peek()) |next_statement| {190 if (it.peek()) |next_statement| {
189 try renderExtraNewline(tree, stream, next_statement.*);191 try renderExtraNewline(tree, stream, start_col, next_statement.*);
190 }192 }
191 }193 }
192194
193 try stream.writeByteNTimes(' ', indent);195 try stream.writeByteNTimes(' ', indent);
194 try renderToken(tree, stream, block.rbrace, indent, space);196 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
195 }197 }
196 },198 },
197 ast.Node.Id.Defer => {199 ast.Node.Id.Defer => {
198 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);200 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
199201
200 try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space);202 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
201 try renderExpression(allocator, stream, tree, indent, defer_node.expr, space);203 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
202 },204 },
203 ast.Node.Id.Comptime => {205 ast.Node.Id.Comptime => {
204 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);206 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
205207
206 try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space);208 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
207 try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space);209 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
208 },210 },
209211
210 ast.Node.Id.AsyncAttribute => {212 ast.Node.Id.AsyncAttribute => {
211 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);213 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
212214
213 if (async_attr.allocator_type) |allocator_type| {215 if (async_attr.allocator_type) |allocator_type| {
214 try renderToken(tree, stream, async_attr.async_token, indent, Space.None);216 try renderToken(tree, stream, async_attr.async_token, indent, start_col, Space.None);
215217
216 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, Space.None);218 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None);
217 try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None);219 try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None);
218 try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space);220 return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space);
219 } else {221 } else {
220 try renderToken(tree, stream, async_attr.async_token, indent, space);222 return renderToken(tree, stream, async_attr.async_token, indent, start_col, space);
221 }223 }
222 },224 },
223225
...@@ -225,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -225,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
225 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);227 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
226228
227 if (suspend_node.label) |label| {229 if (suspend_node.label) |label| {
228 try renderToken(tree, stream, label, indent, Space.None);230 try renderToken(tree, stream, label, indent, start_col, Space.None);
229 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);231 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
230 }232 }
231233
232 if (suspend_node.payload) |payload| {234 if (suspend_node.payload) |payload| {
233 if (suspend_node.body) |body| {235 if (suspend_node.body) |body| {
234 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);236 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
235 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);237 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
236 try renderExpression(allocator, stream, tree, indent, body, space);238 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
237 } else {239 } else {
238 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);240 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
239 try renderExpression(allocator, stream, tree, indent, payload, space);241 return renderExpression(allocator, stream, tree, indent, start_col, payload, space);
240 }242 }
241 } else if (suspend_node.body) |body| {243 } else if (suspend_node.body) |body| {
242 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);244 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
243 try renderExpression(allocator, stream, tree, indent, body, space);245 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
244 } else {246 } else {
245 try renderToken(tree, stream, suspend_node.suspend_token, indent, space);247 return renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, space);
246 }248 }
247 },249 },
248250
...@@ -254,7 +256,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -254,7 +256,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
254 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,256 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
255 else => Space.Space,257 else => Space.Space,
256 };258 };
257 try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space);259 try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
258260
259 const after_op_space = blk: {261 const after_op_space = blk: {
260 const loc = tree.tokenLocation(tree.tokens.at(infix_op_node.op_token).end,262 const loc = tree.tokenLocation(tree.tokens.at(infix_op_node.op_token).end,
...@@ -262,19 +264,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -262,19 +264,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
262 break :blk if (loc.line == 0) op_space else Space.Newline;264 break :blk if (loc.line == 0) op_space else Space.Newline;
263 };265 };
264266
265 try renderToken(tree, stream, infix_op_node.op_token, indent, after_op_space);267 try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space);
266 if (after_op_space == Space.Newline) {268 if (after_op_space == Space.Newline) {
267 try stream.writeByteNTimes(' ', indent + indent_delta);269 try stream.writeByteNTimes(' ', indent + indent_delta);
270 start_col.* = indent + indent_delta;
268 }271 }
269272
270 switch (infix_op_node.op) {273 switch (infix_op_node.op) {
271 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {274 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {
272 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);275 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
273 },276 },
274 else => {},277 else => {},
275 }278 }
276279
277 try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs, space);280 return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
278 },281 },
279282
280 ast.Node.Id.PrefixOp => {283 ast.Node.Id.PrefixOp => {
...@@ -282,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -282,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
282285
283 switch (prefix_op_node.op) {286 switch (prefix_op_node.op) {
284 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {287 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
285 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &288 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // &
286 if (addr_of_info.align_info) |align_info| {289 if (addr_of_info.align_info) |align_info| {
287 const lparen_token = tree.prevToken(align_info.node.firstToken());290 const lparen_token = tree.prevToken(align_info.node.firstToken());
288 const align_token = tree.prevToken(lparen_token);291 const align_token = tree.prevToken(lparen_token);
289292
290 try renderToken(tree, stream, align_token, indent, Space.None); // align293 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
291 try renderToken(tree, stream, lparen_token, indent, Space.None); // (294 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (
292295
293 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);296 try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None);
294297
295 if (align_info.bit_range) |bit_range| {298 if (align_info.bit_range) |bit_range| {
296 const colon1 = tree.prevToken(bit_range.start.firstToken());299 const colon1 = tree.prevToken(bit_range.start.firstToken());
297 const colon2 = tree.prevToken(bit_range.end.firstToken());300 const colon2 = tree.prevToken(bit_range.end.firstToken());
298301
299 try renderToken(tree, stream, colon1, indent, Space.None); // :302 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
300 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);303 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
301 try renderToken(tree, stream, colon2, indent, Space.None); // :304 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
302 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);305 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
303306
304 const rparen_token = tree.nextToken(bit_range.end.lastToken());307 const rparen_token = tree.nextToken(bit_range.end.lastToken());
305 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )308 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
306 } else {309 } else {
307 const rparen_token = tree.nextToken(align_info.node.lastToken());310 const rparen_token = tree.nextToken(align_info.node.lastToken());
308 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )311 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
309 }312 }
310 }313 }
311 if (addr_of_info.const_token) |const_token| {314 if (addr_of_info.const_token) |const_token| {
312 try renderToken(tree, stream, const_token, indent, Space.Space); // const315 try renderToken(tree, stream, const_token, indent, start_col, Space.Space); // const
313 }316 }
314 if (addr_of_info.volatile_token) |volatile_token| {317 if (addr_of_info.volatile_token) |volatile_token| {
315 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile318 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
316 }319 }
317 },320 },
318321
319 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {322 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
320 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [323 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
321 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]324 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
322325
323 if (addr_of_info.align_info) |align_info| {326 if (addr_of_info.align_info) |align_info| {
324 const lparen_token = tree.prevToken(align_info.node.firstToken());327 const lparen_token = tree.prevToken(align_info.node.firstToken());
325 const align_token = tree.prevToken(lparen_token);328 const align_token = tree.prevToken(lparen_token);
326329
327 try renderToken(tree, stream, align_token, indent, Space.None); // align330 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
328 try renderToken(tree, stream, lparen_token, indent, Space.None); // (331 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (
329332
330 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);333 try renderExpression(allocator, stream, tree, indent, start_col, align_info.node, Space.None);
331334
332 if (align_info.bit_range) |bit_range| {335 if (align_info.bit_range) |bit_range| {
333 const colon1 = tree.prevToken(bit_range.start.firstToken());336 const colon1 = tree.prevToken(bit_range.start.firstToken());
334 const colon2 = tree.prevToken(bit_range.end.firstToken());337 const colon2 = tree.prevToken(bit_range.end.firstToken());
335338
336 try renderToken(tree, stream, colon1, indent, Space.None); // :339 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
337 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);340 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
338 try renderToken(tree, stream, colon2, indent, Space.None); // :341 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
339 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);342 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
340343
341 const rparen_token = tree.nextToken(bit_range.end.lastToken());344 const rparen_token = tree.nextToken(bit_range.end.lastToken());
342 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )345 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
343 } else {346 } else {
344 const rparen_token = tree.nextToken(align_info.node.lastToken());347 const rparen_token = tree.nextToken(align_info.node.lastToken());
345 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )348 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )
346 }349 }
347 }350 }
348 if (addr_of_info.const_token) |const_token| {351 if (addr_of_info.const_token) |const_token| {
349 try renderToken(tree, stream, const_token, indent, Space.Space);352 try renderToken(tree, stream, const_token, indent, start_col, Space.Space);
350 }353 }
351 if (addr_of_info.volatile_token) |volatile_token| {354 if (addr_of_info.volatile_token) |volatile_token| {
352 try renderToken(tree, stream, volatile_token, indent, Space.Space);355 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space);
353 }356 }
354 },357 },
355358
356 ast.Node.PrefixOp.Op.ArrayType => |array_index| {359 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
357 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [360 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
358 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);361 try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None);
359 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ]362 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ]
360 },363 },
361 ast.Node.PrefixOp.Op.BitNot,364 ast.Node.PrefixOp.Op.BitNot,
362 ast.Node.PrefixOp.Op.BoolNot,365 ast.Node.PrefixOp.Op.BoolNot,
...@@ -365,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -365,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
365 ast.Node.PrefixOp.Op.UnwrapMaybe,368 ast.Node.PrefixOp.Op.UnwrapMaybe,
366 ast.Node.PrefixOp.Op.MaybeType,369 ast.Node.PrefixOp.Op.MaybeType,
367 ast.Node.PrefixOp.Op.PointerType => {370 ast.Node.PrefixOp.Op.PointerType => {
368 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None);371 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None);
369 },372 },
370373
371 ast.Node.PrefixOp.Op.Try,374 ast.Node.PrefixOp.Op.Try,
372 ast.Node.PrefixOp.Op.Await,375 ast.Node.PrefixOp.Op.Await,
373 ast.Node.PrefixOp.Op.Cancel,376 ast.Node.PrefixOp.Op.Cancel,
374 ast.Node.PrefixOp.Op.Resume => {377 ast.Node.PrefixOp.Op.Resume => {
375 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.Space);378 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
376 },379 },
377 }380 }
378381
379 try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs, space);382 return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space);
380 },383 },
381384
382 ast.Node.Id.SuffixOp => {385 ast.Node.Id.SuffixOp => {
...@@ -385,17 +388,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -385,17 +388,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
385 switch (suffix_op.op) {388 switch (suffix_op.op) {
386 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {389 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
387 if (call_info.async_attr) |async_attr| {390 if (call_info.async_attr) |async_attr| {
388 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);391 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);
389 }392 }
390393
391 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);394 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
392395
393 const lparen = tree.nextToken(suffix_op.lhs.lastToken());396 const lparen = tree.nextToken(suffix_op.lhs.lastToken());
394397
395 if (call_info.params.len == 0) {398 if (call_info.params.len == 0) {
396 try renderToken(tree, stream, lparen, indent, Space.None);399 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
397 try renderToken(tree, stream, suffix_op.rtoken, indent, space);400 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
398 return;
399 }401 }
400402
401 const src_has_trailing_comma = blk: {403 const src_has_trailing_comma = blk: {
...@@ -405,7 +407,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -405,7 +407,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
405407
406 if (src_has_trailing_comma) {408 if (src_has_trailing_comma) {
407 const new_indent = indent + indent_delta;409 const new_indent = indent + indent_delta;
408 try renderToken(tree, stream, lparen, new_indent, Space.Newline);410 try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline);
409411
410 var it = call_info.params.iterator(0);412 var it = call_info.params.iterator(0);
411 while (true) {413 while (true) {
...@@ -419,72 +421,70 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -419,72 +421,70 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
419 };421 };
420422
421 if (it.peek()) |next_node| {423 if (it.peek()) |next_node| {
422 try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.None);424 try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.None);
423 const comma = tree.nextToken(param_node.*.lastToken());425 const comma = tree.nextToken(param_node.*.lastToken());
424 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,426 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
425 try renderExtraNewline(tree, stream, next_node.*);427 try renderExtraNewline(tree, stream, start_col, next_node.*);
426 } else {428 } else {
427 try renderExpression(allocator, stream, tree, param_node_new_indent, param_node.*, Space.Comma);429 try renderExpression(allocator, stream, tree, param_node_new_indent, start_col, param_node.*, Space.Comma);
428 try stream.writeByteNTimes(' ', indent);430 try stream.writeByteNTimes(' ', indent);
429 try renderToken(tree, stream, suffix_op.rtoken, indent, space);431 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
430 return;
431 }432 }
432 }433 }
433 }434 }
434435
435 try renderToken(tree, stream, lparen, indent, Space.None); // (436 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
436437
437 var it = call_info.params.iterator(0);438 var it = call_info.params.iterator(0);
438 while (it.next()) |param_node| {439 while (it.next()) |param_node| {
439 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);440 try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None);
440441
441 if (it.peek() != null) {442 if (it.peek() != null) {
442 const comma = tree.nextToken(param_node.*.lastToken());443 const comma = tree.nextToken(param_node.*.lastToken());
443 try renderToken(tree, stream, comma, indent, Space.Space);444 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
444 }445 }
445 }446 }
446 try renderToken(tree, stream, suffix_op.rtoken, indent, space);447 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
447 },448 },
448449
449 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {450 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
450 const lbracket = tree.prevToken(index_expr.firstToken());451 const lbracket = tree.prevToken(index_expr.firstToken());
451 const rbracket = tree.nextToken(index_expr.lastToken());452 const rbracket = tree.nextToken(index_expr.lastToken());
452453
453 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);454 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
454 try renderToken(tree, stream, lbracket, indent, Space.None); // [455 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
455 try renderExpression(allocator, stream, tree, indent, index_expr, Space.None);456 try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None);
456 try renderToken(tree, stream, rbracket, indent, space); // ]457 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
457 },458 },
458459
459 ast.Node.SuffixOp.Op.Deref => {460 ast.Node.SuffixOp.Op.Deref => {
460 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);461 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
461 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // .462 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
462 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // *463 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // *
463 },464 },
464465
465 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {466 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
466 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);467 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
467468
468 const lbracket = tree.prevToken(range.start.firstToken());469 const lbracket = tree.prevToken(range.start.firstToken());
469 const dotdot = tree.nextToken(range.start.lastToken());470 const dotdot = tree.nextToken(range.start.lastToken());
470471
471 try renderToken(tree, stream, lbracket, indent, Space.None); // [472 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
472 try renderExpression(allocator, stream, tree, indent, range.start, Space.None);473 try renderExpression(allocator, stream, tree, indent, start_col, range.start, Space.None);
473 try renderToken(tree, stream, dotdot, indent, Space.None); // ..474 try renderToken(tree, stream, dotdot, indent, start_col, Space.None); // ..
474 if (range.end) |end| {475 if (range.end) |end| {
475 try renderExpression(allocator, stream, tree, indent, end, Space.None);476 try renderExpression(allocator, stream, tree, indent, start_col, end, Space.None);
476 }477 }
477 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ]478 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
478 },479 },
479480
480 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {481 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
481 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());482 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
482483
483 if (field_inits.len == 0) {484 if (field_inits.len == 0) {
484 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);485 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
485 try renderToken(tree, stream, lbrace, indent, Space.None);486 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
486 try renderToken(tree, stream, suffix_op.rtoken, indent, space);487 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
487 return;
488 }488 }
489489
490 if (field_inits.len == 1) blk: {490 if (field_inits.len == 1) blk: {
...@@ -496,11 +496,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -496,11 +496,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
496 }496 }
497 }497 }
498498
499 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);499 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
500 try renderToken(tree, stream, lbrace, indent, Space.Space);500 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
501 try renderExpression(allocator, stream, tree, indent, &field_init.base, Space.Space);501 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
502 try renderToken(tree, stream, suffix_op.rtoken, indent, space);502 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
503 return;
504 }503 }
505504
506 const src_has_trailing_comma = blk: {505 const src_has_trailing_comma = blk: {
...@@ -515,27 +514,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -515,27 +514,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
515514
516 if (!src_has_trailing_comma and src_same_line) {515 if (!src_has_trailing_comma and src_same_line) {
517 // render all on one line, no trailing comma516 // render all on one line, no trailing comma
518 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);517 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
519 try renderToken(tree, stream, lbrace, indent, Space.Space);518 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
520519
521 var it = field_inits.iterator(0);520 var it = field_inits.iterator(0);
522 while (it.next()) |field_init| {521 while (it.next()) |field_init| {
523 if (it.peek() != null) {522 if (it.peek() != null) {
524 try renderExpression(allocator, stream, tree, indent, field_init.*, Space.None);523 try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.None);
525524
526 const comma = tree.nextToken(field_init.*.lastToken());525 const comma = tree.nextToken(field_init.*.lastToken());
527 try renderToken(tree, stream, comma, indent, Space.Space);526 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
528 } else {527 } else {
529 try renderExpression(allocator, stream, tree, indent, field_init.*, Space.Space);528 try renderExpression(allocator, stream, tree, indent, start_col, field_init.*, Space.Space);
530 }529 }
531 }530 }
532531
533 try renderToken(tree, stream, suffix_op.rtoken, indent, space);532 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
534 return;
535 }533 }
536534
537 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);535 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
538 try renderToken(tree, stream, lbrace, indent, Space.Newline);536 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline);
539537
540 const new_indent = indent + indent_delta;538 const new_indent = indent + indent_delta;
541539
...@@ -544,41 +542,39 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -544,41 +542,39 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
544 try stream.writeByteNTimes(' ', new_indent);542 try stream.writeByteNTimes(' ', new_indent);
545543
546 if (it.peek()) |next_field_init| {544 if (it.peek()) |next_field_init| {
547 try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None);545 try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.None);
548546
549 const comma = tree.nextToken(field_init.*.lastToken());547 const comma = tree.nextToken(field_init.*.lastToken());
550 try renderToken(tree, stream, comma, new_indent, Space.Newline);548 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline);
551549
552 try renderExtraNewline(tree, stream, next_field_init.*);550 try renderExtraNewline(tree, stream, start_col, next_field_init.*);
553 } else {551 } else {
554 try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.Comma);552 try renderExpression(allocator, stream, tree, new_indent, start_col, field_init.*, Space.Comma);
555 }553 }
556 }554 }
557555
558 try stream.writeByteNTimes(' ', indent);556 try stream.writeByteNTimes(' ', indent);
559 try renderToken(tree, stream, suffix_op.rtoken, indent, space);557 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
560 },558 },
561559
562 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {560 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
563 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());561 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
564562
565 if (exprs.len == 0) {563 if (exprs.len == 0) {
566 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);564 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
567 try renderToken(tree, stream, lbrace, indent, Space.None);565 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
568 try renderToken(tree, stream, suffix_op.rtoken, indent, space);566 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
569 return;
570 }567 }
571 if (exprs.len == 1) {568 if (exprs.len == 1) {
572 const expr = exprs.at(0).*;569 const expr = exprs.at(0).*;
573570
574 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);571 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
575 try renderToken(tree, stream, lbrace, indent, Space.None);572 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
576 try renderExpression(allocator, stream, tree, indent, expr, Space.None);573 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
577 try renderToken(tree, stream, suffix_op.rtoken, indent, space);574 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
578 return;
579 }575 }
580576
581 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);577 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
582578
583 // scan to find row size579 // scan to find row size
584 const maybe_row_size: ?usize = blk: {580 const maybe_row_size: ?usize = blk: {
...@@ -613,50 +609,48 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -613,50 +609,48 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
613609
614 if (maybe_row_size) |row_size| {610 if (maybe_row_size) |row_size| {
615 const new_indent = indent + indent_delta;611 const new_indent = indent + indent_delta;
616 try renderToken(tree, stream, lbrace, new_indent, Space.Newline);612 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
617 try stream.writeByteNTimes(' ', new_indent);613 try stream.writeByteNTimes(' ', new_indent);
618614
619 var it = exprs.iterator(0);615 var it = exprs.iterator(0);
620 var i: usize = 1;616 var i: usize = 1;
621 while (it.next()) |expr| {617 while (it.next()) |expr| {
622 if (it.peek()) |next_expr| {618 if (it.peek()) |next_expr| {
623 try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);619 try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.None);
624620
625 const comma = tree.nextToken(expr.*.lastToken());621 const comma = tree.nextToken(expr.*.lastToken());
626622
627 if (i != row_size) {623 if (i != row_size) {
628 try renderToken(tree, stream, comma, new_indent, Space.Space); // ,624 try renderToken(tree, stream, comma, new_indent, start_col, Space.Space); // ,
629 i += 1;625 i += 1;
630 continue;626 continue;
631 }627 }
632 i = 1;628 i = 1;
633629
634 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,630 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
635631
636 try renderExtraNewline(tree, stream, next_expr.*);632 try renderExtraNewline(tree, stream, start_col, next_expr.*);
637 try stream.writeByteNTimes(' ', new_indent);633 try stream.writeByteNTimes(' ', new_indent);
638 } else {634 } else {
639 try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.Comma); // ,635 try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.Comma); // ,
640 }636 }
641 }637 }
642 try stream.writeByteNTimes(' ', indent);638 try stream.writeByteNTimes(' ', indent);
643 try renderToken(tree, stream, suffix_op.rtoken, indent, space);639 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
644 return;
645 } else {640 } else {
646 try renderToken(tree, stream, lbrace, indent, Space.Space);641 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
647 var it = exprs.iterator(0);642 var it = exprs.iterator(0);
648 while (it.next()) |expr| {643 while (it.next()) |expr| {
649 if (it.peek()) |next_expr| {644 if (it.peek()) |next_expr| {
650 try renderExpression(allocator, stream, tree, indent, expr.*, Space.None);645 try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.None);
651 const comma = tree.nextToken(expr.*.lastToken());646 const comma = tree.nextToken(expr.*.lastToken());
652 try renderToken(tree, stream, comma, indent, Space.Space); // ,647 try renderToken(tree, stream, comma, indent, start_col, Space.Space); // ,
653 } else {648 } else {
654 try renderExpression(allocator, stream, tree, indent, expr.*, Space.Space);649 try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.Space);
655 }650 }
656 }651 }
657652
658 try renderToken(tree, stream, suffix_op.rtoken, indent, space);653 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
659 return;
660 }654 }
661 },655 },
662 }656 }
...@@ -667,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -667,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
667661
668 switch (flow_expr.kind) {662 switch (flow_expr.kind) {
669 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {663 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
670 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;664 if (maybe_label == null and flow_expr.rhs == null) {
671 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);665 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // break
666 }
667
668 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // break
672 if (maybe_label) |label| {669 if (maybe_label) |label| {
673 const colon = tree.nextToken(flow_expr.ltoken);670 const colon = tree.nextToken(flow_expr.ltoken);
674 try renderToken(tree, stream, colon, indent, Space.None);671 try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
675672
676 const expr_space = if (flow_expr.rhs != null) Space.Space else space;673 if (flow_expr.rhs == null) {
677 try renderExpression(allocator, stream, tree, indent, label, expr_space);674 return renderExpression(allocator, stream, tree, indent, start_col, label, space); // label
675 }
676 try renderExpression(allocator, stream, tree, indent, start_col, label, Space.Space); // label
678 }677 }
679 },678 },
680 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {679 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
681 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;680 assert(flow_expr.rhs == null);
682 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);681
682 if (maybe_label == null and flow_expr.rhs == null) {
683 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space); // continue
684 }
685
686 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space); // continue
683 if (maybe_label) |label| {687 if (maybe_label) |label| {
684 const colon = tree.nextToken(flow_expr.ltoken);688 const colon = tree.nextToken(flow_expr.ltoken);
685 try renderToken(tree, stream, colon, indent, Space.None);689 try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
686690
687 const expr_space = if (flow_expr.rhs != null) Space.Space else space;691 return renderExpression(allocator, stream, tree, indent, start_col, label, space);
688 try renderExpression(allocator, stream, tree, indent, label, space);
689 }692 }
690 },693 },
691 ast.Node.ControlFlowExpression.Kind.Return => {694 ast.Node.ControlFlowExpression.Kind.Return => {
692 const kw_space = if (flow_expr.rhs != null) Space.Space else space;695 if (flow_expr.rhs == null) {
693 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);696 return renderToken(tree, stream, flow_expr.ltoken, indent, start_col, space);
697 }
698 try renderToken(tree, stream, flow_expr.ltoken, indent, start_col, Space.Space);
694 },699 },
695 }700 }
696701
697 if (flow_expr.rhs) |rhs| {702 return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space);
698 try renderExpression(allocator, stream, tree, indent, rhs, space);
699 }
700 },703 },
701704
702 ast.Node.Id.Payload => {705 ast.Node.Id.Payload => {
703 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);706 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
704707
705 try renderToken(tree, stream, payload.lpipe, indent, Space.None);708 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
706 try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None);709 try renderExpression(allocator, stream, tree, indent, start_col, payload.error_symbol, Space.None);
707 try renderToken(tree, stream, payload.rpipe, indent, space);710 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
708 },711 },
709712
710 ast.Node.Id.PointerPayload => {713 ast.Node.Id.PointerPayload => {
711 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);714 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
712715
713 try renderToken(tree, stream, payload.lpipe, indent, Space.None);716 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
714 if (payload.ptr_token) |ptr_token| {717 if (payload.ptr_token) |ptr_token| {
715 try renderToken(tree, stream, ptr_token, indent, Space.None);718 try renderToken(tree, stream, ptr_token, indent, start_col, Space.None);
716 }719 }
717 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);720 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
718 try renderToken(tree, stream, payload.rpipe, indent, space);721 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
719 },722 },
720723
721 ast.Node.Id.PointerIndexPayload => {724 ast.Node.Id.PointerIndexPayload => {
722 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);725 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
723726
724 try renderToken(tree, stream, payload.lpipe, indent, Space.None);727 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
725 if (payload.ptr_token) |ptr_token| {728 if (payload.ptr_token) |ptr_token| {
726 try renderToken(tree, stream, ptr_token, indent, Space.None);729 try renderToken(tree, stream, ptr_token, indent, start_col, Space.None);
727 }730 }
728 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);731 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
729732
730 if (payload.index_symbol) |index_symbol| {733 if (payload.index_symbol) |index_symbol| {
731 const comma = tree.nextToken(payload.value_symbol.lastToken());734 const comma = tree.nextToken(payload.value_symbol.lastToken());
732735
733 try renderToken(tree, stream, comma, indent, Space.Space);736 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
734 try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None);737 try renderExpression(allocator, stream, tree, indent, start_col, index_symbol, Space.None);
735 }738 }
736739
737 try renderToken(tree, stream, payload.rpipe, indent, space);740 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
738 },741 },
739742
740 ast.Node.Id.GroupedExpression => {743 ast.Node.Id.GroupedExpression => {
741 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);744 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
742745
743 try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None);746 try renderToken(tree, stream, grouped_expr.lparen, indent, start_col, Space.None);
744 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None);747 try renderExpression(allocator, stream, tree, indent, start_col, grouped_expr.expr, Space.None);
745 try renderToken(tree, stream, grouped_expr.rparen, indent, space);748 return renderToken(tree, stream, grouped_expr.rparen, indent, start_col, space);
746 },749 },
747750
748 ast.Node.Id.FieldInitializer => {751 ast.Node.Id.FieldInitializer => {
749 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);752 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
750753
751 try renderToken(tree, stream, field_init.period_token, indent, Space.None); // .754 try renderToken(tree, stream, field_init.period_token, indent, start_col, Space.None); // .
752 try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name755 try renderToken(tree, stream, field_init.name_token, indent, start_col, Space.Space); // name
753 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // =756 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, start_col, Space.Space); // =
754 try renderExpression(allocator, stream, tree, indent, field_init.expr, space);757 return renderExpression(allocator, stream, tree, indent, start_col, field_init.expr, space);
755 },758 },
756759
757 ast.Node.Id.IntegerLiteral => {760 ast.Node.Id.IntegerLiteral => {
758 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);761 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);
759 try renderToken(tree, stream, integer_literal.token, indent, space);762 return renderToken(tree, stream, integer_literal.token, indent, start_col, space);
760 },763 },
761 ast.Node.Id.FloatLiteral => {764 ast.Node.Id.FloatLiteral => {
762 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);765 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);
763 try renderToken(tree, stream, float_literal.token, indent, space);766 return renderToken(tree, stream, float_literal.token, indent, start_col, space);
764 },767 },
765 ast.Node.Id.StringLiteral => {768 ast.Node.Id.StringLiteral => {
766 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);769 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);
767 try renderToken(tree, stream, string_literal.token, indent, space);770 return renderToken(tree, stream, string_literal.token, indent, start_col, space);
768 },771 },
769 ast.Node.Id.CharLiteral => {772 ast.Node.Id.CharLiteral => {
770 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);773 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
771 try renderToken(tree, stream, char_literal.token, indent, space);774 return renderToken(tree, stream, char_literal.token, indent, start_col, space);
772 },775 },
773 ast.Node.Id.BoolLiteral => {776 ast.Node.Id.BoolLiteral => {
774 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);777 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
775 try renderToken(tree, stream, bool_literal.token, indent, space);778 return renderToken(tree, stream, bool_literal.token, indent, start_col, space);
776 },779 },
777 ast.Node.Id.NullLiteral => {780 ast.Node.Id.NullLiteral => {
778 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);781 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);
779 try renderToken(tree, stream, null_literal.token, indent, space);782 return renderToken(tree, stream, null_literal.token, indent, start_col, space);
780 },783 },
781 ast.Node.Id.ThisLiteral => {784 ast.Node.Id.ThisLiteral => {
782 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);785 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);
783 try renderToken(tree, stream, this_literal.token, indent, space);786 return renderToken(tree, stream, this_literal.token, indent, start_col, space);
784 },787 },
785 ast.Node.Id.Unreachable => {788 ast.Node.Id.Unreachable => {
786 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);789 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);
787 try renderToken(tree, stream, unreachable_node.token, indent, space);790 return renderToken(tree, stream, unreachable_node.token, indent, start_col, space);
788 },791 },
789 ast.Node.Id.ErrorType => {792 ast.Node.Id.ErrorType => {
790 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);793 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);
791 try renderToken(tree, stream, error_type.token, indent, space);794 return renderToken(tree, stream, error_type.token, indent, start_col, space);
792 },795 },
793 ast.Node.Id.VarType => {796 ast.Node.Id.VarType => {
794 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);797 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);
795 try renderToken(tree, stream, var_type.token, indent, space);798 return renderToken(tree, stream, var_type.token, indent, start_col, space);
796 },799 },
797 ast.Node.Id.ContainerDecl => {800 ast.Node.Id.ContainerDecl => {
798 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);801 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
799802
800 if (container_decl.layout_token) |layout_token| {803 if (container_decl.layout_token) |layout_token| {
801 try renderToken(tree, stream, layout_token, indent, Space.Space);804 try renderToken(tree, stream, layout_token, indent, start_col, Space.Space);
802 }805 }
803806
804 switch (container_decl.init_arg_expr) {807 switch (container_decl.init_arg_expr) {
805 ast.Node.ContainerDecl.InitArg.None => {808 ast.Node.ContainerDecl.InitArg.None => {
806 try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union809 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
807 },810 },
808 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {811 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
809 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union812 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
810813
811 const lparen = tree.nextToken(container_decl.kind_token);814 const lparen = tree.nextToken(container_decl.kind_token);
812 const enum_token = tree.nextToken(lparen);815 const enum_token = tree.nextToken(lparen);
813816
814 try renderToken(tree, stream, lparen, indent, Space.None); // (817 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
815 try renderToken(tree, stream, enum_token, indent, Space.None); // enum818 try renderToken(tree, stream, enum_token, indent, start_col, Space.None); // enum
816819
817 if (enum_tag_type) |expr| {820 if (enum_tag_type) |expr| {
818 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // (821 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.None); // (
819 try renderExpression(allocator, stream, tree, indent, expr, Space.None);822 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
820823
821 const rparen = tree.nextToken(expr.lastToken());824 const rparen = tree.nextToken(expr.lastToken());
822 try renderToken(tree, stream, rparen, indent, Space.None); // )825 try renderToken(tree, stream, rparen, indent, start_col, Space.None); // )
823 try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // )826 try renderToken(tree, stream, tree.nextToken(rparen), indent, start_col, Space.Space); // )
824 } else {827 } else {
825 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.Space); // )828 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )
826 }829 }
827 },830 },
828 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {831 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
829 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union832 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
830833
831 const lparen = tree.nextToken(container_decl.kind_token);834 const lparen = tree.nextToken(container_decl.kind_token);
832 const rparen = tree.nextToken(type_expr.lastToken());835 const rparen = tree.nextToken(type_expr.lastToken());
833836
834 try renderToken(tree, stream, lparen, indent, Space.None); // (837 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
835 try renderExpression(allocator, stream, tree, indent, type_expr, Space.None);838 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.None);
836 try renderToken(tree, stream, rparen, indent, Space.Space); // )839 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
837 },840 },
838 }841 }
839842
840 if (container_decl.fields_and_decls.len == 0) {843 if (container_decl.fields_and_decls.len == 0) {
841 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // {844 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {
842 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }845 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
843 } else {846 } else {
844 const new_indent = indent + indent_delta;847 const new_indent = indent + indent_delta;
845 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, Space.Newline); // {848 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, Space.Newline); // {
846849
847 var it = container_decl.fields_and_decls.iterator(0);850 var it = container_decl.fields_and_decls.iterator(0);
848 while (it.next()) |decl| {851 while (it.next()) |decl| {
849 try stream.writeByteNTimes(' ', new_indent);852 try stream.writeByteNTimes(' ', new_indent);
850 try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*);853 try renderTopLevelDecl(allocator, stream, tree, new_indent, start_col, decl.*);
851854
852 if (it.peek()) |next_decl| {855 if (it.peek()) |next_decl| {
853 try renderExtraNewline(tree, stream, next_decl.*);856 try renderExtraNewline(tree, stream, start_col, next_decl.*);
854 }857 }
855 }858 }
856859
857 try stream.writeByteNTimes(' ', indent);860 try stream.writeByteNTimes(' ', indent);
858 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }861 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
859 }862 }
860 },863 },
861864
...@@ -865,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -865,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
865 const lbrace = tree.nextToken(err_set_decl.error_token);868 const lbrace = tree.nextToken(err_set_decl.error_token);
866869
867 if (err_set_decl.decls.len == 0) {870 if (err_set_decl.decls.len == 0) {
868 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None);871 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None);
869 try renderToken(tree, stream, lbrace, indent, Space.None);872 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
870 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space);873 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space);
871 return;
872 }874 }
873875
874 if (err_set_decl.decls.len == 1) blk: {876 if (err_set_decl.decls.len == 1) blk: {
...@@ -882,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -882,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
882 break :blk;884 break :blk;
883 }885 }
884886
885 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error887 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
886 try renderToken(tree, stream, lbrace, indent, Space.None); // {888 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
887 try renderExpression(allocator, stream, tree, indent, node, Space.None);889 try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None);
888 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }890 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
889 return;
890 }891 }
891892
892 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error893 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
893 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {894 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
894 const new_indent = indent + indent_delta;895 const new_indent = indent + indent_delta;
895896
896 var it = err_set_decl.decls.iterator(0);897 var it = err_set_decl.decls.iterator(0);
...@@ -898,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -898,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
898 try stream.writeByteNTimes(' ', new_indent);899 try stream.writeByteNTimes(' ', new_indent);
899900
900 if (it.peek()) |next_node| {901 if (it.peek()) |next_node| {
901 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);902 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
902 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,903 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, start_col, Space.Newline); // ,
903904
904 try renderExtraNewline(tree, stream, next_node.*);905 try renderExtraNewline(tree, stream, start_col, next_node.*);
905 } else {906 } else {
906 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma);907 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
907 }908 }
908 }909 }
909910
910 try stream.writeByteNTimes(' ', indent);911 try stream.writeByteNTimes(' ', indent);
911 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }912 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
912 },913 },
913914
914 ast.Node.Id.ErrorTag => {915 ast.Node.Id.ErrorTag => {
915 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);916 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
916917
917 try renderDocComments(tree, stream, tag, indent);918 try renderDocComments(tree, stream, tag, indent, start_col);
918 try renderToken(tree, stream, tag.name_token, indent, space); // name919 return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name
919 },920 },
920921
921 ast.Node.Id.MultilineStringLiteral => {922 ast.Node.Id.MultilineStringLiteral => {
...@@ -933,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -933,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
933 if (!skip_first_indent) {934 if (!skip_first_indent) {
934 try stream.writeByteNTimes(' ', indent + indent_delta);935 try stream.writeByteNTimes(' ', indent + indent_delta);
935 }936 }
936 try renderToken(tree, stream, t, indent, Space.None);937 try renderToken(tree, stream, t, indent, start_col, Space.None);
937 skip_first_indent = false;938 skip_first_indent = false;
938 }939 }
939 try stream.writeByteNTimes(' ', indent);940 try stream.writeByteNTimes(' ', indent);
940 },941 },
941 ast.Node.Id.UndefinedLiteral => {942 ast.Node.Id.UndefinedLiteral => {
942 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);943 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);
943 try renderToken(tree, stream, undefined_literal.token, indent, space);944 return renderToken(tree, stream, undefined_literal.token, indent, start_col, space);
944 },945 },
945946
946 ast.Node.Id.BuiltinCall => {947 ast.Node.Id.BuiltinCall => {
947 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);948 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
948949
949 try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name950 try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name
950 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // (951 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, start_col, Space.None); // (
951952
952 var it = builtin_call.params.iterator(0);953 var it = builtin_call.params.iterator(0);
953 while (it.next()) |param_node| {954 while (it.next()) |param_node| {
954 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);955 try renderExpression(allocator, stream, tree, indent, start_col, param_node.*, Space.None);
955956
956 if (it.peek() != null) {957 if (it.peek() != null) {
957 const comma_token = tree.nextToken(param_node.*.lastToken());958 const comma_token = tree.nextToken(param_node.*.lastToken());
958 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,959 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
959 }960 }
960 }961 }
961 try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // )962 return renderToken(tree, stream, builtin_call.rparen_token, indent, start_col, space); // )
962 },963 },
963964
964 ast.Node.Id.FnProto => {965 ast.Node.Id.FnProto => {
...@@ -968,31 +969,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -968,31 +969,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
968 const visib_token = tree.tokens.at(visib_token_index);969 const visib_token = tree.tokens.at(visib_token_index);
969 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);970 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
970971
971 try renderToken(tree, stream, visib_token_index, indent, Space.Space); // pub972 try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub
972 }973 }
973974
974 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {975 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
975 try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export976 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
976 }977 }
977978
978 if (fn_proto.lib_name) |lib_name| {979 if (fn_proto.lib_name) |lib_name| {
979 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space);980 try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space);
980 }981 }
981982
982 if (fn_proto.cc_token) |cc_token| {983 if (fn_proto.cc_token) |cc_token| {
983 try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc984 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
984 }985 }
985986
986 if (fn_proto.async_attr) |async_attr| {987 if (fn_proto.async_attr) |async_attr| {
987 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);988 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);
988 }989 }
989990
990 const lparen = if (fn_proto.name_token) |name_token| blk: {991 const lparen = if (fn_proto.name_token) |name_token| blk: {
991 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn992 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn
992 try renderToken(tree, stream, name_token, indent, Space.None); // name993 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name
993 break :blk tree.nextToken(name_token);994 break :blk tree.nextToken(name_token);
994 } else blk: {995 } else blk: {
995 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn996 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn
996 break :blk tree.nextToken(fn_proto.fn_token);997 break :blk tree.nextToken(fn_proto.fn_token);
997 };998 };
998999
...@@ -1011,51 +1012,51 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1011,51 +1012,51 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1011 };1012 };
10121013
1013 if (!src_params_trailing_comma and src_params_same_line) {1014 if (!src_params_trailing_comma and src_params_same_line) {
1014 try renderToken(tree, stream, lparen, indent, Space.None); // (1015 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
10151016
1016 // render all on one line, no trailing comma1017 // render all on one line, no trailing comma
1017 var it = fn_proto.params.iterator(0);1018 var it = fn_proto.params.iterator(0);
1018 while (it.next()) |param_decl_node| {1019 while (it.next()) |param_decl_node| {
1019 try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.None);1020 try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.None);
10201021
1021 if (it.peek() != null) {1022 if (it.peek() != null) {
1022 const comma = tree.nextToken(param_decl_node.*.lastToken());1023 const comma = tree.nextToken(param_decl_node.*.lastToken());
1023 try renderToken(tree, stream, comma, indent, Space.Space); // ,1024 try renderToken(tree, stream, comma, indent, start_col, Space.Space); // ,
1024 }1025 }
1025 }1026 }
1026 } else {1027 } else {
1027 // one param per line1028 // one param per line
1028 const new_indent = indent + indent_delta;1029 const new_indent = indent + indent_delta;
1029 try renderToken(tree, stream, lparen, new_indent, Space.Newline); // (1030 try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline); // (
10301031
1031 var it = fn_proto.params.iterator(0);1032 var it = fn_proto.params.iterator(0);
1032 while (it.next()) |param_decl_node| {1033 while (it.next()) |param_decl_node| {
1033 try stream.writeByteNTimes(' ', new_indent);1034 try stream.writeByteNTimes(' ', new_indent);
1034 try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*, Space.Comma);1035 try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node.*, Space.Comma);
1035 }1036 }
1036 try stream.writeByteNTimes(' ', indent);1037 try stream.writeByteNTimes(' ', indent);
1037 }1038 }
10381039
1039 try renderToken(tree, stream, rparen, indent, Space.Space); // )1040 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
10401041
1041 if (fn_proto.align_expr) |align_expr| {1042 if (fn_proto.align_expr) |align_expr| {
1042 const align_rparen = tree.nextToken(align_expr.lastToken());1043 const align_rparen = tree.nextToken(align_expr.lastToken());
1043 const align_lparen = tree.prevToken(align_expr.firstToken());1044 const align_lparen = tree.prevToken(align_expr.firstToken());
1044 const align_kw = tree.prevToken(align_lparen);1045 const align_kw = tree.prevToken(align_lparen);
10451046
1046 try renderToken(tree, stream, align_kw, indent, Space.None); // align1047 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1047 try renderToken(tree, stream, align_lparen, indent, Space.None); // (1048 try renderToken(tree, stream, align_lparen, indent, start_col, Space.None); // (
1048 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);1049 try renderExpression(allocator, stream, tree, indent, start_col, align_expr, Space.None);
1049 try renderToken(tree, stream, align_rparen, indent, Space.Space); // )1050 try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // )
1050 }1051 }
10511052
1052 switch (fn_proto.return_type) {1053 switch (fn_proto.return_type) {
1053 ast.Node.FnProto.ReturnType.Explicit => |node| {1054 ast.Node.FnProto.ReturnType.Explicit => |node| {
1054 try renderExpression(allocator, stream, tree, indent, node, space);1055 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
1055 },1056 },
1056 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {1057 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
1057 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // !1058 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // !
1058 try renderExpression(allocator, stream, tree, indent, node, space);1059 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
1059 },1060 },
1060 }1061 }
1061 },1062 },
...@@ -1064,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1064,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1064 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);1065 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
10651066
1066 if (promise_type.result) |result| {1067 if (promise_type.result) |result| {
1067 try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise1068 try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise
1068 try renderToken(tree, stream, result.arrow_token, indent, Space.None); // ->1069 try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // ->
1069 try renderExpression(allocator, stream, tree, indent, result.return_type, space);1070 return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space);
1070 } else {1071 } else {
1071 try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise1072 return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise
1072 }1073 }
1073 },1074 },
10741075
...@@ -1077,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1077,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1077 ast.Node.Id.Switch => {1078 ast.Node.Id.Switch => {
1078 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);1079 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
10791080
1080 try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch1081 try renderToken(tree, stream, switch_node.switch_token, indent, start_col, Space.Space); // switch
1081 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // (1082 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, start_col, Space.None); // (
10821083
1083 const rparen = tree.nextToken(switch_node.expr.lastToken());1084 const rparen = tree.nextToken(switch_node.expr.lastToken());
1084 const lbrace = tree.nextToken(rparen);1085 const lbrace = tree.nextToken(rparen);
10851086
1086 if (switch_node.cases.len == 0) {1087 if (switch_node.cases.len == 0) {
1087 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);1088 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
1088 try renderToken(tree, stream, rparen, indent, Space.Space); // )1089 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1089 try renderToken(tree, stream, lbrace, indent, Space.None); // {1090 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
1090 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }1091 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
1091 return;
1092 }1092 }
10931093
1094 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);1094 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
10951095
1096 const new_indent = indent + indent_delta;1096 const new_indent = indent + indent_delta;
10971097
1098 try renderToken(tree, stream, rparen, indent, Space.Space); // )1098 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1099 try renderToken(tree, stream, lbrace, new_indent, Space.Newline); // {1099 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); // {
11001100
1101 var it = switch_node.cases.iterator(0);1101 var it = switch_node.cases.iterator(0);
1102 while (it.next()) |node| {1102 while (it.next()) |node| {
1103 try stream.writeByteNTimes(' ', new_indent);1103 try stream.writeByteNTimes(' ', new_indent);
1104 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Comma);1104 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.Comma);
11051105
1106 if (it.peek()) |next_node| {1106 if (it.peek()) |next_node| {
1107 try renderExtraNewline(tree, stream, next_node.*);1107 try renderExtraNewline(tree, stream, start_col, next_node.*);
1108 }1108 }
1109 }1109 }
11101110
1111 try stream.writeByteNTimes(' ', indent);1111 try stream.writeByteNTimes(' ', indent);
1112 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }1112 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
1113 },1113 },
11141114
1115 ast.Node.Id.SwitchCase => {1115 ast.Node.Id.SwitchCase => {
...@@ -1126,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1126,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1126 var it = switch_case.items.iterator(0);1126 var it = switch_case.items.iterator(0);
1127 while (it.next()) |node| {1127 while (it.next()) |node| {
1128 if (it.peek()) |next_node| {1128 if (it.peek()) |next_node| {
1129 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);1129 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
11301130
1131 const comma_token = tree.nextToken(node.*.lastToken());1131 const comma_token = tree.nextToken(node.*.lastToken());
1132 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,1132 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
1133 try renderExtraNewline(tree, stream, next_node.*);1133 try renderExtraNewline(tree, stream, start_col, next_node.*);
1134 } else {1134 } else {
1135 try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);1135 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
1136 }1136 }
1137 }1137 }
1138 } else {1138 } else {
...@@ -1140,85 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1140,85 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1140 while (true) {1140 while (true) {
1141 const node = ??it.next();1141 const node = ??it.next();
1142 if (it.peek()) |next_node| {1142 if (it.peek()) |next_node| {
1143 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);1143 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.None);
11441144
1145 const comma_token = tree.nextToken(node.*.lastToken());1145 const comma_token = tree.nextToken(node.*.lastToken());
1146 try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,1146 try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // ,
1147 try renderExtraNewline(tree, stream, next_node.*);1147 try renderExtraNewline(tree, stream, start_col, next_node.*);
1148 try stream.writeByteNTimes(' ', indent);1148 try stream.writeByteNTimes(' ', indent);
1149 } else {1149 } else {
1150 try renderExpression(allocator, stream, tree, indent, node.*, Space.Comma);1150 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);
1151 try stream.writeByteNTimes(' ', indent);1151 try stream.writeByteNTimes(' ', indent);
1152 break;1152 break;
1153 }1153 }
1154 }1154 }
1155 }1155 }
11561156
1157 try renderToken(tree, stream, switch_case.arrow_token, indent, Space.Space); // =>1157 try renderToken(tree, stream, switch_case.arrow_token, indent, start_col, Space.Space); // =>
11581158
1159 if (switch_case.payload) |payload| {1159 if (switch_case.payload) |payload| {
1160 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1160 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1161 }1161 }
11621162
1163 try renderExpression(allocator, stream, tree, indent, switch_case.expr, space);1163 return renderExpression(allocator, stream, tree, indent, start_col, switch_case.expr, space);
1164 },1164 },
1165 ast.Node.Id.SwitchElse => {1165 ast.Node.Id.SwitchElse => {
1166 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);1166 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
1167 try renderToken(tree, stream, switch_else.token, indent, space);1167 return renderToken(tree, stream, switch_else.token, indent, start_col, space);
1168 },1168 },
1169 ast.Node.Id.Else => {1169 ast.Node.Id.Else => {
1170 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);1170 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
11711171
1172 const block_body = switch (else_node.body.id) {1172 const body_is_block = nodeIsBlock(else_node.body);
1173 ast.Node.Id.Block,1173 const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
1174 ast.Node.Id.If,
1175 ast.Node.Id.For,
1176 ast.Node.Id.While,
1177 ast.Node.Id.Switch => true,
1178 else => false,
1179 };
11801174
1181 const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline;1175 const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1182 try renderToken(tree, stream, else_node.else_token, indent, after_else_space);1176 try renderToken(tree, stream, else_node.else_token, indent, start_col, after_else_space);
11831177
1184 if (else_node.payload) |payload| {1178 if (else_node.payload) |payload| {
1185 const payload_space = if (block_body) Space.Space else Space.Newline;1179 const payload_space = if (same_line) Space.Space else Space.Newline;
1186 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1180 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
1187 }1181 }
11881182
1189 if (block_body) {1183 if (same_line) {
1190 try renderExpression(allocator, stream, tree, indent, else_node.body, space);1184 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
1191 } else {
1192 try stream.writeByteNTimes(' ', indent + indent_delta);
1193 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1194 }1185 }
1186
1187 try stream.writeByteNTimes(' ', indent + indent_delta);
1188 start_col.* = indent + indent_delta;
1189 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
1195 },1190 },
11961191
1197 ast.Node.Id.While => {1192 ast.Node.Id.While => {
1198 const while_node = @fieldParentPtr(ast.Node.While, "base", base);1193 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
11991194
1200 if (while_node.label) |label| {1195 if (while_node.label) |label| {
1201 try renderToken(tree, stream, label, indent, Space.None); // label1196 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1202 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :1197 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
1203 }1198 }
12041199
1205 if (while_node.inline_token) |inline_token| {1200 if (while_node.inline_token) |inline_token| {
1206 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline1201 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
1207 }1202 }
12081203
1209 try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while1204 try renderToken(tree, stream, while_node.while_token, indent, start_col, Space.Space); // while
1210 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // (1205 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, start_col, Space.None); // (
1211 try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None);1206 try renderExpression(allocator, stream, tree, indent, start_col, while_node.condition, Space.None);
1207
1208 const cond_rparen = tree.nextToken(while_node.condition.lastToken());
1209
1210 const body_is_block = nodeIsBlock(while_node.body);
1211
1212 var block_start_space: Space = undefined;
1213 var after_body_space: Space = undefined;
1214
1215 if (body_is_block) {
1216 block_start_space = Space.BlockStart;
1217 after_body_space = if (while_node.@"else" == null) space else Space.SpaceOrOutdent;
1218 } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
1219 block_start_space = Space.Space;
1220 after_body_space = if (while_node.@"else" == null) space else Space.Space;
1221 } else {
1222 block_start_space = Space.Newline;
1223 after_body_space = if (while_node.@"else" == null) space else Space.Newline;
1224 }
12121225
1213 {1226 {
1214 const rparen = tree.nextToken(while_node.condition.lastToken());1227 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1215 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or1228 try renderToken(tree, stream, cond_rparen, indent, start_col, rparen_space); // )
1216 while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1217 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1218 }1229 }
12191230
1220 if (while_node.payload) |payload| {1231 if (while_node.payload) |payload| {
1221 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1232 const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
1233 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
1222 }1234 }
12231235
1224 if (while_node.continue_expr) |continue_expr| {1236 if (while_node.continue_expr) |continue_expr| {
...@@ -1226,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1226,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1226 const lparen = tree.prevToken(continue_expr.firstToken());1238 const lparen = tree.prevToken(continue_expr.firstToken());
1227 const colon = tree.prevToken(lparen);1239 const colon = tree.prevToken(lparen);
12281240
1229 try renderToken(tree, stream, colon, indent, Space.Space); // :1241 try renderToken(tree, stream, colon, indent, start_col, Space.Space); // :
1230 try renderToken(tree, stream, lparen, indent, Space.None); // (1242 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
12311243
1232 try renderExpression(allocator, stream, tree, indent, continue_expr, Space.None);1244 try renderExpression(allocator, stream, tree, indent, start_col, continue_expr, Space.None);
12331245
1234 const rparen_space = if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1246 try renderToken(tree, stream, rparen, indent, start_col, block_start_space); // )
1235 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1236 }1247 }
12371248
1238 const body_space = blk: {1249 var new_indent = indent;
1239 if (while_node.@"else" != null) {1250 if (block_start_space == Space.Newline) {
1240 break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1251 new_indent += indent_delta;
1241 } else {1252 try stream.writeByteNTimes(' ', new_indent);
1242 break :blk space;1253 start_col.* = new_indent;
1243 }
1244 };
1245
1246 if (while_node.body.id == ast.Node.Id.Block) {
1247 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1248 } else {
1249 try stream.writeByteNTimes(' ', indent + indent_delta);
1250 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1251 }1254 }
12521255
1256 try renderExpression(allocator, stream, tree, indent, start_col, while_node.body, after_body_space);
1257
1253 if (while_node.@"else") |@"else"| {1258 if (while_node.@"else") |@"else"| {
1254 if (while_node.body.id == ast.Node.Id.Block) {1259 if (after_body_space == Space.Newline) {
1255 } else {
1256 try stream.writeByteNTimes(' ', indent);1260 try stream.writeByteNTimes(' ', indent);
1261 start_col.* = indent;
1257 }1262 }
12581263 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1259 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1260 }1264 }
1261 },1265 },
12621266
...@@ -1264,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1264,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1264 const for_node = @fieldParentPtr(ast.Node.For, "base", base);1268 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
12651269
1266 if (for_node.label) |label| {1270 if (for_node.label) |label| {
1267 try renderToken(tree, stream, label, indent, Space.None); // label1271 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1268 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :1272 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
1269 }1273 }
12701274
1271 if (for_node.inline_token) |inline_token| {1275 if (for_node.inline_token) |inline_token| {
1272 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline1276 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
1273 }1277 }
12741278
1275 try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for1279 try renderToken(tree, stream, for_node.for_token, indent, start_col, Space.Space); // for
1276 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // (1280 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, start_col, Space.None); // (
1277 try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None);1281 try renderExpression(allocator, stream, tree, indent, start_col, for_node.array_expr, Space.None);
12781282
1279 const rparen = tree.nextToken(for_node.array_expr.lastToken());1283 const rparen = tree.nextToken(for_node.array_expr.lastToken());
1280 const rparen_space = if (for_node.payload != null or1284 const rparen_space = if (for_node.payload != null or
1281 for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1285 for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1282 try renderToken(tree, stream, rparen, indent, rparen_space); // )1286 try renderToken(tree, stream, rparen, indent, start_col, rparen_space); // )
12831287
1284 if (for_node.payload) |payload| {1288 if (for_node.payload) |payload| {
1285 const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1289 const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1286 try renderExpression(allocator, stream, tree, indent, payload, payload_space);1290 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
1287 }1291 }
12881292
1289 const body_space = blk: {1293 const body_space = blk: {
...@@ -1298,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1298,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1298 }1302 }
1299 };1303 };
1300 if (for_node.body.id == ast.Node.Id.Block) {1304 if (for_node.body.id == ast.Node.Id.Block) {
1301 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);1305 try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space);
1302 } else {1306 } else {
1303 try stream.writeByteNTimes(' ', indent + indent_delta);1307 try stream.writeByteNTimes(' ', indent + indent_delta);
1304 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);1308 try renderExpression(allocator, stream, tree, indent, start_col, for_node.body, body_space);
1305 }1309 }
13061310
1307 if (for_node.@"else") |@"else"| {1311 if (for_node.@"else") |@"else"| {
...@@ -1309,7 +1313,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1309,7 +1313,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1309 try stream.writeByteNTimes(' ', indent);1313 try stream.writeByteNTimes(' ', indent);
1310 }1314 }
13111315
1312 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);1316 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1313 }1317 }
1314 },1318 },
13151319
...@@ -1319,128 +1323,109 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1319,128 +1323,109 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1319 const lparen = tree.prevToken(if_node.condition.firstToken());1323 const lparen = tree.prevToken(if_node.condition.firstToken());
1320 const rparen = tree.nextToken(if_node.condition.lastToken());1324 const rparen = tree.nextToken(if_node.condition.lastToken());
13211325
1322 try renderToken(tree, stream, if_node.if_token, indent, Space.Space); // if1326 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
1323 try renderToken(tree, stream, lparen, indent, Space.None); // (1327 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
13241328
1325 try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); // condition1329 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition
13261330
1327 const body_is_block = switch (if_node.body.id) {1331 const body_is_block = nodeIsBlock(if_node.body);
1328 ast.Node.Id.Block,
1329 ast.Node.Id.If,
1330 ast.Node.Id.For,
1331 ast.Node.Id.While,
1332 ast.Node.Id.Switch,
1333 => true,
1334 else => false,
1335 };
13361332
1337 if (body_is_block) {1333 if (body_is_block) {
1338 try renderToken(tree, stream, rparen, indent, Space.Space); // )1334 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1335 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
13391336
1340 if (if_node.payload) |payload| {1337 if (if_node.payload) |payload| {
1341 try renderExpression(allocator, stream, tree, indent, payload, Space.Space); // |x|1338 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.BlockStart); // |x|
1342 }1339 }
13431340
1344 if (if_node.@"else") |@"else"| {1341 if (if_node.@"else") |@"else"| {
1345 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.SpaceOrOutdent);1342 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.SpaceOrOutdent);
1346 return renderExpression(allocator, stream, tree, indent, &@"else".base, space);1343 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1347 } else {1344 } else {
1348 return renderExpression(allocator, stream, tree, indent, if_node.body, space);1345 return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space);
1349 }1346 }
1350 }1347 }
13511348
1352 const src_has_newline = blk: {1349 const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
1353 const loc = tree.tokenLocation(tree.tokens.at(rparen).end, if_node.body.lastToken());
1354 break :blk loc.line != 0;
1355 };
13561350
1357 if (src_has_newline) {1351 if (src_has_newline) {
1358 const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;1352 const after_rparen_space = if (if_node.payload == null) Space.Newline else Space.Space;
1359 try renderToken(tree, stream, rparen, indent, after_rparen_space); // )1353 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
13601354
1361 if (if_node.payload) |payload| {1355 if (if_node.payload) |payload| {
1362 try renderExpression(allocator, stream, tree, indent, payload, Space.Newline);1356 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline);
1363 }1357 }
13641358
1365 const new_indent = indent + indent_delta;1359 const new_indent = indent + indent_delta;
1366 try stream.writeByteNTimes(' ', new_indent);1360 try stream.writeByteNTimes(' ', new_indent);
13671361
1368 if (if_node.@"else") |@"else"| {1362 if (if_node.@"else") |@"else"| {
1369 const else_is_block = switch (@"else".body.id) {1363 const else_is_block = nodeIsBlock(@"else".body);
1370 ast.Node.Id.Block,1364 try renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, Space.Newline);
1371 ast.Node.Id.If,
1372 ast.Node.Id.For,
1373 ast.Node.Id.While,
1374 ast.Node.Id.Switch,
1375 => true,
1376 else => false,
1377 };
1378 try renderExpression(allocator, stream, tree, new_indent, if_node.body, Space.Newline);
1379 try stream.writeByteNTimes(' ', indent);1365 try stream.writeByteNTimes(' ', indent);
13801366
1381 if (else_is_block) {1367 if (else_is_block) {
1382 try renderToken(tree, stream, @"else".else_token, indent, Space.Space); // else1368 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space); // else
13831369
1384 if (@"else".payload) |payload| {1370 if (@"else".payload) |payload| {
1385 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1371 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1386 }1372 }
13871373
1388 return renderExpression(allocator, stream, tree, indent, @"else".body, space);1374 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
1389 } else {1375 } else {
1390 const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;1376 const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
1391 try renderToken(tree, stream, @"else".else_token, indent, after_else_space); // else1377 try renderToken(tree, stream, @"else".else_token, indent, start_col, after_else_space); // else
13921378
1393 if (@"else".payload) |payload| {1379 if (@"else".payload) |payload| {
1394 try renderExpression(allocator, stream, tree, indent, payload, Space.Newline);1380 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Newline);
1395 }1381 }
1396 try stream.writeByteNTimes(' ', new_indent);1382 try stream.writeByteNTimes(' ', new_indent);
13971383
1398 return renderExpression(allocator, stream, tree, new_indent, @"else".body, space);1384 return renderExpression(allocator, stream, tree, new_indent, start_col, @"else".body, space);
1399 }1385 }
1400 } else {1386 } else {
1401 return renderExpression(allocator, stream, tree, new_indent, if_node.body, space);1387 return renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, space);
1402 }1388 }
1403 }1389 }
14041390
1405 try renderToken(tree, stream, rparen, indent, Space.Space); // )1391 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
14061392
1407 if (if_node.payload) |payload| {1393 if (if_node.payload) |payload| {
1408 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1394 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1409 }1395 }
14101396
1411 if (if_node.@"else") |@"else"| {1397 if (if_node.@"else") |@"else"| {
1412 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);1398 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.Space);
1413 try renderToken(tree, stream, @"else".else_token, indent, Space.Space);1399 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space);
14141400
1415 if (@"else".payload) |payload| {1401 if (@"else".payload) |payload| {
1416 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1402 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
1417 }1403 }
14181404
1419 return renderExpression(allocator, stream, tree, indent, @"else".body, space);1405 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
1420 } else {1406 } else {
1421 return renderExpression(allocator, stream, tree, indent, if_node.body, space);1407 return renderExpression(allocator, stream, tree, indent, start_col, if_node.body, space);
1422 }1408 }
1423 },1409 },
14241410
1425 ast.Node.Id.Asm => {1411 ast.Node.Id.Asm => {
1426 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);1412 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
14271413
1428 try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm1414 try renderToken(tree, stream, asm_node.asm_token, indent, start_col, Space.Space); // asm
14291415
1430 if (asm_node.volatile_token) |volatile_token| {1416 if (asm_node.volatile_token) |volatile_token| {
1431 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile1417 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
1432 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // (1418 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, start_col, Space.None); // (
1433 } else {1419 } else {
1434 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (1420 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, start_col, Space.None); // (
1435 }1421 }
14361422
1437 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {1423 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1438 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.None);1424 try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.None);
1439 try renderToken(tree, stream, asm_node.rparen, indent, space);1425 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
1440 return;
1441 }1426 }
14421427
1443 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);1428 try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.Newline);
14441429
1445 const indent_once = indent + indent_delta;1430 const indent_once = indent + indent_delta;
1446 try stream.writeByteNTimes(' ', indent_once);1431 try stream.writeByteNTimes(' ', indent_once);
...@@ -1449,12 +1434,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1449,12 +1434,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1449 const indent_extra = indent_once + 2;1434 const indent_extra = indent_once + 2;
14501435
1451 const colon2 = if (asm_node.outputs.len == 0) blk: {1436 const colon2 = if (asm_node.outputs.len == 0) blk: {
1452 try renderToken(tree, stream, colon1, indent, Space.Newline); // :1437 try renderToken(tree, stream, colon1, indent, start_col, Space.Newline); // :
1453 try stream.writeByteNTimes(' ', indent_once);1438 try stream.writeByteNTimes(' ', indent_once);
14541439
1455 break :blk tree.nextToken(colon1);1440 break :blk tree.nextToken(colon1);
1456 } else blk: {1441 } else blk: {
1457 try renderToken(tree, stream, colon1, indent, Space.Space); // :1442 try renderToken(tree, stream, colon1, indent, start_col, Space.Space); // :
14581443
1459 var it = asm_node.outputs.iterator(0);1444 var it = asm_node.outputs.iterator(0);
1460 while (true) {1445 while (true) {
...@@ -1462,21 +1447,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1462,21 +1447,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1462 const node = &(asm_output.*).base;1447 const node = &(asm_output.*).base;
14631448
1464 if (it.peek()) |next_asm_output| {1449 if (it.peek()) |next_asm_output| {
1465 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);1450 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
1466 const next_node = &(next_asm_output.*).base;1451 const next_node = &(next_asm_output.*).base;
14671452
1468 const comma = tree.prevToken(next_asm_output.*.firstToken());1453 const comma = tree.prevToken(next_asm_output.*.firstToken());
1469 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,1454 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1470 try renderExtraNewline(tree, stream, next_node);1455 try renderExtraNewline(tree, stream, start_col, next_node);
14711456
1472 try stream.writeByteNTimes(' ', indent_extra);1457 try stream.writeByteNTimes(' ', indent_extra);
1473 } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {1458 } else if (asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
1474 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);1459 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1475 try stream.writeByteNTimes(' ', indent);1460 try stream.writeByteNTimes(' ', indent);
1476 try renderToken(tree, stream, asm_node.rparen, indent, space);1461 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
1477 return;
1478 } else {1462 } else {
1479 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);1463 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1480 try stream.writeByteNTimes(' ', indent_once);1464 try stream.writeByteNTimes(' ', indent_once);
1481 const comma_or_colon = tree.nextToken(node.lastToken());1465 const comma_or_colon = tree.nextToken(node.lastToken());
1482 break :blk switch (tree.tokens.at(comma_or_colon).id) {1466 break :blk switch (tree.tokens.at(comma_or_colon).id) {
...@@ -1488,12 +1472,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1488,12 +1472,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1488 };1472 };
14891473
1490 const colon3 = if (asm_node.inputs.len == 0) blk: {1474 const colon3 = if (asm_node.inputs.len == 0) blk: {
1491 try renderToken(tree, stream, colon2, indent, Space.Newline); // :1475 try renderToken(tree, stream, colon2, indent, start_col, Space.Newline); // :
1492 try stream.writeByteNTimes(' ', indent_once);1476 try stream.writeByteNTimes(' ', indent_once);
14931477
1494 break :blk tree.nextToken(colon2);1478 break :blk tree.nextToken(colon2);
1495 } else blk: {1479 } else blk: {
1496 try renderToken(tree, stream, colon2, indent, Space.Space); // :1480 try renderToken(tree, stream, colon2, indent, start_col, Space.Space); // :
14971481
1498 var it = asm_node.inputs.iterator(0);1482 var it = asm_node.inputs.iterator(0);
1499 while (true) {1483 while (true) {
...@@ -1501,21 +1485,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1501,21 +1485,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1501 const node = &(asm_input.*).base;1485 const node = &(asm_input.*).base;
15021486
1503 if (it.peek()) |next_asm_input| {1487 if (it.peek()) |next_asm_input| {
1504 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);1488 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
1505 const next_node = &(next_asm_input.*).base;1489 const next_node = &(next_asm_input.*).base;
15061490
1507 const comma = tree.prevToken(next_asm_input.*.firstToken());1491 const comma = tree.prevToken(next_asm_input.*.firstToken());
1508 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,1492 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1509 try renderExtraNewline(tree, stream, next_node);1493 try renderExtraNewline(tree, stream, start_col, next_node);
15101494
1511 try stream.writeByteNTimes(' ', indent_extra);1495 try stream.writeByteNTimes(' ', indent_extra);
1512 } else if (asm_node.clobbers.len == 0) {1496 } else if (asm_node.clobbers.len == 0) {
1513 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);1497 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1514 try stream.writeByteNTimes(' ', indent);1498 try stream.writeByteNTimes(' ', indent);
1515 try renderToken(tree, stream, asm_node.rparen, indent, space); // )1499 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); // )
1516 return;
1517 } else {1500 } else {
1518 try renderExpression(allocator, stream, tree, indent_extra, node, Space.Newline);1501 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.Newline);
1519 try stream.writeByteNTimes(' ', indent_once);1502 try stream.writeByteNTimes(' ', indent_once);
1520 const comma_or_colon = tree.nextToken(node.lastToken());1503 const comma_or_colon = tree.nextToken(node.lastToken());
1521 break :blk switch (tree.tokens.at(comma_or_colon).id) {1504 break :blk switch (tree.tokens.at(comma_or_colon).id) {
...@@ -1526,21 +1509,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1526,21 +1509,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1526 }1509 }
1527 };1510 };
15281511
1529 try renderToken(tree, stream, colon3, indent, Space.Space); // :1512 try renderToken(tree, stream, colon3, indent, start_col, Space.Space); // :
15301513
1531 var it = asm_node.clobbers.iterator(0);1514 var it = asm_node.clobbers.iterator(0);
1532 while (true) {1515 while (true) {
1533 const clobber_token = ??it.next();1516 const clobber_token = ??it.next();
15341517
1535 if (it.peek() == null) {1518 if (it.peek() == null) {
1536 try renderToken(tree, stream, clobber_token.*, indent_once, Space.Newline);1519 try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline);
1537 try stream.writeByteNTimes(' ', indent);1520 try stream.writeByteNTimes(' ', indent);
1538 try renderToken(tree, stream, asm_node.rparen, indent, space);1521 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
1539 return;
1540 } else {1522 } else {
1541 try renderToken(tree, stream, clobber_token.*, indent_once, Space.None);1523 try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.None);
1542 const comma = tree.nextToken(clobber_token.*);1524 const comma = tree.nextToken(clobber_token.*);
1543 try renderToken(tree, stream, comma, indent_once, Space.Space); // ,1525 try renderToken(tree, stream, comma, indent_once, start_col, Space.Space); // ,
1544 }1526 }
1545 }1527 }
1546 },1528 },
...@@ -1549,34 +1531,34 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1549,34 +1531,34 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1549 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);1531 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
15501532
1551 try stream.write("[");1533 try stream.write("[");
1552 try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name, Space.None);1534 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.symbolic_name, Space.None);
1553 try stream.write("] ");1535 try stream.write("] ");
1554 try renderExpression(allocator, stream, tree, indent, asm_input.constraint, Space.None);1536 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.constraint, Space.None);
1555 try stream.write(" (");1537 try stream.write(" (");
1556 try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None);1538 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None);
1557 try renderToken(tree, stream, asm_input.lastToken(), indent, space); // )1539 return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // )
1558 },1540 },
15591541
1560 ast.Node.Id.AsmOutput => {1542 ast.Node.Id.AsmOutput => {
1561 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);1543 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
15621544
1563 try stream.write("[");1545 try stream.write("[");
1564 try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name, Space.None);1546 try renderExpression(allocator, stream, tree, indent, start_col, asm_output.symbolic_name, Space.None);
1565 try stream.write("] ");1547 try stream.write("] ");
1566 try renderExpression(allocator, stream, tree, indent, asm_output.constraint, Space.None);1548 try renderExpression(allocator, stream, tree, indent, start_col, asm_output.constraint, Space.None);
1567 try stream.write(" (");1549 try stream.write(" (");
15681550
1569 switch (asm_output.kind) {1551 switch (asm_output.kind) {
1570 ast.Node.AsmOutput.Kind.Variable => |variable_name| {1552 ast.Node.AsmOutput.Kind.Variable => |variable_name| {
1571 try renderExpression(allocator, stream, tree, indent, &variable_name.base, Space.None);1553 try renderExpression(allocator, stream, tree, indent, start_col, &variable_name.base, Space.None);
1572 },1554 },
1573 ast.Node.AsmOutput.Kind.Return => |return_type| {1555 ast.Node.AsmOutput.Kind.Return => |return_type| {
1574 try stream.write("-> ");1556 try stream.write("-> ");
1575 try renderExpression(allocator, stream, tree, indent, return_type, Space.None);1557 try renderExpression(allocator, stream, tree, indent, start_col, return_type, Space.None);
1576 },1558 },
1577 }1559 }
15781560
1579 try renderToken(tree, stream, asm_output.lastToken(), indent, space); // )1561 return renderToken(tree, stream, asm_output.lastToken(), indent, start_col, space); // )
1580 },1562 },
15811563
1582 ast.Node.Id.StructField,1564 ast.Node.Id.StructField,
...@@ -1590,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1590,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1590 }1572 }
1591}1573}
15921574
1593fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize,1575fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize,
1594 var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void1576 var_decl: &ast.Node.VarDecl,) (@typeOf(stream).Child.Error || Error)!void
1595{1577{
1596 if (var_decl.visib_token) |visib_token| {1578 if (var_decl.visib_token) |visib_token| {
1597 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub1579 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
1598 }1580 }
15991581
1600 if (var_decl.extern_export_token) |extern_export_token| {1582 if (var_decl.extern_export_token) |extern_export_token| {
1601 try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern1583 try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern
16021584
1603 if (var_decl.lib_name) |lib_name| {1585 if (var_decl.lib_name) |lib_name| {
1604 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); // "lib"1586 try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib"
1605 }1587 }
1606 }1588 }
16071589
1608 if (var_decl.comptime_token) |comptime_token| {1590 if (var_decl.comptime_token) |comptime_token| {
1609 try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime1591 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
1610 }1592 }
16111593
1612 try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var1594 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
16131595
1614 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or1596 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
1615 var_decl.init_node != null)) Space.Space else Space.None;1597 var_decl.init_node != null)) Space.Space else Space.None;
1616 try renderToken(tree, stream, var_decl.name_token, indent, name_space);1598 try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space);
16171599
1618 if (var_decl.type_node) |type_node| {1600 if (var_decl.type_node) |type_node| {
1619 try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, Space.Space);1601 try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space);
1620 const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None;1602 const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None;
1621 try renderExpression(allocator, stream, tree, indent, type_node, s);1603 try renderExpression(allocator, stream, tree, indent, start_col, type_node, s);
1622 }1604 }
16231605
1624 if (var_decl.align_node) |align_node| {1606 if (var_decl.align_node) |align_node| {
1625 const lparen = tree.prevToken(align_node.firstToken());1607 const lparen = tree.prevToken(align_node.firstToken());
1626 const align_kw = tree.prevToken(lparen);1608 const align_kw = tree.prevToken(lparen);
1627 const rparen = tree.nextToken(align_node.lastToken());1609 const rparen = tree.nextToken(align_node.lastToken());
1628 try renderToken(tree, stream, align_kw, indent, Space.None); // align1610 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1629 try renderToken(tree, stream, lparen, indent, Space.None); // (1611 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
1630 try renderExpression(allocator, stream, tree, indent, align_node, Space.None);1612 try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None);
1631 const s = if (var_decl.init_node != null) Space.Space else Space.None;1613 const s = if (var_decl.init_node != null) Space.Space else Space.None;
1632 try renderToken(tree, stream, rparen, indent, s); // )1614 try renderToken(tree, stream, rparen, indent, start_col, s); // )
1633 }1615 }
16341616
1635 if (var_decl.init_node) |init_node| {1617 if (var_decl.init_node) |init_node| {
1636 const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space;1618 const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space;
1637 try renderToken(tree, stream, var_decl.eq_token, indent, s); // =1619 try renderToken(tree, stream, var_decl.eq_token, indent, start_col, s); // =
1638 try renderExpression(allocator, stream, tree, indent, init_node, Space.None);1620 try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None);
1639 }1621 }
16401622
1641 try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline);1623 try renderToken(tree, stream, var_decl.semicolon_token, indent, start_col, Space.Newline);
1642}1624}
16431625
1644fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void {1626fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node, space: Space,) (@typeOf(stream).Child.Error || Error)!void {
1645 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);1627 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
16461628
1647 if (param_decl.comptime_token) |comptime_token| {1629 if (param_decl.comptime_token) |comptime_token| {
1648 try renderToken(tree, stream, comptime_token, indent, Space.Space);1630 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space);
1649 }1631 }
1650 if (param_decl.noalias_token) |noalias_token| {1632 if (param_decl.noalias_token) |noalias_token| {
1651 try renderToken(tree, stream, noalias_token, indent, Space.Space);1633 try renderToken(tree, stream, noalias_token, indent, start_col, Space.Space);
1652 }1634 }
1653 if (param_decl.name_token) |name_token| {1635 if (param_decl.name_token) |name_token| {
1654 try renderToken(tree, stream, name_token, indent, Space.None);1636 try renderToken(tree, stream, name_token, indent, start_col, Space.None);
1655 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // :1637 try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // :
1656 }1638 }
1657 if (param_decl.var_args_token) |var_args_token| {1639 if (param_decl.var_args_token) |var_args_token| {
1658 try renderToken(tree, stream, var_args_token, indent, space);1640 try renderToken(tree, stream, var_args_token, indent, start_col, space);
1659 } else {1641 } else {
1660 try renderExpression(allocator, stream, tree, indent, param_decl.type_node, space);1642 try renderExpression(allocator, stream, tree, indent, start_col, param_decl.type_node, space);
1661 }1643 }
1662}1644}
16631645
1664fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {1646fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize, base: &ast.Node,) (@typeOf(stream).Child.Error || Error)!void {
1665 switch (base.id) {1647 switch (base.id) {
1666 ast.Node.Id.VarDecl => {1648 ast.Node.Id.VarDecl => {
1667 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);1649 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
1668 try renderVarDecl(allocator, stream, tree, indent, var_decl);1650 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
1669 },1651 },
1670 else => {1652 else => {
1671 if (base.requireSemiColon()) {1653 if (base.requireSemiColon()) {
1672 try renderExpression(allocator, stream, tree, indent, base, Space.None);1654 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.None);
16731655
1674 const semicolon_index = tree.nextToken(base.lastToken());1656 const semicolon_index = tree.nextToken(base.lastToken());
1675 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);1657 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);
1676 try renderToken(tree, stream, semicolon_index, indent, Space.Newline);1658 try renderToken(tree, stream, semicolon_index, indent, start_col, Space.Newline);
1677 } else {1659 } else {
1678 try renderExpression(allocator, stream, tree, indent, base, Space.Newline);1660 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.Newline);
1679 }1661 }
1680 },1662 },
1681 }1663 }
...@@ -1689,32 +1671,44 @@ const Space = enum {...@@ -1689,32 +1671,44 @@ const Space = enum {
1689 SpaceOrOutdent,1671 SpaceOrOutdent,
1690 NoNewline,1672 NoNewline,
1691 NoComment,1673 NoComment,
1674 BlockStart,
1692};1675};
16931676
1694fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {1677fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, start_col: &usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {
1678 if (space == Space.BlockStart) {
1679 if (start_col.* < indent + indent_delta)
1680 return renderToken(tree, stream, token_index, indent, start_col, Space.Space);
1681 try renderToken(tree, stream, token_index, indent, start_col, Space.Newline);
1682 try stream.writeByteNTimes(' ', indent);
1683 start_col.* = indent;
1684 return;
1685 }
1686
1695 var token = tree.tokens.at(token_index);1687 var token = tree.tokens.at(token_index);
1696 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " "));1688 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
16971689
1690 if (space == Space.NoComment)
1691 return;
1692
1698 var next_token = tree.tokens.at(token_index + 1);1693 var next_token = tree.tokens.at(token_index + 1);
16991694
1700 switch (space) {1695 if (space == Space.Comma) switch (next_token.id) {
1701 Space.NoComment => return,1696 Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline),
1702 Space.Comma => switch (next_token.id) {1697 Token.Id.LineComment => {
1703 Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, Space.Newline),1698 try stream.write(", ");
1704 Token.Id.LineComment => {1699 return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline);
1705 try stream.write(", ");
1706 return renderToken(tree, stream, token_index + 1, indent, Space.Newline);
1707 },
1708 else => {
1709 if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) {
1710 return stream.write(",");
1711 } else {
1712 return stream.write(",\n");
1713 }
1714 },
1715 },1700 },
1716 else => {},1701 else => {
1717 }1702 if (tree.tokens.at(token_index + 2).id == Token.Id.MultilineStringLiteralLine) {
1703 try stream.write(",");
1704 return;
1705 } else {
1706 try stream.write(",\n");
1707 start_col.* = 0;
1708 return;
1709 }
1710 },
1711 };
17181712
1719 // Skip over same line doc comments1713 // Skip over same line doc comments
1720 var offset: usize = 1;1714 var offset: usize = 1;
...@@ -1733,18 +1727,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1733,18 +1727,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1733 if (next_token.id == Token.Id.MultilineStringLiteralLine) {1727 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1734 return;1728 return;
1735 } else {1729 } else {
1736 return stream.write("\n");1730 try stream.write("\n");
1731 start_col.* = 0;
1732 return;
1737 }1733 }
1738 },1734 },
1739 Space.Space, Space.SpaceOrOutdent => return stream.writeByte(' '),1735 Space.Space, Space.SpaceOrOutdent => {
1740 Space.NoComment, Space.Comma => unreachable,1736 try stream.writeByte(' ');
1737 return;
1738 },
1739 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1741 }1740 }
1742 }1741 }
17431742
1744 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;1743 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1745 if (comment_is_empty) {1744 if (comment_is_empty) {
1746 switch (space) {1745 switch (space) {
1747 Space.Newline => return stream.writeByte('\n'),1746 Space.Newline => {
1747 try stream.writeByte('\n');
1748 start_col.* = 0;
1749 return;
1750 },
1748 else => {},1751 else => {},
1749 }1752 }
1750 }1753 }
...@@ -1765,20 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1765,20 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1765 else => indent + indent_delta,1768 else => indent + indent_delta,
1766 };1769 };
1767 try stream.writeByteNTimes(' ', next_line_indent);1770 try stream.writeByteNTimes(' ', next_line_indent);
1771 start_col.* = next_line_indent;
1768 },1772 },
1769 Space.SpaceOrOutdent => {1773 Space.SpaceOrOutdent => {
1770 try stream.writeByte('\n');1774 try stream.writeByte('\n');
1771 try stream.writeByteNTimes(' ', indent);1775 try stream.writeByteNTimes(' ', indent);
1776 start_col.* = indent;
1772 },1777 },
1773 Space.Newline => {1778 Space.Newline => {
1774 if (next_token.id == Token.Id.MultilineStringLiteralLine) {1779 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1775 return;1780 return;
1776 } else {1781 } else {
1777 return stream.write("\n");1782 try stream.write("\n");
1783 start_col.* = 0;
1784 return;
1778 }1785 }
1779 },1786 },
1780 Space.NoNewline => {},1787 Space.NoNewline => {},
1781 Space.NoComment, Space.Comma => unreachable,1788 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1782 }1789 }
1783 return;1790 return;
1784 }1791 }
...@@ -1801,7 +1808,9 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1801,7 +1808,9 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1801 if (next_token.id == Token.Id.MultilineStringLiteralLine) {1808 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1802 return;1809 return;
1803 } else {1810 } else {
1804 return stream.write("\n");1811 try stream.write("\n");
1812 start_col.* = 0;
1813 return;
1805 }1814 }
1806 },1815 },
1807 Space.None, Space.Space => {1816 Space.None, Space.Space => {
...@@ -1813,13 +1822,15 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1813,13 +1822,15 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1813 else => indent,1822 else => indent,
1814 };1823 };
1815 try stream.writeByteNTimes(' ', next_line_indent);1824 try stream.writeByteNTimes(' ', next_line_indent);
1825 start_col.* = next_line_indent;
1816 },1826 },
1817 Space.SpaceOrOutdent => {1827 Space.SpaceOrOutdent => {
1818 try stream.writeByte('\n');1828 try stream.writeByte('\n');
1819 try stream.writeByteNTimes(' ', indent);1829 try stream.writeByteNTimes(' ', indent);
1830 start_col.* = indent;
1820 },1831 },
1821 Space.NoNewline => {},1832 Space.NoNewline => {},
1822 Space.NoComment, Space.Comma => unreachable,1833 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1823 }1834 }
1824 return;1835 return;
1825 }1836 }
...@@ -1827,18 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1827,18 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1827 }1838 }
1828}1839}
18291840
1830fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void {1841fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize, start_col: &usize,) (@typeOf(stream).Child.Error || Error)!void {
1831 const comment = node.doc_comments ?? return;1842 const comment = node.doc_comments ?? return;
1832 var it = comment.lines.iterator(0);1843 var it = comment.lines.iterator(0);
1833 const first_token = node.firstToken();1844 const first_token = node.firstToken();
1834 while (it.next()) |line_token_index| {1845 while (it.next()) |line_token_index| {
1835 if (line_token_index.* < first_token) {1846 if (line_token_index.* < first_token) {
1836 try renderToken(tree, stream, line_token_index.*, indent, Space.Newline);1847 try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline);
1837 try stream.writeByteNTimes(' ', indent);1848 try stream.writeByteNTimes(' ', indent);
1838 } else {1849 } else {
1839 try renderToken(tree, stream, line_token_index.*, indent, Space.NoComment);1850 try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.NoComment);
1840 try stream.write("\n");1851 try stream.write("\n");
1841 try stream.writeByteNTimes(' ', indent);1852 try stream.writeByteNTimes(' ', indent);
1842 }1853 }
1843 }1854 }
1844}1855}
1856
1857fn nodeIsBlock(base: &const ast.Node) bool {
1858 return switch (base.id) {
1859 ast.Node.Id.Block,
1860 ast.Node.Id.If,
1861 ast.Node.Id.For,
1862 ast.Node.Id.While,
1863 ast.Node.Id.Switch,
1864 => true,
1865 else => false,
1866 };
1867}