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 {
6868 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));
6969 }
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
7179 pub fn dump(self: &Tree) void {
7280 self.root_node.base.dump(0);
7381 }
......@@ -1529,14 +1537,14 @@ pub const Node = struct {
15291537
15301538 switch (self.op) {
15311539 Op.SliceType => |addr_of_info| {
1532 if (addr_of_info.align_expr) |align_expr| {
1533 if (i < 1) return align_expr;
1540 if (addr_of_info.align_info) |align_info| {
1541 if (i < 1) return align_info.node;
15341542 i -= 1;
15351543 }
15361544 },
15371545 Op.AddrOf => |addr_of_info| {
1538 if (addr_of_info.align_expr) |align_expr| {
1539 if (i < 1) return align_expr;
1546 if (addr_of_info.align_info) |align_info| {
1547 if (i < 1) return align_info.node;
15401548 i -= 1;
15411549 }
15421550 },
......@@ -1553,7 +1561,9 @@ pub const Node = struct {
15531561 Op.NegationWrap,
15541562 Op.Try,
15551563 Op.Resume,
1556 Op.UnwrapMaybe => {},
1564 Op.UnwrapMaybe,
1565 Op.PointerType,
1566 => {},
15571567 }
15581568
15591569 if (i < 1) return self.rhs;
......@@ -1656,6 +1666,7 @@ pub const Node = struct {
16561666 if (i < fields.len) return fields.at(i).*;
16571667 i -= fields.len;
16581668 },
1669 Op.Deref => {},
16591670 }
16601671
16611672 return null;
......@@ -2082,9 +2093,6 @@ pub const Node = struct {
20822093 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;
20832094 i -= self.inputs.len;
20842095
2085 if (i < self.clobbers.len) return self.clobbers.at(index).*;
2086 i -= self.clobbers.len;
2087
20882096 return null;
20892097 }
20902098
std/zig/parser_test.zig+92
......@@ -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
193test "zig fmt: same-line doc comment on variable declaration" {
294 try testTransform(
395 \\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(
2828 }
2929 }
3030
31
31 var start_col: usize = 0;
3232 var it = tree.root_node.decls.iterator(0);
3333 while (it.next()) |decl| {
34 try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);
34 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
3535 if (it.peek()) |next_decl| {
36 try renderExtraNewline(tree, stream, next_decl.*);
36 try renderExtraNewline(tree, stream, &start_col, next_decl.*);
3737 }
3838 }
3939}
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 {
4242 const first_token = node.firstToken();
4343 var prev_token = first_token;
4444 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 {
4848 const loc = tree.tokenLocation(prev_token_end, first_token);
4949 if (loc.line >= 2) {
5050 try stream.writeByte('\n');
51 start_col.* = 0;
5152 }
5253}
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 {
5556 switch (decl.id) {
5657 ast.Node.Id.FnProto => {
5758 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
6162 if (fn_proto.body_node) |body_node| {
62 try renderExpression(allocator, stream, tree, indent, decl, Space.Space);
63 try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline);
63 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space);
64 try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline);
6465 } else {
65 try renderExpression(allocator, stream, tree, indent, decl, Space.None);
66 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline);
66 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None);
67 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline);
6768 }
6869 },
6970
......@@ -71,153 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i
7172 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
7273
7374 if (use_decl.visib_token) |visib_token| {
74 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
75 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
7576 }
76 try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use
77 try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None);
78 try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ;
77 try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use
78 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);
79 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;
7980 },
8081
8182 ast.Node.Id.VarDecl => {
8283 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
8384
84 try renderDocComments(tree, stream, var_decl, indent);
85 try renderVarDecl(allocator, stream, tree, indent, var_decl);
85 try renderDocComments(tree, stream, var_decl, indent, start_col);
86 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
8687 },
8788
8889 ast.Node.Id.TestDecl => {
8990 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
9091
91 try renderDocComments(tree, stream, test_decl, indent);
92 try renderToken(tree, stream, test_decl.test_token, indent, Space.Space);
93 try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space);
94 try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline);
92 try renderDocComments(tree, stream, test_decl, indent, start_col);
93 try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space);
94 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space);
95 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);
9596 },
9697
9798 ast.Node.Id.StructField => {
9899 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);
101102 if (field.visib_token) |visib_token| {
102 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
103 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
103104 }
104 try renderToken(tree, stream, field.name_token, indent, Space.None); // name
105 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // :
106 try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.Comma); // type,
105 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
106 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
107 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type,
107108 },
108109
109110 ast.Node.Id.UnionTag => {
110111 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
114115 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,
116117 }
117118
118119 if (tag.type_expr == null) {
119 try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name
120 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
120121 } else {
121 try renderToken(tree, stream, tag.name_token, indent, Space.None); // name
122 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name
122123 }
123124
124125 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
127128 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;
129131 } else {
130 try renderExpression(allocator, stream, tree, indent, type_expr, Space.Space); // type
132 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Space); // type
131133 }
132134 }
133135
134136 const value_expr = ??tag.value_expr;
135 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // =
136 try renderExpression(allocator, stream, tree, indent, value_expr, Space.Comma); // value,
137 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // =
138 try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value,
137139 },
138140
139141 ast.Node.Id.EnumTag => {
140142 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
144146 if (tag.value) |value| {
145 try renderToken(tree, stream, tag.name_token, indent, Space.Space); // name
147 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); // =
148 try renderExpression(allocator, stream, tree, indent, value, Space.Comma);
149 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // =
150 try renderExpression(allocator, stream, tree, indent, start_col, value, Space.Comma);
149151 } else {
150 try renderToken(tree, stream, tag.name_token, indent, Space.Comma); // name
152 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name
151153 }
152154 },
153155
154156 ast.Node.Id.Comptime => {
155157 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);
157159 },
158160 else => unreachable,
159161 }
160162}
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 {
163165 switch (base.id) {
164166 ast.Node.Id.Identifier => {
165167 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);
167169 },
168170 ast.Node.Id.Block => {
169171 const block = @fieldParentPtr(ast.Node.Block, "base", base);
170172
171173 if (block.label) |label| {
172 try renderToken(tree, stream, label, indent, Space.None);
173 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
174 try renderToken(tree, stream, label, indent, start_col, Space.None);
175 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
174176 }
175177
176178 if (block.statements.len == 0) {
177 try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None);
178 try renderToken(tree, stream, block.rbrace, indent, space);
179 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
180 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
179181 } else {
180182 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
183185 var it = block.statements.iterator(0);
184186 while (it.next()) |statement| {
185187 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
188190 if (it.peek()) |next_statement| {
189 try renderExtraNewline(tree, stream, next_statement.*);
191 try renderExtraNewline(tree, stream, start_col, next_statement.*);
190192 }
191193 }
192194
193195 try stream.writeByteNTimes(' ', indent);
194 try renderToken(tree, stream, block.rbrace, indent, space);
196 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
195197 }
196198 },
197199 ast.Node.Id.Defer => {
198200 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
199201
200 try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space);
201 try renderExpression(allocator, stream, tree, indent, defer_node.expr, space);
202 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
203 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
202204 },
203205 ast.Node.Id.Comptime => {
204206 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
205207
206 try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space);
207 try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space);
208 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
209 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
208210 },
209211
210212 ast.Node.Id.AsyncAttribute => {
211213 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
212214
213215 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);
217 try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None);
218 try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space);
218 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None);
219 try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None);
220 return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space);
219221 } 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);
221223 }
222224 },
223225
......@@ -225,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
225227 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
226228
227229 if (suspend_node.label) |label| {
228 try renderToken(tree, stream, label, indent, Space.None);
229 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
230 try renderToken(tree, stream, label, indent, start_col, Space.None);
231 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
230232 }
231233
232234 if (suspend_node.payload) |payload| {
233235 if (suspend_node.body) |body| {
234 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
235 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
236 try renderExpression(allocator, stream, tree, indent, body, space);
236 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
237 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
238 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
237239 } else {
238 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
239 try renderExpression(allocator, stream, tree, indent, payload, space);
240 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
241 return renderExpression(allocator, stream, tree, indent, start_col, payload, space);
240242 }
241243 } else if (suspend_node.body) |body| {
242 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
243 try renderExpression(allocator, stream, tree, indent, body, space);
244 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
245 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
244246 } 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);
246248 }
247249 },
248250
......@@ -254,7 +256,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
254256 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
255257 else => Space.Space,
256258 };
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
259261 const after_op_space = blk: {
260262 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
262264 break :blk if (loc.line == 0) op_space else Space.Newline;
263265 };
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);
266268 if (after_op_space == Space.Newline) {
267269 try stream.writeByteNTimes(' ', indent + indent_delta);
270 start_col.* = indent + indent_delta;
268271 }
269272
270273 switch (infix_op_node.op) {
271274 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);
273276 },
274277 else => {},
275278 }
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);
278281 },
279282
280283 ast.Node.Id.PrefixOp => {
......@@ -282,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
282285
283286 switch (prefix_op_node.op) {
284287 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); // &
286289 if (addr_of_info.align_info) |align_info| {
287290 const lparen_token = tree.prevToken(align_info.node.firstToken());
288291 const align_token = tree.prevToken(lparen_token);
289292
290 try renderToken(tree, stream, align_token, indent, Space.None); // align
291 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
293 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
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
295298 if (align_info.bit_range) |bit_range| {
296299 const colon1 = tree.prevToken(bit_range.start.firstToken());
297300 const colon2 = tree.prevToken(bit_range.end.firstToken());
298301
299 try renderToken(tree, stream, colon1, indent, Space.None); // :
300 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
301 try renderToken(tree, stream, colon2, indent, Space.None); // :
302 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
302 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
303 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
304 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
305 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
303306
304307 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); // )
306309 } else {
307310 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); // )
309312 }
310313 }
311314 if (addr_of_info.const_token) |const_token| {
312 try renderToken(tree, stream, const_token, indent, Space.Space); // const
315 try renderToken(tree, stream, const_token, indent, start_col, Space.Space); // const
313316 }
314317 if (addr_of_info.volatile_token) |volatile_token| {
315 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
318 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
316319 }
317320 },
318321
319322 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
320 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
321 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
323 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
324 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
322325
323326 if (addr_of_info.align_info) |align_info| {
324327 const lparen_token = tree.prevToken(align_info.node.firstToken());
325328 const align_token = tree.prevToken(lparen_token);
326329
327 try renderToken(tree, stream, align_token, indent, Space.None); // align
328 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
330 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
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
332335 if (align_info.bit_range) |bit_range| {
333336 const colon1 = tree.prevToken(bit_range.start.firstToken());
334337 const colon2 = tree.prevToken(bit_range.end.firstToken());
335338
336 try renderToken(tree, stream, colon1, indent, Space.None); // :
337 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
338 try renderToken(tree, stream, colon2, indent, Space.None); // :
339 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
339 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
340 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
341 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
342 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
340343
341344 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); // )
343346 } else {
344347 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); // )
346349 }
347350 }
348351 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);
350353 }
351354 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);
353356 }
354357 },
355358
356359 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
357 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
358 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);
359 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ]
360 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
361 try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None);
362 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ]
360363 },
361364 ast.Node.PrefixOp.Op.BitNot,
362365 ast.Node.PrefixOp.Op.BoolNot,
......@@ -365,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
365368 ast.Node.PrefixOp.Op.UnwrapMaybe,
366369 ast.Node.PrefixOp.Op.MaybeType,
367370 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);
369372 },
370373
371374 ast.Node.PrefixOp.Op.Try,
372375 ast.Node.PrefixOp.Op.Await,
373376 ast.Node.PrefixOp.Op.Cancel,
374377 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);
376379 },
377380 }
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);
380383 },
381384
382385 ast.Node.Id.SuffixOp => {
......@@ -385,17 +388,16 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
385388 switch (suffix_op.op) {
386389 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
387390 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);
389392 }
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
393396 const lparen = tree.nextToken(suffix_op.lhs.lastToken());
394397
395398 if (call_info.params.len == 0) {
396 try renderToken(tree, stream, lparen, indent, Space.None);
397 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
398 return;
399 try renderToken(tree, stream, lparen, indent, start_col, Space.None);
400 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
399401 }
400402
401403 const src_has_trailing_comma = blk: {
......@@ -405,7 +407,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
405407
406408 if (src_has_trailing_comma) {
407409 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
410412 var it = call_info.params.iterator(0);
411413 while (true) {
......@@ -419,72 +421,70 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
419421 };
420422
421423 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);
423425 const comma = tree.nextToken(param_node.*.lastToken());
424 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
425 try renderExtraNewline(tree, stream, next_node.*);
426 try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
427 try renderExtraNewline(tree, stream, start_col, next_node.*);
426428 } 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);
428430 try stream.writeByteNTimes(' ', indent);
429 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
430 return;
431 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
431432 }
432433 }
433434 }
434435
435 try renderToken(tree, stream, lparen, indent, Space.None); // (
436 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
436437
437438 var it = call_info.params.iterator(0);
438439 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
441442 if (it.peek() != null) {
442443 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);
444445 }
445446 }
446 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
447 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
447448 },
448449
449450 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
450451 const lbracket = tree.prevToken(index_expr.firstToken());
451452 const rbracket = tree.nextToken(index_expr.lastToken());
452453
453 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
454 try renderToken(tree, stream, lbracket, indent, Space.None); // [
455 try renderExpression(allocator, stream, tree, indent, index_expr, Space.None);
456 try renderToken(tree, stream, rbracket, indent, space); // ]
454 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
455 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
456 try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None);
457 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
457458 },
458459
459460 ast.Node.SuffixOp.Op.Deref => {
460 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
461 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // .
462 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // *
461 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
462 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
463 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // *
463464 },
464465
465466 @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
468469 const lbracket = tree.prevToken(range.start.firstToken());
469470 const dotdot = tree.nextToken(range.start.lastToken());
470471
471 try renderToken(tree, stream, lbracket, indent, Space.None); // [
472 try renderExpression(allocator, stream, tree, indent, range.start, Space.None);
473 try renderToken(tree, stream, dotdot, indent, Space.None); // ..
472 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
473 try renderExpression(allocator, stream, tree, indent, start_col, range.start, Space.None);
474 try renderToken(tree, stream, dotdot, indent, start_col, Space.None); // ..
474475 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);
476477 }
477 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ]
478 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
478479 },
479480
480481 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
481482 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
482483
483484 if (field_inits.len == 0) {
484 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
485 try renderToken(tree, stream, lbrace, indent, Space.None);
486 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
487 return;
485 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
486 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
487 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
488488 }
489489
490490 if (field_inits.len == 1) blk: {
......@@ -496,11 +496,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
496496 }
497497 }
498498
499 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
500 try renderToken(tree, stream, lbrace, indent, Space.Space);
501 try renderExpression(allocator, stream, tree, indent, &field_init.base, Space.Space);
502 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
503 return;
499 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
500 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
501 try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
502 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
504503 }
505504
506505 const src_has_trailing_comma = blk: {
......@@ -515,27 +514,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
515514
516515 if (!src_has_trailing_comma and src_same_line) {
517516 // render all on one line, no trailing comma
518 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
519 try renderToken(tree, stream, lbrace, indent, Space.Space);
517 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
518 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
520519
521520 var it = field_inits.iterator(0);
522521 while (it.next()) |field_init| {
523522 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
526525 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);
528527 } 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);
530529 }
531530 }
532531
533 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
534 return;
532 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
535533 }
536534
537 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
538 try renderToken(tree, stream, lbrace, indent, Space.Newline);
535 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
536 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline);
539537
540538 const new_indent = indent + indent_delta;
541539
......@@ -544,41 +542,39 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
544542 try stream.writeByteNTimes(' ', new_indent);
545543
546544 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
549547 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.*);
553551 } 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);
555553 }
556554 }
557555
558556 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);
560558 },
561559
562560 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
563561 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
564562
565563 if (exprs.len == 0) {
566 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
567 try renderToken(tree, stream, lbrace, indent, Space.None);
568 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
569 return;
564 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
565 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
566 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
570567 }
571568 if (exprs.len == 1) {
572569 const expr = exprs.at(0).*;
573570
574 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
575 try renderToken(tree, stream, lbrace, indent, Space.None);
576 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
577 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
578 return;
571 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
572 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
573 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
574 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
579575 }
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
583579 // scan to find row size
584580 const maybe_row_size: ?usize = blk: {
......@@ -613,50 +609,48 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
613609
614610 if (maybe_row_size) |row_size| {
615611 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);
617613 try stream.writeByteNTimes(' ', new_indent);
618614
619615 var it = exprs.iterator(0);
620616 var i: usize = 1;
621617 while (it.next()) |expr| {
622618 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
625621 const comma = tree.nextToken(expr.*.lastToken());
626622
627623 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); // ,
629625 i += 1;
630626 continue;
631627 }
632628 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.*);
637633 try stream.writeByteNTimes(' ', new_indent);
638634 } 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); // ,
640636 }
641637 }
642638 try stream.writeByteNTimes(' ', indent);
643 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
644 return;
639 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
645640 } else {
646 try renderToken(tree, stream, lbrace, indent, Space.Space);
641 try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
647642 var it = exprs.iterator(0);
648643 while (it.next()) |expr| {
649644 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);
651646 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); // ,
653648 } else {
654 try renderExpression(allocator, stream, tree, indent, expr.*, Space.Space);
649 try renderExpression(allocator, stream, tree, indent, start_col, expr.*, Space.Space);
655650 }
656651 }
657652
658 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
659 return;
653 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
660654 }
661655 },
662656 }
......@@ -667,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
667661
668662 switch (flow_expr.kind) {
669663 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
670 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
671 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
664 if (maybe_label == null and flow_expr.rhs == null) {
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
672669 if (maybe_label) |label| {
673670 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;
677 try renderExpression(allocator, stream, tree, indent, label, expr_space);
673 if (flow_expr.rhs == null) {
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
678677 }
679678 },
680679 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
681 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
682 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
680 assert(flow_expr.rhs == null);
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
683687 if (maybe_label) |label| {
684688 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;
688 try renderExpression(allocator, stream, tree, indent, label, space);
691 return renderExpression(allocator, stream, tree, indent, start_col, label, space);
689692 }
690693 },
691694 ast.Node.ControlFlowExpression.Kind.Return => {
692 const kw_space = if (flow_expr.rhs != null) Space.Space else space;
693 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
695 if (flow_expr.rhs == null) {
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);
694699 },
695700 }
696701
697 if (flow_expr.rhs) |rhs| {
698 try renderExpression(allocator, stream, tree, indent, rhs, space);
699 }
702 return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space);
700703 },
701704
702705 ast.Node.Id.Payload => {
703706 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
704707
705 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
706 try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None);
707 try renderToken(tree, stream, payload.rpipe, indent, space);
708 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
709 try renderExpression(allocator, stream, tree, indent, start_col, payload.error_symbol, Space.None);
710 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
708711 },
709712
710713 ast.Node.Id.PointerPayload => {
711714 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);
714717 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);
716719 }
717 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);
718 try renderToken(tree, stream, payload.rpipe, indent, space);
720 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
721 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
719722 },
720723
721724 ast.Node.Id.PointerIndexPayload => {
722725 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);
725728 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);
727730 }
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
730733 if (payload.index_symbol) |index_symbol| {
731734 const comma = tree.nextToken(payload.value_symbol.lastToken());
732735
733 try renderToken(tree, stream, comma, indent, Space.Space);
734 try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None);
736 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
737 try renderExpression(allocator, stream, tree, indent, start_col, index_symbol, Space.None);
735738 }
736739
737 try renderToken(tree, stream, payload.rpipe, indent, space);
740 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
738741 },
739742
740743 ast.Node.Id.GroupedExpression => {
741744 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
742745
743 try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None);
744 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None);
745 try renderToken(tree, stream, grouped_expr.rparen, indent, space);
746 try renderToken(tree, stream, grouped_expr.lparen, indent, start_col, Space.None);
747 try renderExpression(allocator, stream, tree, indent, start_col, grouped_expr.expr, Space.None);
748 return renderToken(tree, stream, grouped_expr.rparen, indent, start_col, space);
746749 },
747750
748751 ast.Node.Id.FieldInitializer => {
749752 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
750753
751 try renderToken(tree, stream, field_init.period_token, indent, Space.None); // .
752 try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name
753 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // =
754 try renderExpression(allocator, stream, tree, indent, field_init.expr, space);
754 try renderToken(tree, stream, field_init.period_token, indent, start_col, Space.None); // .
755 try renderToken(tree, stream, field_init.name_token, indent, start_col, Space.Space); // name
756 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, start_col, Space.Space); // =
757 return renderExpression(allocator, stream, tree, indent, start_col, field_init.expr, space);
755758 },
756759
757760 ast.Node.Id.IntegerLiteral => {
758761 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);
760763 },
761764 ast.Node.Id.FloatLiteral => {
762765 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);
764767 },
765768 ast.Node.Id.StringLiteral => {
766769 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);
768771 },
769772 ast.Node.Id.CharLiteral => {
770773 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);
772775 },
773776 ast.Node.Id.BoolLiteral => {
774777 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);
776779 },
777780 ast.Node.Id.NullLiteral => {
778781 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);
780783 },
781784 ast.Node.Id.ThisLiteral => {
782785 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);
784787 },
785788 ast.Node.Id.Unreachable => {
786789 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);
788791 },
789792 ast.Node.Id.ErrorType => {
790793 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);
792795 },
793796 ast.Node.Id.VarType => {
794797 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);
796799 },
797800 ast.Node.Id.ContainerDecl => {
798801 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
799802
800803 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);
802805 }
803806
804807 switch (container_decl.init_arg_expr) {
805808 ast.Node.ContainerDecl.InitArg.None => {
806 try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union
809 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
807810 },
808811 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
809 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
812 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
810813
811814 const lparen = tree.nextToken(container_decl.kind_token);
812815 const enum_token = tree.nextToken(lparen);
813816
814 try renderToken(tree, stream, lparen, indent, Space.None); // (
815 try renderToken(tree, stream, enum_token, indent, Space.None); // enum
817 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
818 try renderToken(tree, stream, enum_token, indent, start_col, Space.None); // enum
816819
817820 if (enum_tag_type) |expr| {
818 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // (
819 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
821 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.None); // (
822 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
820823
821824 const rparen = tree.nextToken(expr.lastToken());
822 try renderToken(tree, stream, rparen, indent, Space.None); // )
823 try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // )
825 try renderToken(tree, stream, rparen, indent, start_col, Space.None); // )
826 try renderToken(tree, stream, tree.nextToken(rparen), indent, start_col, Space.Space); // )
824827 } 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); // )
826829 }
827830 },
828831 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
829 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
832 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
830833
831834 const lparen = tree.nextToken(container_decl.kind_token);
832835 const rparen = tree.nextToken(type_expr.lastToken());
833836
834 try renderToken(tree, stream, lparen, indent, Space.None); // (
835 try renderExpression(allocator, stream, tree, indent, type_expr, Space.None);
836 try renderToken(tree, stream, rparen, indent, Space.Space); // )
837 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
838 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.None);
839 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
837840 },
838841 }
839842
840843 if (container_decl.fields_and_decls.len == 0) {
841 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // {
842 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }
844 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {
845 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
843846 } else {
844847 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
847850 var it = container_decl.fields_and_decls.iterator(0);
848851 while (it.next()) |decl| {
849852 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
852855 if (it.peek()) |next_decl| {
853 try renderExtraNewline(tree, stream, next_decl.*);
856 try renderExtraNewline(tree, stream, start_col, next_decl.*);
854857 }
855858 }
856859
857860 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); // }
859862 }
860863 },
861864
......@@ -865,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
865868 const lbrace = tree.nextToken(err_set_decl.error_token);
866869
867870 if (err_set_decl.decls.len == 0) {
868 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None);
869 try renderToken(tree, stream, lbrace, indent, Space.None);
870 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space);
871 return;
871 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None);
872 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
873 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space);
872874 }
873875
874876 if (err_set_decl.decls.len == 1) blk: {
......@@ -882,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
882884 break :blk;
883885 }
884886
885 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
886 try renderToken(tree, stream, lbrace, indent, Space.None); // {
887 try renderExpression(allocator, stream, tree, indent, node, Space.None);
888 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }
889 return;
887 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
888 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
889 try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None);
890 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
890891 }
891892
892 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
893 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
893 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
894 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
894895 const new_indent = indent + indent_delta;
895896
896897 var it = err_set_decl.decls.iterator(0);
......@@ -898,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
898899 try stream.writeByteNTimes(' ', new_indent);
899900
900901 if (it.peek()) |next_node| {
901 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);
902 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,
902 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
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.*);
905906 } 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);
907908 }
908909 }
909910
910911 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); // }
912913 },
913914
914915 ast.Node.Id.ErrorTag => {
915916 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
916917
917 try renderDocComments(tree, stream, tag, indent);
918 try renderToken(tree, stream, tag.name_token, indent, space); // name
918 try renderDocComments(tree, stream, tag, indent, start_col);
919 return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name
919920 },
920921
921922 ast.Node.Id.MultilineStringLiteral => {
......@@ -933,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
933934 if (!skip_first_indent) {
934935 try stream.writeByteNTimes(' ', indent + indent_delta);
935936 }
936 try renderToken(tree, stream, t, indent, Space.None);
937 try renderToken(tree, stream, t, indent, start_col, Space.None);
937938 skip_first_indent = false;
938939 }
939940 try stream.writeByteNTimes(' ', indent);
940941 },
941942 ast.Node.Id.UndefinedLiteral => {
942943 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);
944945 },
945946
946947 ast.Node.Id.BuiltinCall => {
947948 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
948949
949 try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name
950 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // (
950 try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name
951 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, start_col, Space.None); // (
951952
952953 var it = builtin_call.params.iterator(0);
953954 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
956957 if (it.peek() != null) {
957958 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); // ,
959960 }
960961 }
961 try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // )
962 return renderToken(tree, stream, builtin_call.rparen_token, indent, start_col, space); // )
962963 },
963964
964965 ast.Node.Id.FnProto => {
......@@ -968,31 +969,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
968969 const visib_token = tree.tokens.at(visib_token_index);
969970 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); // pub
972 try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub
972973 }
973974
974975 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
975 try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export
976 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
976977 }
977978
978979 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);
980981 }
981982
982983 if (fn_proto.cc_token) |cc_token| {
983 try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc
984 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
984985 }
985986
986987 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);
988989 }
989990
990991 const lparen = if (fn_proto.name_token) |name_token| blk: {
991 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn
992 try renderToken(tree, stream, name_token, indent, Space.None); // name
992 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn
993 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name
993994 break :blk tree.nextToken(name_token);
994995 } else blk: {
995 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn
996 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn
996997 break :blk tree.nextToken(fn_proto.fn_token);
997998 };
998999
......@@ -1011,51 +1012,51 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
10111012 };
10121013
10131014 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
10161017 // render all on one line, no trailing comma
10171018 var it = fn_proto.params.iterator(0);
10181019 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
10211022 if (it.peek() != null) {
10221023 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); // ,
10241025 }
10251026 }
10261027 } else {
10271028 // one param per line
10281029 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
10311032 var it = fn_proto.params.iterator(0);
10321033 while (it.next()) |param_decl_node| {
10331034 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);
10351036 }
10361037 try stream.writeByteNTimes(' ', indent);
10371038 }
10381039
1039 try renderToken(tree, stream, rparen, indent, Space.Space); // )
1040 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
10401041
10411042 if (fn_proto.align_expr) |align_expr| {
10421043 const align_rparen = tree.nextToken(align_expr.lastToken());
10431044 const align_lparen = tree.prevToken(align_expr.firstToken());
10441045 const align_kw = tree.prevToken(align_lparen);
10451046
1046 try renderToken(tree, stream, align_kw, indent, Space.None); // align
1047 try renderToken(tree, stream, align_lparen, indent, Space.None); // (
1048 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
1049 try renderToken(tree, stream, align_rparen, indent, Space.Space); // )
1047 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1048 try renderToken(tree, stream, align_lparen, indent, start_col, Space.None); // (
1049 try renderExpression(allocator, stream, tree, indent, start_col, align_expr, Space.None);
1050 try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // )
10501051 }
10511052
10521053 switch (fn_proto.return_type) {
10531054 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);
10551056 },
10561057 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
1057 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // !
1058 try renderExpression(allocator, stream, tree, indent, node, space);
1058 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // !
1059 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
10591060 },
10601061 }
10611062 },
......@@ -1064,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
10641065 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
10651066
10661067 if (promise_type.result) |result| {
1067 try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise
1068 try renderToken(tree, stream, result.arrow_token, indent, Space.None); // ->
1069 try renderExpression(allocator, stream, tree, indent, result.return_type, space);
1068 try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise
1069 try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // ->
1070 return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space);
10701071 } else {
1071 try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise
1072 return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise
10721073 }
10731074 },
10741075
......@@ -1077,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
10771078 ast.Node.Id.Switch => {
10781079 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
10791080
1080 try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch
1081 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // (
1081 try renderToken(tree, stream, switch_node.switch_token, indent, start_col, Space.Space); // switch
1082 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, start_col, Space.None); // (
10821083
10831084 const rparen = tree.nextToken(switch_node.expr.lastToken());
10841085 const lbrace = tree.nextToken(rparen);
10851086
10861087 if (switch_node.cases.len == 0) {
1087 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);
1088 try renderToken(tree, stream, rparen, indent, Space.Space); // )
1089 try renderToken(tree, stream, lbrace, indent, Space.None); // {
1090 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }
1091 return;
1088 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
1089 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1090 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
1091 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
10921092 }
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
10961096 const new_indent = indent + indent_delta;
10971097
1098 try renderToken(tree, stream, rparen, indent, Space.Space); // )
1099 try renderToken(tree, stream, lbrace, new_indent, Space.Newline); // {
1098 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
1099 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); // {
11001100
11011101 var it = switch_node.cases.iterator(0);
11021102 while (it.next()) |node| {
11031103 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
11061106 if (it.peek()) |next_node| {
1107 try renderExtraNewline(tree, stream, next_node.*);
1107 try renderExtraNewline(tree, stream, start_col, next_node.*);
11081108 }
11091109 }
11101110
11111111 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); // }
11131113 },
11141114
11151115 ast.Node.Id.SwitchCase => {
......@@ -1126,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
11261126 var it = switch_case.items.iterator(0);
11271127 while (it.next()) |node| {
11281128 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
11311131 const comma_token = tree.nextToken(node.*.lastToken());
1132 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
1133 try renderExtraNewline(tree, stream, next_node.*);
1132 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
1133 try renderExtraNewline(tree, stream, start_col, next_node.*);
11341134 } else {
1135 try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);
1135 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
11361136 }
11371137 }
11381138 } else {
......@@ -1140,85 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
11401140 while (true) {
11411141 const node = ??it.next();
11421142 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
11451145 const comma_token = tree.nextToken(node.*.lastToken());
1146 try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,
1147 try renderExtraNewline(tree, stream, next_node.*);
1146 try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // ,
1147 try renderExtraNewline(tree, stream, start_col, next_node.*);
11481148 try stream.writeByteNTimes(' ', indent);
11491149 } else {
1150 try renderExpression(allocator, stream, tree, indent, node.*, Space.Comma);
1150 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Comma);
11511151 try stream.writeByteNTimes(' ', indent);
11521152 break;
11531153 }
11541154 }
11551155 }
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
11591159 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);
11611161 }
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);
11641164 },
11651165 ast.Node.Id.SwitchElse => {
11661166 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);
11681168 },
11691169 ast.Node.Id.Else => {
11701170 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
11711171
1172 const block_body = switch (else_node.body.id) {
1173 ast.Node.Id.Block,
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 };
1172 const body_is_block = nodeIsBlock(else_node.body);
1173 const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
11801174
1181 const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline;
1182 try renderToken(tree, stream, else_node.else_token, indent, after_else_space);
1175 const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1176 try renderToken(tree, stream, else_node.else_token, indent, start_col, after_else_space);
11831177
11841178 if (else_node.payload) |payload| {
1185 const payload_space = if (block_body) Space.Space else Space.Newline;
1186 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1179 const payload_space = if (same_line) Space.Space else Space.Newline;
1180 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
11871181 }
11881182
1189 if (block_body) {
1190 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1191 } else {
1192 try stream.writeByteNTimes(' ', indent + indent_delta);
1193 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1183 if (same_line) {
1184 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
11941185 }
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);
11951190 },
11961191
11971192 ast.Node.Id.While => {
11981193 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
11991194
12001195 if (while_node.label) |label| {
1201 try renderToken(tree, stream, label, indent, Space.None); // label
1202 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1196 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1197 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
12031198 }
12041199
12051200 if (while_node.inline_token) |inline_token| {
1206 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1201 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
12071202 }
12081203
1209 try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while
1210 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // (
1211 try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None);
1204 try renderToken(tree, stream, while_node.while_token, indent, start_col, Space.Space); // while
1205 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, start_col, 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
12131226 {
1214 const rparen = tree.nextToken(while_node.condition.lastToken());
1215 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or
1216 while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1217 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1227 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1228 try renderToken(tree, stream, cond_rparen, indent, start_col, rparen_space); // )
12181229 }
12191230
12201231 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);
12221234 }
12231235
12241236 if (while_node.continue_expr) |continue_expr| {
......@@ -1226,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
12261238 const lparen = tree.prevToken(continue_expr.firstToken());
12271239 const colon = tree.prevToken(lparen);
12281240
1229 try renderToken(tree, stream, colon, indent, Space.Space); // :
1230 try renderToken(tree, stream, lparen, indent, Space.None); // (
1241 try renderToken(tree, stream, colon, indent, start_col, Space.Space); // :
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;
1235 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1246 try renderToken(tree, stream, rparen, indent, start_col, block_start_space); // )
12361247 }
12371248
1238 const body_space = blk: {
1239 if (while_node.@"else" != null) {
1240 break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1241 } else {
1242 break :blk space;
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);
1249 var new_indent = indent;
1250 if (block_start_space == Space.Newline) {
1251 new_indent += indent_delta;
1252 try stream.writeByteNTimes(' ', new_indent);
1253 start_col.* = new_indent;
12511254 }
12521255
1256 try renderExpression(allocator, stream, tree, indent, start_col, while_node.body, after_body_space);
1257
12531258 if (while_node.@"else") |@"else"| {
1254 if (while_node.body.id == ast.Node.Id.Block) {
1255 } else {
1259 if (after_body_space == Space.Newline) {
12561260 try stream.writeByteNTimes(' ', indent);
1261 start_col.* = indent;
12571262 }
1258
1259 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1263 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
12601264 }
12611265 },
12621266
......@@ -1264,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
12641268 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
12651269
12661270 if (for_node.label) |label| {
1267 try renderToken(tree, stream, label, indent, Space.None); // label
1268 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1271 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1272 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
12691273 }
12701274
12711275 if (for_node.inline_token) |inline_token| {
1272 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1276 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
12731277 }
12741278
1275 try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for
1276 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // (
1277 try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None);
1279 try renderToken(tree, stream, for_node.for_token, indent, start_col, Space.Space); // for
1280 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, start_col, Space.None); // (
1281 try renderExpression(allocator, stream, tree, indent, start_col, for_node.array_expr, Space.None);
12781282
12791283 const rparen = tree.nextToken(for_node.array_expr.lastToken());
12801284 const rparen_space = if (for_node.payload != null or
12811285 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
12841288 if (for_node.payload) |payload| {
12851289 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);
12871291 }
12881292
12891293 const body_space = blk: {
......@@ -1298,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
12981302 }
12991303 };
13001304 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);
13021306 } else {
13031307 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);
13051309 }
13061310
13071311 if (for_node.@"else") |@"else"| {
......@@ -1309,7 +1313,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
13091313 try stream.writeByteNTimes(' ', indent);
13101314 }
13111315
1312 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1316 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
13131317 }
13141318 },
13151319
......@@ -1319,128 +1323,109 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
13191323 const lparen = tree.prevToken(if_node.condition.firstToken());
13201324 const rparen = tree.nextToken(if_node.condition.lastToken());
13211325
1322 try renderToken(tree, stream, if_node.if_token, indent, Space.Space); // if
1323 try renderToken(tree, stream, lparen, indent, Space.None); // (
1326 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
1327 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
13241328
1325 try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None); // condition
1329 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) {
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 };
1331 const body_is_block = nodeIsBlock(if_node.body);
13361332
13371333 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
13401337 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|
13421339 }
13431340
13441341 if (if_node.@"else") |@"else"| {
1345 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.SpaceOrOutdent);
1346 return renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1342 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.SpaceOrOutdent);
1343 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
13471344 } 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);
13491346 }
13501347 }
13511348
1352 const src_has_newline = blk: {
1353 const loc = tree.tokenLocation(tree.tokens.at(rparen).end, if_node.body.lastToken());
1354 break :blk loc.line != 0;
1355 };
1349 const src_has_newline = !tree.tokensOnSameLine(rparen, if_node.body.lastToken());
13561350
13571351 if (src_has_newline) {
13581352 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
13611355 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);
13631357 }
13641358
13651359 const new_indent = indent + indent_delta;
13661360 try stream.writeByteNTimes(' ', new_indent);
13671361
13681362 if (if_node.@"else") |@"else"| {
1369 const else_is_block = switch (@"else".body.id) {
1370 ast.Node.Id.Block,
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);
1363 const else_is_block = nodeIsBlock(@"else".body);
1364 try renderExpression(allocator, stream, tree, new_indent, start_col, if_node.body, Space.Newline);
13791365 try stream.writeByteNTimes(' ', indent);
13801366
13811367 if (else_is_block) {
1382 try renderToken(tree, stream, @"else".else_token, indent, Space.Space); // else
1368 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space); // else
13831369
13841370 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);
13861372 }
13871373
1388 return renderExpression(allocator, stream, tree, indent, @"else".body, space);
1374 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
13891375 } else {
13901376 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); // else
1377 try renderToken(tree, stream, @"else".else_token, indent, start_col, after_else_space); // else
13921378
13931379 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);
13951381 }
13961382 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);
13991385 }
14001386 } 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);
14021388 }
14031389 }
14041390
1405 try renderToken(tree, stream, rparen, indent, Space.Space); // )
1391 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
14061392
14071393 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);
14091395 }
14101396
14111397 if (if_node.@"else") |@"else"| {
1412 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);
1413 try renderToken(tree, stream, @"else".else_token, indent, Space.Space);
1398 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.Space);
1399 try renderToken(tree, stream, @"else".else_token, indent, start_col, Space.Space);
14141400
14151401 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);
14171403 }
14181404
1419 return renderExpression(allocator, stream, tree, indent, @"else".body, space);
1405 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
14201406 } 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);
14221408 }
14231409 },
14241410
14251411 ast.Node.Id.Asm => {
14261412 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
14271413
1428 try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm
1414 try renderToken(tree, stream, asm_node.asm_token, indent, start_col, Space.Space); // asm
14291415
14301416 if (asm_node.volatile_token) |volatile_token| {
1431 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
1432 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // (
1417 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
1418 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, start_col, Space.None); // (
14331419 } 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); // (
14351421 }
14361422
14371423 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);
1439 try renderToken(tree, stream, asm_node.rparen, indent, space);
1440 return;
1424 try renderExpression(allocator, stream, tree, indent, start_col, asm_node.template, Space.None);
1425 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
14411426 }
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
14451430 const indent_once = indent + indent_delta;
14461431 try stream.writeByteNTimes(' ', indent_once);
......@@ -1449,12 +1434,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
14491434 const indent_extra = indent_once + 2;
14501435
14511436 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); // :
14531438 try stream.writeByteNTimes(' ', indent_once);
14541439
14551440 break :blk tree.nextToken(colon1);
14561441 } else blk: {
1457 try renderToken(tree, stream, colon1, indent, Space.Space); // :
1442 try renderToken(tree, stream, colon1, indent, start_col, Space.Space); // :
14581443
14591444 var it = asm_node.outputs.iterator(0);
14601445 while (true) {
......@@ -1462,21 +1447,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
14621447 const node = &(asm_output.*).base;
14631448
14641449 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);
14661451 const next_node = &(next_asm_output.*).base;
14671452
14681453 const comma = tree.prevToken(next_asm_output.*.firstToken());
1469 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1470 try renderExtraNewline(tree, stream, next_node);
1454 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1455 try renderExtraNewline(tree, stream, start_col, next_node);
14711456
14721457 try stream.writeByteNTimes(' ', indent_extra);
14731458 } 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);
14751460 try stream.writeByteNTimes(' ', indent);
1476 try renderToken(tree, stream, asm_node.rparen, indent, space);
1477 return;
1461 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
14781462 } 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);
14801464 try stream.writeByteNTimes(' ', indent_once);
14811465 const comma_or_colon = tree.nextToken(node.lastToken());
14821466 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
14881472 };
14891473
14901474 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); // :
14921476 try stream.writeByteNTimes(' ', indent_once);
14931477
14941478 break :blk tree.nextToken(colon2);
14951479 } else blk: {
1496 try renderToken(tree, stream, colon2, indent, Space.Space); // :
1480 try renderToken(tree, stream, colon2, indent, start_col, Space.Space); // :
14971481
14981482 var it = asm_node.inputs.iterator(0);
14991483 while (true) {
......@@ -1501,21 +1485,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
15011485 const node = &(asm_input.*).base;
15021486
15031487 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);
15051489 const next_node = &(next_asm_input.*).base;
15061490
15071491 const comma = tree.prevToken(next_asm_input.*.firstToken());
1508 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1509 try renderExtraNewline(tree, stream, next_node);
1492 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1493 try renderExtraNewline(tree, stream, start_col, next_node);
15101494
15111495 try stream.writeByteNTimes(' ', indent_extra);
15121496 } 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);
15141498 try stream.writeByteNTimes(' ', indent);
1515 try renderToken(tree, stream, asm_node.rparen, indent, space); // )
1516 return;
1499 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space); // )
15171500 } 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);
15191502 try stream.writeByteNTimes(' ', indent_once);
15201503 const comma_or_colon = tree.nextToken(node.lastToken());
15211504 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
15261509 }
15271510 };
15281511
1529 try renderToken(tree, stream, colon3, indent, Space.Space); // :
1512 try renderToken(tree, stream, colon3, indent, start_col, Space.Space); // :
15301513
15311514 var it = asm_node.clobbers.iterator(0);
15321515 while (true) {
15331516 const clobber_token = ??it.next();
15341517
15351518 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);
15371520 try stream.writeByteNTimes(' ', indent);
1538 try renderToken(tree, stream, asm_node.rparen, indent, space);
1539 return;
1521 return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
15401522 } 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);
15421524 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); // ,
15441526 }
15451527 }
15461528 },
......@@ -1549,34 +1531,34 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
15491531 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
15501532
15511533 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);
15531535 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);
15551537 try stream.write(" (");
1556 try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None);
1557 try renderToken(tree, stream, asm_input.lastToken(), indent, space); // )
1538 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None);
1539 return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // )
15581540 },
15591541
15601542 ast.Node.Id.AsmOutput => {
15611543 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
15621544
15631545 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);
15651547 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);
15671549 try stream.write(" (");
15681550
15691551 switch (asm_output.kind) {
15701552 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);
15721554 },
15731555 ast.Node.AsmOutput.Kind.Return => |return_type| {
15741556 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);
15761558 },
15771559 }
15781560
1579 try renderToken(tree, stream, asm_output.lastToken(), indent, space); // )
1561 return renderToken(tree, stream, asm_output.lastToken(), indent, start_col, space); // )
15801562 },
15811563
15821564 ast.Node.Id.StructField,
......@@ -1590,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
15901572 }
15911573}
15921574
1593fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize,
1594 var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void
1575fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize,
1576 var_decl: &ast.Node.VarDecl,) (@typeOf(stream).Child.Error || Error)!void
15951577{
15961578 if (var_decl.visib_token) |visib_token| {
1597 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
1579 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
15981580 }
15991581
16001582 if (var_decl.extern_export_token) |extern_export_token| {
1601 try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern
1583 try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern
16021584
16031585 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"
16051587 }
16061588 }
16071589
16081590 if (var_decl.comptime_token) |comptime_token| {
1609 try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime
1591 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
16101592 }
16111593
1612 try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var
1594 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
16131595
16141596 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
16151597 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
16181600 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);
16201602 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);
16221604 }
16231605
16241606 if (var_decl.align_node) |align_node| {
16251607 const lparen = tree.prevToken(align_node.firstToken());
16261608 const align_kw = tree.prevToken(lparen);
16271609 const rparen = tree.nextToken(align_node.lastToken());
1628 try renderToken(tree, stream, align_kw, indent, Space.None); // align
1629 try renderToken(tree, stream, lparen, indent, Space.None); // (
1630 try renderExpression(allocator, stream, tree, indent, align_node, Space.None);
1610 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1611 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
1612 try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None);
16311613 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); // )
16331615 }
16341616
16351617 if (var_decl.init_node) |init_node| {
16361618 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); // =
1638 try renderExpression(allocator, stream, tree, indent, init_node, Space.None);
1619 try renderToken(tree, stream, var_decl.eq_token, indent, start_col, s); // =
1620 try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None);
16391621 }
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);
16421624}
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 {
16451627 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
16461628
16471629 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);
16491631 }
16501632 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);
16521634 }
16531635 if (param_decl.name_token) |name_token| {
1654 try renderToken(tree, stream, name_token, indent, Space.None);
1655 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // :
1636 try renderToken(tree, stream, name_token, indent, start_col, Space.None);
1637 try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // :
16561638 }
16571639 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);
16591641 } 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);
16611643 }
16621644}
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 {
16651647 switch (base.id) {
16661648 ast.Node.Id.VarDecl => {
16671649 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);
16691651 },
16701652 else => {
16711653 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
16741656 const semicolon_index = tree.nextToken(base.lastToken());
16751657 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);
16771659 } else {
1678 try renderExpression(allocator, stream, tree, indent, base, Space.Newline);
1660 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.Newline);
16791661 }
16801662 },
16811663 }
......@@ -1689,32 +1671,44 @@ const Space = enum {
16891671 SpaceOrOutdent,
16901672 NoNewline,
16911673 NoComment,
1674 BlockStart,
16921675};
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
16951687 var token = tree.tokens.at(token_index);
16961688 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
16971689
1690 if (space == Space.NoComment)
1691 return;
1692
16981693 var next_token = tree.tokens.at(token_index + 1);
16991694
1700 switch (space) {
1701 Space.NoComment => return,
1702 Space.Comma => switch (next_token.id) {
1703 Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, Space.Newline),
1704 Token.Id.LineComment => {
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 },
1695 if (space == Space.Comma) switch (next_token.id) {
1696 Token.Id.Comma => return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline),
1697 Token.Id.LineComment => {
1698 try stream.write(", ");
1699 return renderToken(tree, stream, token_index + 1, indent, start_col, Space.Newline);
17151700 },
1716 else => {},
1717 }
1701 else => {
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
17191713 // Skip over same line doc comments
17201714 var offset: usize = 1;
......@@ -1733,18 +1727,27 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
17331727 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
17341728 return;
17351729 } else {
1736 return stream.write("\n");
1730 try stream.write("\n");
1731 start_col.* = 0;
1732 return;
17371733 }
17381734 },
1739 Space.Space, Space.SpaceOrOutdent => return stream.writeByte(' '),
1740 Space.NoComment, Space.Comma => unreachable,
1735 Space.Space, Space.SpaceOrOutdent => {
1736 try stream.writeByte(' ');
1737 return;
1738 },
1739 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
17411740 }
17421741 }
17431742
17441743 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
17451744 if (comment_is_empty) {
17461745 switch (space) {
1747 Space.Newline => return stream.writeByte('\n'),
1746 Space.Newline => {
1747 try stream.writeByte('\n');
1748 start_col.* = 0;
1749 return;
1750 },
17481751 else => {},
17491752 }
17501753 }
......@@ -1765,20 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
17651768 else => indent + indent_delta,
17661769 };
17671770 try stream.writeByteNTimes(' ', next_line_indent);
1771 start_col.* = next_line_indent;
17681772 },
17691773 Space.SpaceOrOutdent => {
17701774 try stream.writeByte('\n');
17711775 try stream.writeByteNTimes(' ', indent);
1776 start_col.* = indent;
17721777 },
17731778 Space.Newline => {
17741779 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
17751780 return;
17761781 } else {
1777 return stream.write("\n");
1782 try stream.write("\n");
1783 start_col.* = 0;
1784 return;
17781785 }
17791786 },
17801787 Space.NoNewline => {},
1781 Space.NoComment, Space.Comma => unreachable,
1788 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
17821789 }
17831790 return;
17841791 }
......@@ -1801,7 +1808,9 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
18011808 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
18021809 return;
18031810 } else {
1804 return stream.write("\n");
1811 try stream.write("\n");
1812 start_col.* = 0;
1813 return;
18051814 }
18061815 },
18071816 Space.None, Space.Space => {
......@@ -1813,13 +1822,15 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
18131822 else => indent,
18141823 };
18151824 try stream.writeByteNTimes(' ', next_line_indent);
1825 start_col.* = next_line_indent;
18161826 },
18171827 Space.SpaceOrOutdent => {
18181828 try stream.writeByte('\n');
18191829 try stream.writeByteNTimes(' ', indent);
1830 start_col.* = indent;
18201831 },
18211832 Space.NoNewline => {},
1822 Space.NoComment, Space.Comma => unreachable,
1833 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
18231834 }
18241835 return;
18251836 }
......@@ -1827,18 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
18271838 }
18281839}
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 {
18311842 const comment = node.doc_comments ?? return;
18321843 var it = comment.lines.iterator(0);
18331844 const first_token = node.firstToken();
18341845 while (it.next()) |line_token_index| {
18351846 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);
18371848 try stream.writeByteNTimes(' ', indent);
18381849 } 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);
18401851 try stream.write("\n");
18411852 try stream.writeByteNTimes(' ', indent);
18421853 }
18431854 }
18441855}
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}