authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-22 21:04:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-22 21:04:22-07:00
log8379fff80455f89f9673638642cf506cb73c4241
treed75907250d996f6f679d98799931dd8888baea35
parenta6038f03753a967082487020a0b834c1c4305503

zig fmt: alignment in anonymous literal


2 files changed, 395 insertions(+), 211 deletions(-)

lib/std/zig/parser_test.zig+17-17
...@@ -540,23 +540,23 @@ test "zig fmt: anon literal in array" {...@@ -540,23 +540,23 @@ test "zig fmt: anon literal in array" {
540 );540 );
541}541}
542542
543//test "zig fmt: alignment in anonymous literal" {543test "zig fmt: alignment in anonymous literal" {
544// try testTransform(544 try testTransform(
545// \\const a = .{545 \\const a = .{
546// \\ "U", "L", "F",546 \\ "U", "L", "F",
547// \\ "U'",547 \\ "U'",
548// \\ "L'",548 \\ "L'",
549// \\ "F'",549 \\ "F'",
550// \\};550 \\};
551// \\551 \\
552// ,552 ,
553// \\const a = .{553 \\const a = .{
554// \\ "U", "L", "F",554 \\ "U", "L", "F",
555// \\ "U'", "L'", "F'",555 \\ "U'", "L'", "F'",
556// \\};556 \\};
557// \\557 \\
558// );558 );
559//}559}
560560
561test "zig fmt: anon struct literal 0 element" {561test "zig fmt: anon struct literal 0 element" {
562 try testCanonical(562 try testCanonical(
lib/std/zig/render.zig+378-194
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6const std = @import("../std.zig");6const std = @import("../std.zig");
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const mem = std.mem;8const mem = std.mem;
9const Allocator = std.mem.Allocator;
9const meta = std.meta;10const meta = std.meta;
10const ast = std.zig.ast;11const ast = std.zig.ast;
11const Token = std.zig.Token;12const Token = std.zig.Token;
...@@ -29,7 +30,7 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void {...@@ -29,7 +30,7 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void {
29 const comment_end_loc = tree.tokens.items(.start)[0];30 const comment_end_loc = tree.tokens.items(.start)[0];
30 _ = try renderComments(ais, tree, 0, comment_end_loc);31 _ = try renderComments(ais, tree, 0, comment_end_loc);
3132
32 try renderMembers(ais, tree, tree.rootDecls());33 try renderMembers(buffer.allocator, ais, tree, tree.rootDecls());
3334
34 if (ais.disabled_offset) |disabled_offset| {35 if (ais.disabled_offset) |disabled_offset| {
35 try writeFixingWhitespace(ais.underlying_writer, tree.source[disabled_offset..]);36 try writeFixingWhitespace(ais.underlying_writer, tree.source[disabled_offset..]);
...@@ -37,17 +38,17 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void {...@@ -37,17 +38,17 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void {
37}38}
3839
39/// Render all members in the given slice, keeping empty lines where appropriate40/// Render all members in the given slice, keeping empty lines where appropriate
40fn renderMembers(ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void {41fn renderMembers(gpa: *Allocator, ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void {
41 if (members.len == 0) return;42 if (members.len == 0) return;
42 //try renderExtraNewline(ais, tree, members[0]);43 //try renderExtraNewline(ais, tree, members[0]);
43 try renderMember(ais, tree, members[0], .newline);44 try renderMember(gpa, ais, tree, members[0], .newline);
44 for (members[1..]) |member| {45 for (members[1..]) |member| {
45 try renderExtraNewline(ais, tree, member);46 try renderExtraNewline(ais, tree, member);
46 try renderMember(ais, tree, member, .newline);47 try renderMember(gpa, ais, tree, member, .newline);
47 }48 }
48}49}
4950
50fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void {51fn renderMember(gpa: *Allocator, ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) Error!void {
51 const token_tags = tree.tokens.items(.tag);52 const token_tags = tree.tokens.items(.tag);
52 const main_tokens = tree.nodes.items(.main_token);53 const main_tokens = tree.nodes.items(.main_token);
53 const datas = tree.nodes.items(.data);54 const datas = tree.nodes.items(.data);
...@@ -87,8 +88,8 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E...@@ -87,8 +88,8 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
87 try renderToken(ais, tree, i, .space);88 try renderToken(ais, tree, i, .space);
88 }89 }
89 assert(datas[decl].rhs != 0);90 assert(datas[decl].rhs != 0);
90 try renderExpression(ais, tree, fn_proto, .space);91 try renderExpression(gpa, ais, tree, fn_proto, .space);
91 return renderExpression(ais, tree, datas[decl].rhs, space);92 return renderExpression(gpa, ais, tree, datas[decl].rhs, space);
92 },93 },
93 .fn_proto_simple,94 .fn_proto_simple,
94 .fn_proto_multi,95 .fn_proto_multi,
...@@ -119,7 +120,7 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E...@@ -119,7 +120,7 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
119 while (i < fn_token) : (i += 1) {120 while (i < fn_token) : (i += 1) {
120 try renderToken(ais, tree, i, .space);121 try renderToken(ais, tree, i, .space);
121 }122 }
122 try renderExpression(ais, tree, decl, .none);123 try renderExpression(gpa, ais, tree, decl, .none);
123 return renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon124 return renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon
124 },125 },
125126
...@@ -130,14 +131,14 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E...@@ -130,14 +131,14 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
130 try renderToken(ais, tree, main_token - 1, .space); // pub131 try renderToken(ais, tree, main_token - 1, .space); // pub
131 }132 }
132 try renderToken(ais, tree, main_token, .space); // usingnamespace133 try renderToken(ais, tree, main_token, .space); // usingnamespace
133 try renderExpression(ais, tree, expr, .none);134 try renderExpression(gpa, ais, tree, expr, .none);
134 return renderToken(ais, tree, tree.lastToken(expr) + 1, space); // ;135 return renderToken(ais, tree, tree.lastToken(expr) + 1, space); // ;
135 },136 },
136137
137 .global_var_decl => return renderVarDecl(ais, tree, tree.globalVarDecl(decl)),138 .global_var_decl => return renderVarDecl(gpa, ais, tree, tree.globalVarDecl(decl)),
138 .local_var_decl => return renderVarDecl(ais, tree, tree.localVarDecl(decl)),139 .local_var_decl => return renderVarDecl(gpa, ais, tree, tree.localVarDecl(decl)),
139 .simple_var_decl => return renderVarDecl(ais, tree, tree.simpleVarDecl(decl)),140 .simple_var_decl => return renderVarDecl(gpa, ais, tree, tree.simpleVarDecl(decl)),
140 .aligned_var_decl => return renderVarDecl(ais, tree, tree.alignedVarDecl(decl)),141 .aligned_var_decl => return renderVarDecl(gpa, ais, tree, tree.alignedVarDecl(decl)),
141142
142 .test_decl => {143 .test_decl => {
143 const test_token = main_tokens[decl];144 const test_token = main_tokens[decl];
...@@ -145,13 +146,13 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E...@@ -145,13 +146,13 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
145 if (token_tags[test_token + 1] == .string_literal) {146 if (token_tags[test_token + 1] == .string_literal) {
146 try renderToken(ais, tree, test_token + 1, .space);147 try renderToken(ais, tree, test_token + 1, .space);
147 }148 }
148 try renderExpression(ais, tree, datas[decl].rhs, space);149 try renderExpression(gpa, ais, tree, datas[decl].rhs, space);
149 },150 },
150151
151 .container_field_init => return renderContainerField(ais, tree, tree.containerFieldInit(decl), space),152 .container_field_init => return renderContainerField(gpa, ais, tree, tree.containerFieldInit(decl), space),
152 .container_field_align => return renderContainerField(ais, tree, tree.containerFieldAlign(decl), space),153 .container_field_align => return renderContainerField(gpa, ais, tree, tree.containerFieldAlign(decl), space),
153 .container_field => return renderContainerField(ais, tree, tree.containerField(decl), space),154 .container_field => return renderContainerField(gpa, ais, tree, tree.containerField(decl), space),
154 .@"comptime" => return renderExpression(ais, tree, decl, space),155 .@"comptime" => return renderExpression(gpa, ais, tree, decl, space),
155156
156 .root => unreachable,157 .root => unreachable,
157 else => unreachable,158 else => unreachable,
...@@ -159,16 +160,16 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E...@@ -159,16 +160,16 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E
159}160}
160161
161/// Render all expressions in the slice, keeping empty lines where appropriate162/// Render all expressions in the slice, keeping empty lines where appropriate
162fn renderExpressions(ais: *Ais, tree: ast.Tree, expressions: []const ast.Node.Index, space: Space) Error!void {163fn renderExpressions(gpa: *Allocator, ais: *Ais, tree: ast.Tree, expressions: []const ast.Node.Index, space: Space) Error!void {
163 if (expressions.len == 0) return;164 if (expressions.len == 0) return;
164 try renderExpression(ais, tree, expressions[0], space);165 try renderExpression(gpa, ais, tree, expressions[0], space);
165 for (expressions[1..]) |expression| {166 for (expressions[1..]) |expression| {
166 try renderExtraNewline(ais, tree, expression);167 try renderExtraNewline(ais, tree, expression);
167 try renderExpression(ais, tree, expression, space);168 try renderExpression(gpa, ais, tree, expression, space);
168 }169 }
169}170}
170171
171fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {172fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
172 const token_tags = tree.tokens.items(.tag);173 const token_tags = tree.tokens.items(.tag);
173 const main_tokens = tree.nodes.items(.main_token);174 const main_tokens = tree.nodes.items(.main_token);
174 const node_tags = tree.nodes.items(.tag);175 const node_tags = tree.nodes.items(.tag);
...@@ -217,18 +218,18 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -217,18 +218,18 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
217 => {218 => {
218 const statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs };219 const statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
219 if (datas[node].lhs == 0) {220 if (datas[node].lhs == 0) {
220 return renderBlock(ais, tree, node, statements[0..0], space);221 return renderBlock(gpa, ais, tree, node, statements[0..0], space);
221 } else if (datas[node].rhs == 0) {222 } else if (datas[node].rhs == 0) {
222 return renderBlock(ais, tree, node, statements[0..1], space);223 return renderBlock(gpa, ais, tree, node, statements[0..1], space);
223 } else {224 } else {
224 return renderBlock(ais, tree, node, statements[0..2], space);225 return renderBlock(gpa, ais, tree, node, statements[0..2], space);
225 }226 }
226 },227 },
227 .block,228 .block,
228 .block_semicolon,229 .block_semicolon,
229 => {230 => {
230 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];231 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];
231 return renderBlock(ais, tree, node, statements, space);232 return renderBlock(gpa, ais, tree, node, statements, space);
232 },233 },
233234
234 .@"errdefer" => {235 .@"errdefer" => {
...@@ -242,20 +243,20 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -242,20 +243,20 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
242 try renderToken(ais, tree, payload_token, .none); // identifier243 try renderToken(ais, tree, payload_token, .none); // identifier
243 try renderToken(ais, tree, payload_token + 1, .space); // |244 try renderToken(ais, tree, payload_token + 1, .space); // |
244 }245 }
245 return renderExpression(ais, tree, expr, space);246 return renderExpression(gpa, ais, tree, expr, space);
246 },247 },
247248
248 .@"defer" => {249 .@"defer" => {
249 const defer_token = main_tokens[node];250 const defer_token = main_tokens[node];
250 const expr = datas[node].rhs;251 const expr = datas[node].rhs;
251 try renderToken(ais, tree, defer_token, .space);252 try renderToken(ais, tree, defer_token, .space);
252 return renderExpression(ais, tree, expr, space);253 return renderExpression(gpa, ais, tree, expr, space);
253 },254 },
254 .@"comptime", .@"nosuspend" => {255 .@"comptime", .@"nosuspend" => {
255 const comptime_token = main_tokens[node];256 const comptime_token = main_tokens[node];
256 const block = datas[node].lhs;257 const block = datas[node].lhs;
257 try renderToken(ais, tree, comptime_token, .space);258 try renderToken(ais, tree, comptime_token, .space);
258 return renderExpression(ais, tree, block, space);259 return renderExpression(gpa, ais, tree, block, space);
259 },260 },
260261
261 .@"suspend" => {262 .@"suspend" => {
...@@ -263,7 +264,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -263,7 +264,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
263 const body = datas[node].lhs;264 const body = datas[node].lhs;
264 if (body != 0) {265 if (body != 0) {
265 try renderToken(ais, tree, suspend_token, .space);266 try renderToken(ais, tree, suspend_token, .space);
266 return renderExpression(ais, tree, body, space);267 return renderExpression(gpa, ais, tree, body, space);
267 } else {268 } else {
268 return renderToken(ais, tree, suspend_token, space);269 return renderToken(ais, tree, suspend_token, space);
269 }270 }
...@@ -276,7 +277,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -276,7 +277,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
276 const same_line = tree.tokensOnSameLine(main_token, fallback_first);277 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
277 const after_op_space = if (same_line) Space.space else Space.newline;278 const after_op_space = if (same_line) Space.space else Space.newline;
278279
279 try renderExpression(ais, tree, datas[node].lhs, .space); // target280 try renderExpression(gpa, ais, tree, datas[node].lhs, .space); // target
280281
281 if (token_tags[fallback_first - 1] == .pipe) {282 if (token_tags[fallback_first - 1] == .pipe) {
282 try renderToken(ais, tree, main_token, .space); // catch keyword283 try renderToken(ais, tree, main_token, .space); // catch keyword
...@@ -289,12 +290,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -289,12 +290,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
289 }290 }
290291
291 ais.pushIndentOneShot();292 ais.pushIndentOneShot();
292 try renderExpression(ais, tree, datas[node].rhs, space); // fallback293 try renderExpression(gpa, ais, tree, datas[node].rhs, space); // fallback
293 },294 },
294295
295 .field_access => {296 .field_access => {
296 const field_access = datas[node];297 const field_access = datas[node];
297 try renderExpression(ais, tree, field_access.lhs, .none);298 try renderExpression(gpa, ais, tree, field_access.lhs, .none);
298 try renderToken(ais, tree, main_tokens[node], .none);299 try renderToken(ais, tree, main_tokens[node], .none);
299 return renderToken(ais, tree, field_access.rhs, space);300 return renderToken(ais, tree, field_access.rhs, space);
300 },301 },
...@@ -303,9 +304,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -303,9 +304,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
303 .switch_range,304 .switch_range,
304 => {305 => {
305 const infix = datas[node];306 const infix = datas[node];
306 try renderExpression(ais, tree, infix.lhs, .none);307 try renderExpression(gpa, ais, tree, infix.lhs, .none);
307 try renderToken(ais, tree, main_tokens[node], .none);308 try renderToken(ais, tree, main_tokens[node], .none);
308 return renderExpression(ais, tree, infix.rhs, space);309 return renderExpression(gpa, ais, tree, infix.rhs, space);
309 },310 },
310311
311 .add,312 .add,
...@@ -349,7 +350,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -349,7 +350,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
349 .@"orelse",350 .@"orelse",
350 => {351 => {
351 const infix = datas[node];352 const infix = datas[node];
352 try renderExpression(ais, tree, infix.lhs, .space);353 try renderExpression(gpa, ais, tree, infix.lhs, .space);
353 const op_token = main_tokens[node];354 const op_token = main_tokens[node];
354 if (tree.tokensOnSameLine(op_token, op_token + 1)) {355 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
355 try renderToken(ais, tree, op_token, .space);356 try renderToken(ais, tree, op_token, .space);
...@@ -359,7 +360,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -359,7 +360,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
359 ais.popIndent();360 ais.popIndent();
360 }361 }
361 ais.pushIndentOneShot();362 ais.pushIndentOneShot();
362 return renderExpression(ais, tree, infix.rhs, space);363 return renderExpression(gpa, ais, tree, infix.rhs, space);
363 },364 },
364365
365 .bit_not,366 .bit_not,
...@@ -370,7 +371,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -370,7 +371,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
370 .address_of,371 .address_of,
371 => {372 => {
372 try renderToken(ais, tree, main_tokens[node], .none);373 try renderToken(ais, tree, main_tokens[node], .none);
373 return renderExpression(ais, tree, datas[node].lhs, space);374 return renderExpression(gpa, ais, tree, datas[node].lhs, space);
374 },375 },
375376
376 .@"try",377 .@"try",
...@@ -378,79 +379,79 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -378,79 +379,79 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
378 .@"await",379 .@"await",
379 => {380 => {
380 try renderToken(ais, tree, main_tokens[node], .space);381 try renderToken(ais, tree, main_tokens[node], .space);
381 return renderExpression(ais, tree, datas[node].lhs, space);382 return renderExpression(gpa, ais, tree, datas[node].lhs, space);
382 },383 },
383384
384 .array_type => return renderArrayType(ais, tree, tree.arrayType(node), space),385 .array_type => return renderArrayType(gpa, ais, tree, tree.arrayType(node), space),
385 .array_type_sentinel => return renderArrayType(ais, tree, tree.arrayTypeSentinel(node), space),386 .array_type_sentinel => return renderArrayType(gpa, ais, tree, tree.arrayTypeSentinel(node), space),
386387
387 .ptr_type_aligned => return renderPtrType(ais, tree, tree.ptrTypeAligned(node), space),388 .ptr_type_aligned => return renderPtrType(gpa, ais, tree, tree.ptrTypeAligned(node), space),
388 .ptr_type_sentinel => return renderPtrType(ais, tree, tree.ptrTypeSentinel(node), space),389 .ptr_type_sentinel => return renderPtrType(gpa, ais, tree, tree.ptrTypeSentinel(node), space),
389 .ptr_type => return renderPtrType(ais, tree, tree.ptrType(node), space),390 .ptr_type => return renderPtrType(gpa, ais, tree, tree.ptrType(node), space),
390 .ptr_type_bit_range => return renderPtrType(ais, tree, tree.ptrTypeBitRange(node), space),391 .ptr_type_bit_range => return renderPtrType(gpa, ais, tree, tree.ptrTypeBitRange(node), space),
391392
392 .array_init_one, .array_init_one_comma => {393 .array_init_one, .array_init_one_comma => {
393 var elements: [1]ast.Node.Index = undefined;394 var elements: [1]ast.Node.Index = undefined;
394 return renderArrayInit(ais, tree, tree.arrayInitOne(&elements, node), space);395 return renderArrayInit(gpa, ais, tree, tree.arrayInitOne(&elements, node), space);
395 },396 },
396 .array_init_dot_two, .array_init_dot_two_comma => {397 .array_init_dot_two, .array_init_dot_two_comma => {
397 var elements: [2]ast.Node.Index = undefined;398 var elements: [2]ast.Node.Index = undefined;
398 return renderArrayInit(ais, tree, tree.arrayInitDotTwo(&elements, node), space);399 return renderArrayInit(gpa, ais, tree, tree.arrayInitDotTwo(&elements, node), space);
399 },400 },
400 .array_init_dot,401 .array_init_dot,
401 .array_init_dot_comma,402 .array_init_dot_comma,
402 => return renderArrayInit(ais, tree, tree.arrayInitDot(node), space),403 => return renderArrayInit(gpa, ais, tree, tree.arrayInitDot(node), space),
403 .array_init,404 .array_init,
404 .array_init_comma,405 .array_init_comma,
405 => return renderArrayInit(ais, tree, tree.arrayInit(node), space),406 => return renderArrayInit(gpa, ais, tree, tree.arrayInit(node), space),
406407
407 .struct_init_one, .struct_init_one_comma => {408 .struct_init_one, .struct_init_one_comma => {
408 var fields: [1]ast.Node.Index = undefined;409 var fields: [1]ast.Node.Index = undefined;
409 return renderStructInit(ais, tree, tree.structInitOne(&fields, node), space);410 return renderStructInit(gpa, ais, tree, tree.structInitOne(&fields, node), space);
410 },411 },
411 .struct_init_dot_two, .struct_init_dot_two_comma => {412 .struct_init_dot_two, .struct_init_dot_two_comma => {
412 var fields: [2]ast.Node.Index = undefined;413 var fields: [2]ast.Node.Index = undefined;
413 return renderStructInit(ais, tree, tree.structInitDotTwo(&fields, node), space);414 return renderStructInit(gpa, ais, tree, tree.structInitDotTwo(&fields, node), space);
414 },415 },
415 .struct_init_dot,416 .struct_init_dot,
416 .struct_init_dot_comma,417 .struct_init_dot_comma,
417 => return renderStructInit(ais, tree, tree.structInitDot(node), space),418 => return renderStructInit(gpa, ais, tree, tree.structInitDot(node), space),
418 .struct_init,419 .struct_init,
419 .struct_init_comma,420 .struct_init_comma,
420 => return renderStructInit(ais, tree, tree.structInit(node), space),421 => return renderStructInit(gpa, ais, tree, tree.structInit(node), space),
421422
422 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => {423 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => {
423 var params: [1]ast.Node.Index = undefined;424 var params: [1]ast.Node.Index = undefined;
424 return renderCall(ais, tree, tree.callOne(&params, node), space);425 return renderCall(gpa, ais, tree, tree.callOne(&params, node), space);
425 },426 },
426427
427 .call,428 .call,
428 .call_comma,429 .call_comma,
429 .async_call,430 .async_call,
430 .async_call_comma,431 .async_call_comma,
431 => return renderCall(ais, tree, tree.callFull(node), space),432 => return renderCall(gpa, ais, tree, tree.callFull(node), space),
432433
433 .array_access => {434 .array_access => {
434 const suffix = datas[node];435 const suffix = datas[node];
435 const lbracket = tree.firstToken(suffix.rhs) - 1;436 const lbracket = tree.firstToken(suffix.rhs) - 1;
436 const rbracket = tree.lastToken(suffix.rhs) + 1;437 const rbracket = tree.lastToken(suffix.rhs) + 1;
437 try renderExpression(ais, tree, suffix.lhs, .none);438 try renderExpression(gpa, ais, tree, suffix.lhs, .none);
438 try renderToken(ais, tree, lbracket, .none); // [439 try renderToken(ais, tree, lbracket, .none); // [
439 try renderExpression(ais, tree, suffix.rhs, .none);440 try renderExpression(gpa, ais, tree, suffix.rhs, .none);
440 return renderToken(ais, tree, rbracket, space); // ]441 return renderToken(ais, tree, rbracket, space); // ]
441 },442 },
442443
443 .slice_open => return renderSlice(ais, tree, tree.sliceOpen(node), space),444 .slice_open => return renderSlice(gpa, ais, tree, tree.sliceOpen(node), space),
444 .slice => return renderSlice(ais, tree, tree.slice(node), space),445 .slice => return renderSlice(gpa, ais, tree, tree.slice(node), space),
445 .slice_sentinel => return renderSlice(ais, tree, tree.sliceSentinel(node), space),446 .slice_sentinel => return renderSlice(gpa, ais, tree, tree.sliceSentinel(node), space),
446447
447 .deref => {448 .deref => {
448 try renderExpression(ais, tree, datas[node].lhs, .none);449 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
449 return renderToken(ais, tree, main_tokens[node], space);450 return renderToken(ais, tree, main_tokens[node], space);
450 },451 },
451452
452 .unwrap_optional => {453 .unwrap_optional => {
453 try renderExpression(ais, tree, datas[node].lhs, .none);454 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
454 try renderToken(ais, tree, main_tokens[node], .none);455 try renderToken(ais, tree, main_tokens[node], .none);
455 return renderToken(ais, tree, datas[node].rhs, space);456 return renderToken(ais, tree, datas[node].rhs, space);
456 },457 },
...@@ -463,7 +464,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -463,7 +464,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
463 try renderToken(ais, tree, main_token, space); // break keyword464 try renderToken(ais, tree, main_token, space); // break keyword
464 } else if (label_token == 0 and target != 0) {465 } else if (label_token == 0 and target != 0) {
465 try renderToken(ais, tree, main_token, .space); // break keyword466 try renderToken(ais, tree, main_token, .space); // break keyword
466 try renderExpression(ais, tree, target, space);467 try renderExpression(gpa, ais, tree, target, space);
467 } else if (label_token != 0 and target == 0) {468 } else if (label_token != 0 and target == 0) {
468 try renderToken(ais, tree, main_token, .space); // break keyword469 try renderToken(ais, tree, main_token, .space); // break keyword
469 try renderToken(ais, tree, label_token - 1, .none); // colon470 try renderToken(ais, tree, label_token - 1, .none); // colon
...@@ -472,7 +473,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -472,7 +473,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
472 try renderToken(ais, tree, main_token, .space); // break keyword473 try renderToken(ais, tree, main_token, .space); // break keyword
473 try renderToken(ais, tree, label_token - 1, .none); // colon474 try renderToken(ais, tree, label_token - 1, .none); // colon
474 try renderToken(ais, tree, label_token, .space); // identifier475 try renderToken(ais, tree, label_token, .space); // identifier
475 try renderExpression(ais, tree, target, space);476 try renderExpression(gpa, ais, tree, target, space);
476 }477 }
477 },478 },
478479
...@@ -491,7 +492,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -491,7 +492,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
491 .@"return" => {492 .@"return" => {
492 if (datas[node].lhs != 0) {493 if (datas[node].lhs != 0) {
493 try renderToken(ais, tree, main_tokens[node], .space);494 try renderToken(ais, tree, main_tokens[node], .space);
494 try renderExpression(ais, tree, datas[node].lhs, space);495 try renderExpression(gpa, ais, tree, datas[node].lhs, space);
495 } else {496 } else {
496 try renderToken(ais, tree, main_tokens[node], space);497 try renderToken(ais, tree, main_tokens[node], space);
497 }498 }
...@@ -500,33 +501,33 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -500,33 +501,33 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
500 .grouped_expression => {501 .grouped_expression => {
501 try renderToken(ais, tree, main_tokens[node], .none); // lparen502 try renderToken(ais, tree, main_tokens[node], .none); // lparen
502 ais.pushIndentOneShot();503 ais.pushIndentOneShot();
503 try renderExpression(ais, tree, datas[node].lhs, .none);504 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
504 return renderToken(ais, tree, datas[node].rhs, space); // rparen505 return renderToken(ais, tree, datas[node].rhs, space); // rparen
505 },506 },
506507
507 .container_decl,508 .container_decl,
508 .container_decl_comma,509 .container_decl_comma,
509 => return renderContainerDecl(ais, tree, tree.containerDecl(node), space),510 => return renderContainerDecl(gpa, ais, tree, tree.containerDecl(node), space),
510511
511 .container_decl_two, .container_decl_two_comma => {512 .container_decl_two, .container_decl_two_comma => {
512 var buffer: [2]ast.Node.Index = undefined;513 var buffer: [2]ast.Node.Index = undefined;
513 return renderContainerDecl(ais, tree, tree.containerDeclTwo(&buffer, node), space);514 return renderContainerDecl(gpa, ais, tree, tree.containerDeclTwo(&buffer, node), space);
514 },515 },
515 .container_decl_arg,516 .container_decl_arg,
516 .container_decl_arg_comma,517 .container_decl_arg_comma,
517 => return renderContainerDecl(ais, tree, tree.containerDeclArg(node), space),518 => return renderContainerDecl(gpa, ais, tree, tree.containerDeclArg(node), space),
518519
519 .tagged_union,520 .tagged_union,
520 .tagged_union_comma,521 .tagged_union_comma,
521 => return renderContainerDecl(ais, tree, tree.taggedUnion(node), space),522 => return renderContainerDecl(gpa, ais, tree, tree.taggedUnion(node), space),
522523
523 .tagged_union_two, .tagged_union_two_comma => {524 .tagged_union_two, .tagged_union_two_comma => {
524 var buffer: [2]ast.Node.Index = undefined;525 var buffer: [2]ast.Node.Index = undefined;
525 return renderContainerDecl(ais, tree, tree.taggedUnionTwo(&buffer, node), space);526 return renderContainerDecl(gpa, ais, tree, tree.taggedUnionTwo(&buffer, node), space);
526 },527 },
527 .tagged_union_enum_tag,528 .tagged_union_enum_tag,
528 .tagged_union_enum_tag_comma,529 .tagged_union_enum_tag_comma,
529 => return renderContainerDecl(ais, tree, tree.taggedUnionEnumTag(node), space),530 => return renderContainerDecl(gpa, ais, tree, tree.taggedUnionEnumTag(node), space),
530531
531 .error_set_decl => {532 .error_set_decl => {
532 const error_token = main_tokens[node];533 const error_token = main_tokens[node];
...@@ -579,35 +580,35 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -579,35 +580,35 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
579580
580 .builtin_call_two, .builtin_call_two_comma => {581 .builtin_call_two, .builtin_call_two_comma => {
581 if (datas[node].lhs == 0) {582 if (datas[node].lhs == 0) {
582 return renderBuiltinCall(ais, tree, main_tokens[node], &.{}, space);583 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{}, space);
583 } else if (datas[node].rhs == 0) {584 } else if (datas[node].rhs == 0) {
584 return renderBuiltinCall(ais, tree, main_tokens[node], &.{datas[node].lhs}, space);585 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{datas[node].lhs}, space);
585 } else {586 } else {
586 return renderBuiltinCall(ais, tree, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);587 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);
587 }588 }
588 },589 },
589 .builtin_call, .builtin_call_comma => {590 .builtin_call, .builtin_call_comma => {
590 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];591 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
591 return renderBuiltinCall(ais, tree, main_tokens[node], params, space);592 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], params, space);
592 },593 },
593594
594 .fn_proto_simple => {595 .fn_proto_simple => {
595 var params: [1]ast.Node.Index = undefined;596 var params: [1]ast.Node.Index = undefined;
596 return renderFnProto(ais, tree, tree.fnProtoSimple(&params, node), space);597 return renderFnProto(gpa, ais, tree, tree.fnProtoSimple(&params, node), space);
597 },598 },
598 .fn_proto_multi => return renderFnProto(ais, tree, tree.fnProtoMulti(node), space),599 .fn_proto_multi => return renderFnProto(gpa, ais, tree, tree.fnProtoMulti(node), space),
599 .fn_proto_one => {600 .fn_proto_one => {
600 var params: [1]ast.Node.Index = undefined;601 var params: [1]ast.Node.Index = undefined;
601 return renderFnProto(ais, tree, tree.fnProtoOne(&params, node), space);602 return renderFnProto(gpa, ais, tree, tree.fnProtoOne(&params, node), space);
602 },603 },
603 .fn_proto => return renderFnProto(ais, tree, tree.fnProto(node), space),604 .fn_proto => return renderFnProto(gpa, ais, tree, tree.fnProto(node), space),
604605
605 .anyframe_type => {606 .anyframe_type => {
606 const main_token = main_tokens[node];607 const main_token = main_tokens[node];
607 if (datas[node].rhs != 0) {608 if (datas[node].rhs != 0) {
608 try renderToken(ais, tree, main_token, .none); // anyframe609 try renderToken(ais, tree, main_token, .none); // anyframe
609 try renderToken(ais, tree, main_token + 1, .none); // ->610 try renderToken(ais, tree, main_token + 1, .none); // ->
610 return renderExpression(ais, tree, datas[node].rhs, space);611 return renderExpression(gpa, ais, tree, datas[node].rhs, space);
611 } else {612 } else {
612 return renderToken(ais, tree, main_token, space); // anyframe613 return renderToken(ais, tree, main_token, space); // anyframe
613 }614 }
...@@ -624,7 +625,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -624,7 +625,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
624625
625 try renderToken(ais, tree, switch_token, .space); // switch keyword626 try renderToken(ais, tree, switch_token, .space); // switch keyword
626 try renderToken(ais, tree, switch_token + 1, .none); // lparen627 try renderToken(ais, tree, switch_token + 1, .none); // lparen
627 try renderExpression(ais, tree, condition, .none); // condtion expression628 try renderExpression(gpa, ais, tree, condition, .none); // condtion expression
628 try renderToken(ais, tree, rparen, .space); // rparen629 try renderToken(ais, tree, rparen, .space); // rparen
629630
630 ais.pushIndentNextLine();631 ais.pushIndentNextLine();
...@@ -632,26 +633,26 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -632,26 +633,26 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
632 try renderToken(ais, tree, rparen + 1, .none); // lbrace633 try renderToken(ais, tree, rparen + 1, .none); // lbrace
633 } else {634 } else {
634 try renderToken(ais, tree, rparen + 1, .newline); // lbrace635 try renderToken(ais, tree, rparen + 1, .newline); // lbrace
635 try renderExpressions(ais, tree, cases, .comma);636 try renderExpressions(gpa, ais, tree, cases, .comma);
636 }637 }
637 ais.popIndent();638 ais.popIndent();
638 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace639 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
639 },640 },
640641
641 .switch_case_one => return renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),642 .switch_case_one => return renderSwitchCase(gpa, ais, tree, tree.switchCaseOne(node), space),
642 .switch_case => return renderSwitchCase(ais, tree, tree.switchCase(node), space),643 .switch_case => return renderSwitchCase(gpa, ais, tree, tree.switchCase(node), space),
643644
644 .while_simple => return renderWhile(ais, tree, tree.whileSimple(node), space),645 .while_simple => return renderWhile(gpa, ais, tree, tree.whileSimple(node), space),
645 .while_cont => return renderWhile(ais, tree, tree.whileCont(node), space),646 .while_cont => return renderWhile(gpa, ais, tree, tree.whileCont(node), space),
646 .@"while" => return renderWhile(ais, tree, tree.whileFull(node), space),647 .@"while" => return renderWhile(gpa, ais, tree, tree.whileFull(node), space),
647 .for_simple => return renderWhile(ais, tree, tree.forSimple(node), space),648 .for_simple => return renderWhile(gpa, ais, tree, tree.forSimple(node), space),
648 .@"for" => return renderWhile(ais, tree, tree.forFull(node), space),649 .@"for" => return renderWhile(gpa, ais, tree, tree.forFull(node), space),
649650
650 .if_simple => return renderIf(ais, tree, tree.ifSimple(node), space),651 .if_simple => return renderIf(gpa, ais, tree, tree.ifSimple(node), space),
651 .@"if" => return renderIf(ais, tree, tree.ifFull(node), space),652 .@"if" => return renderIf(gpa, ais, tree, tree.ifFull(node), space),
652653
653 .asm_simple => return renderAsm(ais, tree, tree.asmSimple(node), space),654 .asm_simple => return renderAsm(gpa, ais, tree, tree.asmSimple(node), space),
654 .@"asm" => return renderAsm(ais, tree, tree.asmFull(node), space),655 .@"asm" => return renderAsm(gpa, ais, tree, tree.asmFull(node), space),
655656
656 .enum_literal => {657 .enum_literal => {
657 try renderToken(ais, tree, main_tokens[node] - 1, .none); // .658 try renderToken(ais, tree, main_tokens[node] - 1, .none); // .
...@@ -676,22 +677,24 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -676,22 +677,24 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
676677
677// TODO: handle comments inside the brackets678// TODO: handle comments inside the brackets
678fn renderArrayType(679fn renderArrayType(
680 gpa: *Allocator,
679 ais: *Ais,681 ais: *Ais,
680 tree: ast.Tree,682 tree: ast.Tree,
681 array_type: ast.full.ArrayType,683 array_type: ast.full.ArrayType,
682 space: Space,684 space: Space,
683) Error!void {685) Error!void {
684 try renderToken(ais, tree, array_type.ast.lbracket, .none); // lbracket686 try renderToken(ais, tree, array_type.ast.lbracket, .none); // lbracket
685 try renderExpression(ais, tree, array_type.ast.elem_count, .none);687 try renderExpression(gpa, ais, tree, array_type.ast.elem_count, .none);
686 if (array_type.ast.sentinel) |sentinel| {688 if (array_type.ast.sentinel) |sentinel| {
687 try renderToken(ais, tree, tree.firstToken(sentinel) - 1, .none); // colon689 try renderToken(ais, tree, tree.firstToken(sentinel) - 1, .none); // colon
688 try renderExpression(ais, tree, sentinel, .none);690 try renderExpression(gpa, ais, tree, sentinel, .none);
689 }691 }
690 try renderToken(ais, tree, tree.firstToken(array_type.ast.elem_type) - 1, .none); // rbracket692 try renderToken(ais, tree, tree.firstToken(array_type.ast.elem_type) - 1, .none); // rbracket
691 return renderExpression(ais, tree, array_type.ast.elem_type, space);693 return renderExpression(gpa, ais, tree, array_type.ast.elem_type, space);
692}694}
693695
694fn renderPtrType(696fn renderPtrType(
697 gpa: *Allocator,
695 ais: *Ais,698 ais: *Ais,
696 tree: ast.Tree,699 tree: ast.Tree,
697 ptr_type: ast.full.PtrType,700 ptr_type: ast.full.PtrType,
...@@ -707,7 +710,7 @@ fn renderPtrType(...@@ -707,7 +710,7 @@ fn renderPtrType(
707 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and710 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and
708 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])711 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
709 {712 {
710 return renderExpression(ais, tree, ptr_type.ast.child_type, space);713 return renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);
711 }714 }
712 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk715 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
713 },716 },
...@@ -720,7 +723,7 @@ fn renderPtrType(...@@ -720,7 +723,7 @@ fn renderPtrType(
720 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket723 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
721 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk724 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
722 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon725 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
723 try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);726 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);
724 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket727 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
725 }728 }
726 },729 },
...@@ -737,7 +740,7 @@ fn renderPtrType(...@@ -737,7 +740,7 @@ fn renderPtrType(
737 } else {740 } else {
738 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket741 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
739 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon742 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
740 try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);743 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);
741 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket744 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
742 }745 }
743 },746 },
...@@ -751,13 +754,13 @@ fn renderPtrType(...@@ -751,13 +754,13 @@ fn renderPtrType(
751 const align_first = tree.firstToken(ptr_type.ast.align_node);754 const align_first = tree.firstToken(ptr_type.ast.align_node);
752 try renderToken(ais, tree, align_first - 2, .none); // align755 try renderToken(ais, tree, align_first - 2, .none); // align
753 try renderToken(ais, tree, align_first - 1, .none); // lparen756 try renderToken(ais, tree, align_first - 1, .none); // lparen
754 try renderExpression(ais, tree, ptr_type.ast.align_node, .none);757 try renderExpression(gpa, ais, tree, ptr_type.ast.align_node, .none);
755 if (ptr_type.ast.bit_range_start != 0) {758 if (ptr_type.ast.bit_range_start != 0) {
756 assert(ptr_type.ast.bit_range_end != 0);759 assert(ptr_type.ast.bit_range_end != 0);
757 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon760 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
758 try renderExpression(ais, tree, ptr_type.ast.bit_range_start, .none);761 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_start, .none);
759 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon762 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
760 try renderExpression(ais, tree, ptr_type.ast.bit_range_end, .none);763 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_end, .none);
761 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen764 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
762 } else {765 } else {
763 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen766 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
...@@ -772,10 +775,11 @@ fn renderPtrType(...@@ -772,10 +775,11 @@ fn renderPtrType(
772 try renderToken(ais, tree, volatile_token, .space);775 try renderToken(ais, tree, volatile_token, .space);
773 }776 }
774777
775 try renderExpression(ais, tree, ptr_type.ast.child_type, space);778 try renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);
776}779}
777780
778fn renderSlice(781fn renderSlice(
782 gpa: *Allocator,
779 ais: *Ais,783 ais: *Ais,
780 tree: ast.Tree,784 tree: ast.Tree,
781 slice: ast.full.Slice,785 slice: ast.full.Slice,
...@@ -787,11 +791,11 @@ fn renderSlice(...@@ -787,11 +791,11 @@ fn renderSlice(
787 const after_start_space = if (after_start_space_bool) Space.space else Space.none;791 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
788 const after_dots_space = if (slice.ast.end != 0) after_start_space else Space.none;792 const after_dots_space = if (slice.ast.end != 0) after_start_space else Space.none;
789793
790 try renderExpression(ais, tree, slice.ast.sliced, .none);794 try renderExpression(gpa, ais, tree, slice.ast.sliced, .none);
791 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket795 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket
792796
793 const start_last = tree.lastToken(slice.ast.start);797 const start_last = tree.lastToken(slice.ast.start);
794 try renderExpression(ais, tree, slice.ast.start, after_start_space);798 try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space);
795 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")799 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")
796 if (slice.ast.end == 0) {800 if (slice.ast.end == 0) {
797 return renderToken(ais, tree, start_last + 2, space); // rbracket801 return renderToken(ais, tree, start_last + 2, space); // rbracket
...@@ -799,17 +803,18 @@ fn renderSlice(...@@ -799,17 +803,18 @@ fn renderSlice(
799803
800 const end_last = tree.lastToken(slice.ast.end);804 const end_last = tree.lastToken(slice.ast.end);
801 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;805 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;
802 try renderExpression(ais, tree, slice.ast.end, after_end_space);806 try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space);
803 if (slice.ast.sentinel == 0) {807 if (slice.ast.sentinel == 0) {
804 return renderToken(ais, tree, end_last + 1, space); // rbracket808 return renderToken(ais, tree, end_last + 1, space); // rbracket
805 }809 }
806810
807 try renderToken(ais, tree, end_last + 1, .none); // colon811 try renderToken(ais, tree, end_last + 1, .none); // colon
808 try renderExpression(ais, tree, slice.ast.sentinel, .none);812 try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none);
809 try renderToken(ais, tree, tree.lastToken(slice.ast.sentinel) + 1, space); // rbracket813 try renderToken(ais, tree, tree.lastToken(slice.ast.sentinel) + 1, space); // rbracket
810}814}
811815
812fn renderAsmOutput(816fn renderAsmOutput(
817 gpa: *Allocator,
813 ais: *Ais,818 ais: *Ais,
814 tree: ast.Tree,819 tree: ast.Tree,
815 asm_output: ast.Node.Index,820 asm_output: ast.Node.Index,
...@@ -830,7 +835,7 @@ fn renderAsmOutput(...@@ -830,7 +835,7 @@ fn renderAsmOutput(
830835
831 if (token_tags[symbolic_name + 4] == .arrow) {836 if (token_tags[symbolic_name + 4] == .arrow) {
832 try renderToken(ais, tree, symbolic_name + 4, .space); // ->837 try renderToken(ais, tree, symbolic_name + 4, .space); // ->
833 try renderExpression(ais, tree, datas[asm_output].lhs, Space.none);838 try renderExpression(gpa, ais, tree, datas[asm_output].lhs, Space.none);
834 return renderToken(ais, tree, datas[asm_output].rhs, space); // rparen839 return renderToken(ais, tree, datas[asm_output].rhs, space); // rparen
835 } else {840 } else {
836 try renderToken(ais, tree, symbolic_name + 4, .none); // ident841 try renderToken(ais, tree, symbolic_name + 4, .none); // ident
...@@ -839,6 +844,7 @@ fn renderAsmOutput(...@@ -839,6 +844,7 @@ fn renderAsmOutput(
839}844}
840845
841fn renderAsmInput(846fn renderAsmInput(
847 gpa: *Allocator,
842 ais: *Ais,848 ais: *Ais,
843 tree: ast.Tree,849 tree: ast.Tree,
844 asm_input: ast.Node.Index,850 asm_input: ast.Node.Index,
...@@ -855,11 +861,11 @@ fn renderAsmInput(...@@ -855,11 +861,11 @@ fn renderAsmInput(
855 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket861 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket
856 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"862 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"
857 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen863 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen
858 try renderExpression(ais, tree, datas[asm_input].lhs, Space.none);864 try renderExpression(gpa, ais, tree, datas[asm_input].lhs, Space.none);
859 return renderToken(ais, tree, datas[asm_input].rhs, space); // rparen865 return renderToken(ais, tree, datas[asm_input].rhs, space); // rparen
860}866}
861867
862fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!void {868fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!void {
863 if (var_decl.visib_token) |visib_token| {869 if (var_decl.visib_token) |visib_token| {
864 try renderToken(ais, tree, visib_token, Space.space); // pub870 try renderToken(ais, tree, visib_token, Space.space); // pub
865 }871 }
...@@ -896,9 +902,9 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo...@@ -896,9 +902,9 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
896 if (var_decl.ast.align_node != 0 or var_decl.ast.section_node != 0 or902 if (var_decl.ast.align_node != 0 or var_decl.ast.section_node != 0 or
897 var_decl.ast.init_node != 0)903 var_decl.ast.init_node != 0)
898 {904 {
899 try renderExpression(ais, tree, var_decl.ast.type_node, .space);905 try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space);
900 } else {906 } else {
901 try renderExpression(ais, tree, var_decl.ast.type_node, .none);907 try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .none);
902 const semicolon = tree.lastToken(var_decl.ast.type_node) + 1;908 const semicolon = tree.lastToken(var_decl.ast.type_node) + 1;
903 return renderToken(ais, tree, semicolon, Space.newline); // ;909 return renderToken(ais, tree, semicolon, Space.newline); // ;
904 }910 }
...@@ -910,7 +916,7 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo...@@ -910,7 +916,7 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
910 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;916 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;
911 try renderToken(ais, tree, align_kw, Space.none); // align917 try renderToken(ais, tree, align_kw, Space.none); // align
912 try renderToken(ais, tree, lparen, Space.none); // (918 try renderToken(ais, tree, lparen, Space.none); // (
913 try renderExpression(ais, tree, var_decl.ast.align_node, Space.none);919 try renderExpression(gpa, ais, tree, var_decl.ast.align_node, Space.none);
914 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {920 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {
915 try renderToken(ais, tree, rparen, .space); // )921 try renderToken(ais, tree, rparen, .space); // )
916 } else {922 } else {
...@@ -925,7 +931,7 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo...@@ -925,7 +931,7 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
925 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;931 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;
926 try renderToken(ais, tree, section_kw, Space.none); // linksection932 try renderToken(ais, tree, section_kw, Space.none); // linksection
927 try renderToken(ais, tree, lparen, Space.none); // (933 try renderToken(ais, tree, lparen, Space.none); // (
928 try renderExpression(ais, tree, var_decl.ast.section_node, Space.none);934 try renderExpression(gpa, ais, tree, var_decl.ast.section_node, Space.none);
929 if (var_decl.ast.init_node != 0) {935 if (var_decl.ast.init_node != 0) {
930 try renderToken(ais, tree, rparen, .space); // )936 try renderToken(ais, tree, rparen, .space); // )
931 } else {937 } else {
...@@ -943,11 +949,11 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo...@@ -943,11 +949,11 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
943 ais.popIndent();949 ais.popIndent();
944 }950 }
945 ais.pushIndentOneShot();951 ais.pushIndentOneShot();
946 try renderExpression(ais, tree, var_decl.ast.init_node, .semicolon);952 try renderExpression(gpa, ais, tree, var_decl.ast.init_node, .semicolon);
947}953}
948954
949fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void {955fn renderIf(gpa: *Allocator, ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void {
950 return renderWhile(ais, tree, .{956 return renderWhile(gpa, ais, tree, .{
951 .ast = .{957 .ast = .{
952 .while_token = if_node.ast.if_token,958 .while_token = if_node.ast.if_token,
953 .cond_expr = if_node.ast.cond_expr,959 .cond_expr = if_node.ast.cond_expr,
...@@ -965,7 +971,7 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error...@@ -965,7 +971,7 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error
965971
966/// Note that this function is additionally used to render if and for expressions, with972/// Note that this function is additionally used to render if and for expressions, with
967/// respective values set to null.973/// respective values set to null.
968fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Space) Error!void {974fn renderWhile(gpa: *Allocator, ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Space) Error!void {
969 const node_tags = tree.nodes.items(.tag);975 const node_tags = tree.nodes.items(.tag);
970 const token_tags = tree.tokens.items(.tag);976 const token_tags = tree.tokens.items(.tag);
971977
...@@ -980,7 +986,7 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -980,7 +986,7 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
980986
981 try renderToken(ais, tree, while_node.ast.while_token, .space); // if987 try renderToken(ais, tree, while_node.ast.while_token, .space); // if
982 try renderToken(ais, tree, while_node.ast.while_token + 1, .none); // lparen988 try renderToken(ais, tree, while_node.ast.while_token + 1, .none); // lparen
983 try renderExpression(ais, tree, while_node.ast.cond_expr, .none); // condition989 try renderExpression(gpa, ais, tree, while_node.ast.cond_expr, .none); // condition
984990
985 const then_tag = node_tags[while_node.ast.then_expr];991 const then_tag = node_tags[while_node.ast.then_expr];
986 if (nodeIsBlock(then_tag) and !nodeIsIf(then_tag)) {992 if (nodeIsBlock(then_tag) and !nodeIsIf(then_tag)) {
...@@ -1023,21 +1029,21 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1023,21 +1029,21 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1023 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1029 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1024 try renderToken(ais, tree, lparen - 1, .space); // :1030 try renderToken(ais, tree, lparen - 1, .space); // :
1025 try renderToken(ais, tree, lparen, .none); // lparen1031 try renderToken(ais, tree, lparen, .none); // lparen
1026 try renderExpression(ais, tree, while_node.ast.cont_expr, .none);1032 try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none);
1027 const brace_space: Space = if (ais.isLineOverIndented()) .newline else .space;1033 const brace_space: Space = if (ais.isLineOverIndented()) .newline else .space;
1028 try renderToken(ais, tree, rparen, brace_space); // rparen1034 try renderToken(ais, tree, rparen, brace_space); // rparen
1029 }1035 }
1030 if (while_node.ast.else_expr != 0) {1036 if (while_node.ast.else_expr != 0) {
1031 try renderExpression(ais, tree, while_node.ast.then_expr, Space.space);1037 try renderExpression(gpa, ais, tree, while_node.ast.then_expr, Space.space);
1032 try renderToken(ais, tree, while_node.else_token, .space); // else1038 try renderToken(ais, tree, while_node.else_token, .space); // else
1033 if (while_node.error_token) |error_token| {1039 if (while_node.error_token) |error_token| {
1034 try renderToken(ais, tree, error_token - 1, .none); // |1040 try renderToken(ais, tree, error_token - 1, .none); // |
1035 try renderToken(ais, tree, error_token, .none); // identifier1041 try renderToken(ais, tree, error_token, .none); // identifier
1036 try renderToken(ais, tree, error_token + 1, .space); // |1042 try renderToken(ais, tree, error_token + 1, .space); // |
1037 }1043 }
1038 return renderExpression(ais, tree, while_node.ast.else_expr, space);1044 return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space);
1039 } else {1045 } else {
1040 return renderExpression(ais, tree, while_node.ast.then_expr, space);1046 return renderExpression(gpa, ais, tree, while_node.ast.then_expr, space);
1041 }1047 }
1042 }1048 }
10431049
...@@ -1067,11 +1073,11 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1067,11 +1073,11 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1067 break :blk ident + 1;1073 break :blk ident + 1;
1068 }1074 }
1069 };1075 };
1070 const after_space: Space = if (while_node.ast.cont_expr != 0) .space else .newline; 1076 const after_space: Space = if (while_node.ast.cont_expr != 0) .space else .newline;
1071 try renderToken(ais, tree, pipe, after_space); // |1077 try renderToken(ais, tree, pipe, after_space); // |
1072 } else {1078 } else {
1073 ais.pushIndent();1079 ais.pushIndent();
1074 const after_space: Space = if (while_node.ast.cont_expr != 0) .space else .newline; 1080 const after_space: Space = if (while_node.ast.cont_expr != 0) .space else .newline;
1075 try renderToken(ais, tree, rparen, after_space); // rparen1081 try renderToken(ais, tree, rparen, after_space); // rparen
1076 ais.popIndent();1082 ais.popIndent();
1077 }1083 }
...@@ -1080,12 +1086,12 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1080,12 +1086,12 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1080 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1086 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1081 try renderToken(ais, tree, cont_lparen - 1, .space); // :1087 try renderToken(ais, tree, cont_lparen - 1, .space); // :
1082 try renderToken(ais, tree, cont_lparen, .none); // lparen1088 try renderToken(ais, tree, cont_lparen, .none); // lparen
1083 try renderExpression(ais, tree, while_node.ast.cont_expr, .none);1089 try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none);
1084 try renderToken(ais, tree, cont_rparen, .newline); // rparen1090 try renderToken(ais, tree, cont_rparen, .newline); // rparen
1085 }1091 }
1086 if (while_node.ast.else_expr != 0) {1092 if (while_node.ast.else_expr != 0) {
1087 ais.pushIndent();1093 ais.pushIndent();
1088 try renderExpression(ais, tree, while_node.ast.then_expr, Space.newline);1094 try renderExpression(gpa, ais, tree, while_node.ast.then_expr, Space.newline);
1089 ais.popIndent();1095 ais.popIndent();
1090 const else_is_block = nodeIsBlock(node_tags[while_node.ast.else_expr]);1096 const else_is_block = nodeIsBlock(node_tags[while_node.ast.else_expr]);
1091 if (else_is_block) {1097 if (else_is_block) {
...@@ -1095,7 +1101,7 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1095,7 +1101,7 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1095 try renderToken(ais, tree, error_token, .none); // identifier1101 try renderToken(ais, tree, error_token, .none); // identifier
1096 try renderToken(ais, tree, error_token + 1, .space); // |1102 try renderToken(ais, tree, error_token + 1, .space); // |
1097 }1103 }
1098 return renderExpression(ais, tree, while_node.ast.else_expr, space);1104 return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space);
1099 } else {1105 } else {
1100 if (while_node.error_token) |error_token| {1106 if (while_node.error_token) |error_token| {
1101 try renderToken(ais, tree, while_node.else_token, .space); // else1107 try renderToken(ais, tree, while_node.else_token, .space); // else
...@@ -1106,13 +1112,13 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1106,13 +1112,13 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1106 try renderToken(ais, tree, while_node.else_token, .newline); // else1112 try renderToken(ais, tree, while_node.else_token, .newline); // else
1107 }1113 }
1108 ais.pushIndent();1114 ais.pushIndent();
1109 try renderExpression(ais, tree, while_node.ast.else_expr, space);1115 try renderExpression(gpa, ais, tree, while_node.ast.else_expr, space);
1110 ais.popIndent();1116 ais.popIndent();
1111 return;1117 return;
1112 }1118 }
1113 } else {1119 } else {
1114 ais.pushIndent();1120 ais.pushIndent();
1115 try renderExpression(ais, tree, while_node.ast.then_expr, space);1121 try renderExpression(gpa, ais, tree, while_node.ast.then_expr, space);
1116 ais.popIndent();1122 ais.popIndent();
1117 return;1123 return;
1118 }1124 }
...@@ -1152,12 +1158,12 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1152,12 +1158,12 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1152 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1158 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1153 try renderToken(ais, tree, cont_lparen - 1, .space); // :1159 try renderToken(ais, tree, cont_lparen - 1, .space); // :
1154 try renderToken(ais, tree, cont_lparen, .none); // lparen1160 try renderToken(ais, tree, cont_lparen, .none); // lparen
1155 try renderExpression(ais, tree, while_node.ast.cont_expr, .none);1161 try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none);
1156 try renderToken(ais, tree, cont_rparen, .space); // rparen1162 try renderToken(ais, tree, cont_rparen, .space); // rparen
1157 }1163 }
11581164
1159 if (while_node.ast.else_expr != 0) {1165 if (while_node.ast.else_expr != 0) {
1160 try renderExpression(ais, tree, while_node.ast.then_expr, .space);1166 try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .space);
1161 try renderToken(ais, tree, while_node.else_token, .space); // else1167 try renderToken(ais, tree, while_node.else_token, .space); // else
11621168
1163 if (while_node.error_token) |error_token| {1169 if (while_node.error_token) |error_token| {
...@@ -1166,13 +1172,14 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa...@@ -1166,13 +1172,14 @@ fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Spa
1166 try renderToken(ais, tree, error_token + 1, .space); // |1172 try renderToken(ais, tree, error_token + 1, .space); // |
1167 }1173 }
11681174
1169 return renderExpression(ais, tree, while_node.ast.else_expr, space);1175 return renderExpression(gpa, ais, tree, while_node.ast.else_expr, space);
1170 } else {1176 } else {
1171 return renderExpression(ais, tree, while_node.ast.then_expr, space);1177 return renderExpression(gpa, ais, tree, while_node.ast.then_expr, space);
1172 }1178 }
1173}1179}
11741180
1175fn renderContainerField(1181fn renderContainerField(
1182 gpa: *Allocator,
1176 ais: *Ais,1183 ais: *Ais,
1177 tree: ast.Tree,1184 tree: ast.Tree,
1178 field: ast.full.ContainerField,1185 field: ast.full.ContainerField,
...@@ -1190,26 +1197,26 @@ fn renderContainerField(...@@ -1190,26 +1197,26 @@ fn renderContainerField(
1190 try renderToken(ais, tree, field.ast.name_token + 1, .space); // :1197 try renderToken(ais, tree, field.ast.name_token + 1, .space); // :
11911198
1192 if (field.ast.align_expr != 0) {1199 if (field.ast.align_expr != 0) {
1193 try renderExpression(ais, tree, field.ast.type_expr, .space); // type1200 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type
1194 const align_token = tree.firstToken(field.ast.align_expr) - 2;1201 const align_token = tree.firstToken(field.ast.align_expr) - 2;
1195 try renderToken(ais, tree, align_token, .none); // align1202 try renderToken(ais, tree, align_token, .none); // align
1196 try renderToken(ais, tree, align_token + 1, .none); // (1203 try renderToken(ais, tree, align_token + 1, .none); // (
1197 try renderExpression(ais, tree, field.ast.align_expr, .none); // alignment1204 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1198 const rparen = tree.lastToken(field.ast.align_expr) + 1;1205 const rparen = tree.lastToken(field.ast.align_expr) + 1;
1199 return renderTokenComma(ais, tree, rparen, space); // )1206 return renderTokenComma(ais, tree, rparen, space); // )
1200 } else {1207 } else {
1201 return renderExpressionComma(ais, tree, field.ast.type_expr, space); // type1208 return renderExpressionComma(gpa, ais, tree, field.ast.type_expr, space); // type
1202 }1209 }
1203 }1210 }
1204 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {1211 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
1205 try renderToken(ais, tree, field.ast.name_token, .space); // name1212 try renderToken(ais, tree, field.ast.name_token, .space); // name
1206 try renderToken(ais, tree, field.ast.name_token + 1, .space); // =1213 try renderToken(ais, tree, field.ast.name_token + 1, .space); // =
1207 return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value1214 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value
1208 }1215 }
12091216
1210 try renderToken(ais, tree, field.ast.name_token, .none); // name1217 try renderToken(ais, tree, field.ast.name_token, .none); // name
1211 try renderToken(ais, tree, field.ast.name_token + 1, .space); // :1218 try renderToken(ais, tree, field.ast.name_token + 1, .space); // :
1212 try renderExpression(ais, tree, field.ast.type_expr, .space); // type1219 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type
12131220
1214 if (field.ast.align_expr != 0) {1221 if (field.ast.align_expr != 0) {
1215 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1222 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
...@@ -1217,15 +1224,16 @@ fn renderContainerField(...@@ -1217,15 +1224,16 @@ fn renderContainerField(
1217 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1224 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1218 try renderToken(ais, tree, align_kw, .none); // align1225 try renderToken(ais, tree, align_kw, .none); // align
1219 try renderToken(ais, tree, lparen_token, .none); // (1226 try renderToken(ais, tree, lparen_token, .none); // (
1220 try renderExpression(ais, tree, field.ast.align_expr, .none); // alignment1227 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1221 try renderToken(ais, tree, rparen_token, .space); // )1228 try renderToken(ais, tree, rparen_token, .space); // )
1222 }1229 }
1223 const eq_token = tree.firstToken(field.ast.value_expr) - 1;1230 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
1224 try renderToken(ais, tree, eq_token, .space); // =1231 try renderToken(ais, tree, eq_token, .space); // =
1225 return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value1232 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value
1226}1233}
12271234
1228fn renderBuiltinCall(1235fn renderBuiltinCall(
1236 gpa: *Allocator,
1229 ais: *Ais,1237 ais: *Ais,
1230 tree: ast.Tree,1238 tree: ast.Tree,
1231 builtin_token: ast.TokenIndex,1239 builtin_token: ast.TokenIndex,
...@@ -1249,7 +1257,7 @@ fn renderBuiltinCall(...@@ -1249,7 +1257,7 @@ fn renderBuiltinCall(
1249 try renderToken(ais, tree, builtin_token + 1, .none); // (1257 try renderToken(ais, tree, builtin_token + 1, .none); // (
12501258
1251 for (params) |param_node, i| {1259 for (params) |param_node, i| {
1252 try renderExpression(ais, tree, param_node, .none);1260 try renderExpression(gpa, ais, tree, param_node, .none);
12531261
1254 if (i + 1 < params.len) {1262 if (i + 1 < params.len) {
1255 const comma_token = tree.lastToken(param_node) + 1;1263 const comma_token = tree.lastToken(param_node) + 1;
...@@ -1263,7 +1271,7 @@ fn renderBuiltinCall(...@@ -1263,7 +1271,7 @@ fn renderBuiltinCall(
1263 try renderToken(ais, tree, builtin_token + 1, Space.newline); // (1271 try renderToken(ais, tree, builtin_token + 1, Space.newline); // (
12641272
1265 for (params) |param_node| {1273 for (params) |param_node| {
1266 try renderExpression(ais, tree, param_node, .comma);1274 try renderExpression(gpa, ais, tree, param_node, .comma);
1267 }1275 }
1268 ais.popIndent();1276 ais.popIndent();
12691277
...@@ -1271,7 +1279,7 @@ fn renderBuiltinCall(...@@ -1271,7 +1279,7 @@ fn renderBuiltinCall(
1271 }1279 }
1272}1280}
12731281
1274fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: Space) Error!void {1282fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: Space) Error!void {
1275 const token_tags = tree.tokens.items(.tag);1283 const token_tags = tree.tokens.items(.tag);
1276 const token_starts = tree.tokens.items(.start);1284 const token_starts = tree.tokens.items(.start);
12771285
...@@ -1372,7 +1380,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1372,7 +1380,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
1372 }1380 }
1373 const param = fn_proto.ast.params[param_i];1381 const param = fn_proto.ast.params[param_i];
1374 param_i += 1;1382 param_i += 1;
1375 try renderExpression(ais, tree, param, .none);1383 try renderExpression(gpa, ais, tree, param, .none);
1376 last_param_token = tree.lastToken(param);1384 last_param_token = tree.lastToken(param);
1377 }1385 }
1378 } else {1386 } else {
...@@ -1417,7 +1425,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1417,7 +1425,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
1417 }1425 }
1418 const param = fn_proto.ast.params[param_i];1426 const param = fn_proto.ast.params[param_i];
1419 param_i += 1;1427 param_i += 1;
1420 try renderExpression(ais, tree, param, .comma);1428 try renderExpression(gpa, ais, tree, param, .comma);
1421 last_param_token = tree.lastToken(param) + 1;1429 last_param_token = tree.lastToken(param) + 1;
1422 }1430 }
1423 ais.popIndent();1431 ais.popIndent();
...@@ -1431,7 +1439,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1431,7 +1439,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
14311439
1432 try renderToken(ais, tree, align_lparen - 1, .none); // align1440 try renderToken(ais, tree, align_lparen - 1, .none); // align
1433 try renderToken(ais, tree, align_lparen, .none); // (1441 try renderToken(ais, tree, align_lparen, .none); // (
1434 try renderExpression(ais, tree, fn_proto.ast.align_expr, .none);1442 try renderExpression(gpa, ais, tree, fn_proto.ast.align_expr, .none);
1435 try renderToken(ais, tree, align_rparen, .space); // )1443 try renderToken(ais, tree, align_rparen, .space); // )
1436 }1444 }
14371445
...@@ -1441,7 +1449,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1441,7 +1449,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
14411449
1442 try renderToken(ais, tree, section_lparen - 1, .none); // section1450 try renderToken(ais, tree, section_lparen - 1, .none); // section
1443 try renderToken(ais, tree, section_lparen, .none); // (1451 try renderToken(ais, tree, section_lparen, .none); // (
1444 try renderExpression(ais, tree, fn_proto.ast.section_expr, .none);1452 try renderExpression(gpa, ais, tree, fn_proto.ast.section_expr, .none);
1445 try renderToken(ais, tree, section_rparen, .space); // )1453 try renderToken(ais, tree, section_rparen, .space); // )
1446 }1454 }
14471455
...@@ -1451,7 +1459,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1451,7 +1459,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
14511459
1452 try renderToken(ais, tree, callconv_lparen - 1, .none); // callconv1460 try renderToken(ais, tree, callconv_lparen - 1, .none); // callconv
1453 try renderToken(ais, tree, callconv_lparen, .none); // (1461 try renderToken(ais, tree, callconv_lparen, .none); // (
1454 try renderExpression(ais, tree, fn_proto.ast.callconv_expr, .none);1462 try renderExpression(gpa, ais, tree, fn_proto.ast.callconv_expr, .none);
1455 try renderToken(ais, tree, callconv_rparen, .space); // )1463 try renderToken(ais, tree, callconv_rparen, .space); // )
1456 } else if (is_inline) {1464 } else if (is_inline) {
1457 try ais.writer().writeAll("callconv(.Inline) ");1465 try ais.writer().writeAll("callconv(.Inline) ");
...@@ -1460,10 +1468,11 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S...@@ -1460,10 +1468,11 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S
1460 if (token_tags[maybe_bang] == .bang) {1468 if (token_tags[maybe_bang] == .bang) {
1461 try renderToken(ais, tree, maybe_bang, .none); // !1469 try renderToken(ais, tree, maybe_bang, .none); // !
1462 }1470 }
1463 return renderExpression(ais, tree, fn_proto.ast.return_type, space);1471 return renderExpression(gpa, ais, tree, fn_proto.ast.return_type, space);
1464}1472}
14651473
1466fn renderSwitchCase(1474fn renderSwitchCase(
1475 gpa: *Allocator,
1467 ais: *Ais,1476 ais: *Ais,
1468 tree: ast.Tree,1477 tree: ast.Tree,
1469 switch_case: ast.full.SwitchCase,1478 switch_case: ast.full.SwitchCase,
...@@ -1477,14 +1486,14 @@ fn renderSwitchCase(...@@ -1477,14 +1486,14 @@ fn renderSwitchCase(
1477 try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .space); // else keyword1486 try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .space); // else keyword
1478 } else if (switch_case.ast.values.len == 1) {1487 } else if (switch_case.ast.values.len == 1) {
1479 // render on one line and drop the trailing comma if any1488 // render on one line and drop the trailing comma if any
1480 try renderExpression(ais, tree, switch_case.ast.values[0], .space);1489 try renderExpression(gpa, ais, tree, switch_case.ast.values[0], .space);
1481 } else if (trailing_comma) {1490 } else if (trailing_comma) {
1482 // Render each value on a new line1491 // Render each value on a new line
1483 try renderExpressions(ais, tree, switch_case.ast.values, .comma);1492 try renderExpressions(gpa, ais, tree, switch_case.ast.values, .comma);
1484 } else {1493 } else {
1485 // Render on one line1494 // Render on one line
1486 for (switch_case.ast.values) |value_expr| {1495 for (switch_case.ast.values) |value_expr| {
1487 try renderExpression(ais, tree, value_expr, .comma_space);1496 try renderExpression(gpa, ais, tree, value_expr, .comma_space);
1488 }1497 }
1489 }1498 }
14901499
...@@ -1503,10 +1512,11 @@ fn renderSwitchCase(...@@ -1503,10 +1512,11 @@ fn renderSwitchCase(
1503 }1512 }
1504 }1513 }
15051514
1506 try renderExpression(ais, tree, switch_case.ast.target_expr, space);1515 try renderExpression(gpa, ais, tree, switch_case.ast.target_expr, space);
1507}1516}
15081517
1509fn renderBlock(1518fn renderBlock(
1519 gpa: *Allocator,
1510 ais: *Ais,1520 ais: *Ais,
1511 tree: ast.Tree,1521 tree: ast.Tree,
1512 block_node: ast.Node.Index,1522 block_node: ast.Node.Index,
...@@ -1533,11 +1543,11 @@ fn renderBlock(...@@ -1533,11 +1543,11 @@ fn renderBlock(
1533 for (statements) |stmt, i| {1543 for (statements) |stmt, i| {
1534 if (i != 0) try renderExtraNewline(ais, tree, stmt);1544 if (i != 0) try renderExtraNewline(ais, tree, stmt);
1535 switch (node_tags[stmt]) {1545 switch (node_tags[stmt]) {
1536 .global_var_decl => try renderVarDecl(ais, tree, tree.globalVarDecl(stmt)),1546 .global_var_decl => try renderVarDecl(gpa, ais, tree, tree.globalVarDecl(stmt)),
1537 .local_var_decl => try renderVarDecl(ais, tree, tree.localVarDecl(stmt)),1547 .local_var_decl => try renderVarDecl(gpa, ais, tree, tree.localVarDecl(stmt)),
1538 .simple_var_decl => try renderVarDecl(ais, tree, tree.simpleVarDecl(stmt)),1548 .simple_var_decl => try renderVarDecl(gpa, ais, tree, tree.simpleVarDecl(stmt)),
1539 .aligned_var_decl => try renderVarDecl(ais, tree, tree.alignedVarDecl(stmt)),1549 .aligned_var_decl => try renderVarDecl(gpa, ais, tree, tree.alignedVarDecl(stmt)),
1540 else => try renderExpression(ais, tree, stmt, .semicolon),1550 else => try renderExpression(gpa, ais, tree, stmt, .semicolon),
1541 }1551 }
1542 }1552 }
1543 }1553 }
...@@ -1548,6 +1558,7 @@ fn renderBlock(...@@ -1548,6 +1558,7 @@ fn renderBlock(
15481558
1549// TODO: handle comments between fields1559// TODO: handle comments between fields
1550fn renderStructInit(1560fn renderStructInit(
1561 gpa: *Allocator,
1551 ais: *Ais,1562 ais: *Ais,
1552 tree: ast.Tree,1563 tree: ast.Tree,
1553 struct_init: ast.full.StructInit,1564 struct_init: ast.full.StructInit,
...@@ -1557,7 +1568,7 @@ fn renderStructInit(...@@ -1557,7 +1568,7 @@ fn renderStructInit(
1557 if (struct_init.ast.type_expr == 0) {1568 if (struct_init.ast.type_expr == 0) {
1558 try renderToken(ais, tree, struct_init.ast.lbrace - 1, .none); // .1569 try renderToken(ais, tree, struct_init.ast.lbrace - 1, .none); // .
1559 } else {1570 } else {
1560 try renderExpression(ais, tree, struct_init.ast.type_expr, .none); // T1571 try renderExpression(gpa, ais, tree, struct_init.ast.type_expr, .none); // T
1561 }1572 }
1562 if (struct_init.ast.fields.len == 0) {1573 if (struct_init.ast.fields.len == 0) {
1563 try renderToken(ais, tree, struct_init.ast.lbrace, .none); // lbrace1574 try renderToken(ais, tree, struct_init.ast.lbrace, .none); // lbrace
...@@ -1573,7 +1584,7 @@ fn renderStructInit(...@@ -1573,7 +1584,7 @@ fn renderStructInit(
1573 try renderToken(ais, tree, struct_init.ast.lbrace + 1, .none); // .1584 try renderToken(ais, tree, struct_init.ast.lbrace + 1, .none); // .
1574 try renderToken(ais, tree, struct_init.ast.lbrace + 2, .space); // name1585 try renderToken(ais, tree, struct_init.ast.lbrace + 2, .space); // name
1575 try renderToken(ais, tree, struct_init.ast.lbrace + 3, .space); // =1586 try renderToken(ais, tree, struct_init.ast.lbrace + 3, .space); // =
1576 try renderExpression(ais, tree, struct_init.ast.fields[0], .comma);1587 try renderExpression(gpa, ais, tree, struct_init.ast.fields[0], .comma);
15771588
1578 for (struct_init.ast.fields[1..]) |field_init| {1589 for (struct_init.ast.fields[1..]) |field_init| {
1579 const init_token = tree.firstToken(field_init);1590 const init_token = tree.firstToken(field_init);
...@@ -1581,7 +1592,7 @@ fn renderStructInit(...@@ -1581,7 +1592,7 @@ fn renderStructInit(
1581 try renderToken(ais, tree, init_token - 3, .none); // .1592 try renderToken(ais, tree, init_token - 3, .none); // .
1582 try renderToken(ais, tree, init_token - 2, .space); // name1593 try renderToken(ais, tree, init_token - 2, .space); // name
1583 try renderToken(ais, tree, init_token - 1, .space); // =1594 try renderToken(ais, tree, init_token - 1, .space); // =
1584 try renderExpression(ais, tree, field_init, .comma);1595 try renderExpression(gpa, ais, tree, field_init, .comma);
1585 }1596 }
15861597
1587 ais.popIndent();1598 ais.popIndent();
...@@ -1595,7 +1606,7 @@ fn renderStructInit(...@@ -1595,7 +1606,7 @@ fn renderStructInit(
1595 try renderToken(ais, tree, init_token - 3, .none); // .1606 try renderToken(ais, tree, init_token - 3, .none); // .
1596 try renderToken(ais, tree, init_token - 2, .space); // name1607 try renderToken(ais, tree, init_token - 2, .space); // name
1597 try renderToken(ais, tree, init_token - 1, .space); // =1608 try renderToken(ais, tree, init_token - 1, .space); // =
1598 try renderExpression(ais, tree, field_init, .comma_space);1609 try renderExpression(gpa, ais, tree, field_init, .comma_space);
1599 }1610 }
16001611
1601 return renderToken(ais, tree, last_field_token + 1, space); // rbrace1612 return renderToken(ais, tree, last_field_token + 1, space); // rbrace
...@@ -1604,16 +1615,19 @@ fn renderStructInit(...@@ -1604,16 +1615,19 @@ fn renderStructInit(
16041615
1605// TODO: handle comments between elements1616// TODO: handle comments between elements
1606fn renderArrayInit(1617fn renderArrayInit(
1618 gpa: *Allocator,
1607 ais: *Ais,1619 ais: *Ais,
1608 tree: ast.Tree,1620 tree: ast.Tree,
1609 array_init: ast.full.ArrayInit,1621 array_init: ast.full.ArrayInit,
1610 space: Space,1622 space: Space,
1611) Error!void {1623) Error!void {
1612 const token_tags = tree.tokens.items(.tag);1624 const token_tags = tree.tokens.items(.tag);
1625 const token_starts = tree.tokens.items(.start);
1626
1613 if (array_init.ast.type_expr == 0) {1627 if (array_init.ast.type_expr == 0) {
1614 try renderToken(ais, tree, array_init.ast.lbrace - 1, .none); // .1628 try renderToken(ais, tree, array_init.ast.lbrace - 1, .none); // .
1615 } else {1629 } else {
1616 try renderExpression(ais, tree, array_init.ast.type_expr, .none); // T1630 try renderExpression(gpa, ais, tree, array_init.ast.type_expr, .none); // T
1617 }1631 }
16181632
1619 if (array_init.ast.elements.len == 0) {1633 if (array_init.ast.elements.len == 0) {
...@@ -1626,30 +1640,172 @@ fn renderArrayInit(...@@ -1626,30 +1640,172 @@ fn renderArrayInit(
1626 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];1640 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
1627 const last_elem_token = tree.lastToken(last_elem);1641 const last_elem_token = tree.lastToken(last_elem);
1628 const trailing_comma = token_tags[last_elem_token + 1] == .comma;1642 const trailing_comma = token_tags[last_elem_token + 1] == .comma;
1629 if (trailing_comma) {1643 if (!trailing_comma) {
1630 // Render one element per line.
1631 ais.pushIndentNextLine();
1632 try renderToken(ais, tree, array_init.ast.lbrace, .newline);
1633 try renderExpressions(ais, tree, array_init.ast.elements, .comma);
1634 ais.popIndent();
1635 return renderToken(ais, tree, last_elem_token + 2, space); // rbrace
1636 } else {
1637 // Render all on one line, no trailing comma.1644 // Render all on one line, no trailing comma.
1638 if (array_init.ast.elements.len == 1) {1645 if (array_init.ast.elements.len == 1) {
1639 // If there is only one element, we don't use spaces1646 // If there is only one element, we don't use spaces
1640 try renderToken(ais, tree, array_init.ast.lbrace, .none);1647 try renderToken(ais, tree, array_init.ast.lbrace, .none);
1641 try renderExpression(ais, tree, array_init.ast.elements[0], .none);1648 try renderExpression(gpa, ais, tree, array_init.ast.elements[0], .none);
1642 } else {1649 } else {
1643 try renderToken(ais, tree, array_init.ast.lbrace, .space);1650 try renderToken(ais, tree, array_init.ast.lbrace, .space);
1644 for (array_init.ast.elements) |elem| {1651 for (array_init.ast.elements) |elem| {
1645 try renderExpression(ais, tree, elem, .comma_space);1652 try renderExpression(gpa, ais, tree, elem, .comma_space);
1646 }1653 }
1647 }1654 }
1648 return renderToken(ais, tree, last_elem_token + 1, space); // rbrace1655 return renderToken(ais, tree, last_elem_token + 1, space); // rbrace
1649 }1656 }
1657
1658 ais.pushIndentNextLine();
1659 try renderToken(ais, tree, array_init.ast.lbrace, .newline);
1660
1661 const rbrace = last_elem_token + 2;
1662 assert(token_tags[rbrace] == .r_brace);
1663
1664 var expr_index: usize = 0;
1665 while (rowSize(tree, array_init.ast.elements[expr_index..], rbrace)) |row_size| {
1666 const row_exprs = array_init.ast.elements[expr_index..];
1667 // A place to store the width of each expression and its column's maximum
1668 const widths = try gpa.alloc(usize, row_exprs.len + row_size);
1669 defer gpa.free(widths);
1670 mem.set(usize, widths, 0);
1671
1672 const expr_newlines = try gpa.alloc(bool, row_exprs.len);
1673 defer gpa.free(expr_newlines);
1674 mem.set(bool, expr_newlines, false);
1675
1676 const expr_widths = widths[0 .. widths.len - row_size];
1677 const column_widths = widths[widths.len - row_size ..];
1678
1679 // Find next row with trailing comment (if any) to end the current section
1680 const section_end = sec_end: {
1681 var this_line_first_expr: usize = 0;
1682 var this_line_size = rowSize(tree, row_exprs, rbrace);
1683 for (row_exprs) |expr, i| {
1684 // Ignore comment on first line of this section
1685 if (i == 0 or tree.tokensOnSameLine(tree.firstToken(row_exprs[0]), tree.lastToken(expr))) continue;
1686 // Track start of line containing comment
1687 if (!tree.tokensOnSameLine(tree.firstToken(row_exprs[this_line_first_expr]), tree.lastToken(expr))) {
1688 this_line_first_expr = i;
1689 this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rbrace);
1690 }
1691
1692 const maybe_comma = tree.lastToken(expr) + 1;
1693 if (token_tags[maybe_comma] == .comma) {
1694 const after_comma_src = tree.source[token_starts[maybe_comma]..token_starts[maybe_comma + 1]];
1695 const same_line_comment = for (after_comma_src) |byte| switch (byte) {
1696 '\n' => break,
1697 '/' => break :sec_end i - this_line_size.? + 1, // Found row ending in comment
1698 else => continue,
1699 };
1700 }
1701 }
1702 break :sec_end row_exprs.len;
1703 };
1704 expr_index += section_end;
1705
1706 const section_exprs = row_exprs[0..section_end];
1707
1708 var sub_expr_buffer = std.ArrayList(u8).init(gpa);
1709 defer sub_expr_buffer.deinit();
1710
1711 var auto_indenting_stream = Ais{
1712 .indent_delta = indent_delta,
1713 .underlying_writer = sub_expr_buffer.writer(),
1714 };
1715
1716 // Calculate size of columns in current section
1717 var column_counter: usize = 0;
1718 var single_line = true;
1719 var contains_newline = false;
1720 for (section_exprs) |expr, i| {
1721 sub_expr_buffer.shrinkRetainingCapacity(0);
1722 if (i + 1 < section_exprs.len) {
1723 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .none);
1724 const width = sub_expr_buffer.items.len;
1725 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items, '\n') != null;
1726 contains_newline = contains_newline or this_contains_newline;
1727 expr_widths[i] = width;
1728 expr_newlines[i] = this_contains_newline;
1729
1730 if (!this_contains_newline) {
1731 const column = column_counter % row_size;
1732 column_widths[column] = std.math.max(column_widths[column], width);
1733
1734 const expr_last_token = tree.lastToken(expr) + 1;
1735 const next_expr = section_exprs[i + 1];
1736 column_counter += 1;
1737 if (!tree.tokensOnSameLine(expr_last_token, tree.firstToken(next_expr))) single_line = false;
1738 } else {
1739 single_line = false;
1740 column_counter = 0;
1741 }
1742 } else {
1743 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .none);
1744 const width = sub_expr_buffer.items.len;
1745 contains_newline = contains_newline or mem.indexOfScalar(u8, sub_expr_buffer.items, '\n') != null;
1746 expr_widths[i] = width;
1747 expr_newlines[i] = contains_newline;
1748
1749 if (!contains_newline) {
1750 const column = column_counter % row_size;
1751 column_widths[column] = std.math.max(column_widths[column], width);
1752 }
1753 break;
1754 }
1755 }
1756
1757 // Render exprs in current section
1758 column_counter = 0;
1759 var last_col_index: usize = row_size - 1;
1760 for (section_exprs) |expr, i| {
1761 if (i + 1 < section_exprs.len) {
1762 const next_expr = section_exprs[i + 1];
1763 try renderExpression(gpa, ais, tree, expr, .none);
1764
1765 const comma = tree.lastToken(expr) + 1;
1766
1767 if (column_counter != last_col_index) {
1768 if (!expr_newlines[i] and !expr_newlines[i + 1]) {
1769 // Neither the current or next expression is multiline
1770 try renderToken(ais, tree, comma, .space); // ,
1771 assert(column_widths[column_counter % row_size] >= expr_widths[i]);
1772 const padding = column_widths[column_counter % row_size] - expr_widths[i];
1773 try ais.writer().writeByteNTimes(' ', padding);
1774
1775 column_counter += 1;
1776 continue;
1777 }
1778 }
1779 if (single_line and row_size != 1) {
1780 try renderToken(ais, tree, comma, .space); // ,
1781 continue;
1782 }
1783
1784 column_counter = 0;
1785 try renderToken(ais, tree, comma, .newline); // ,
1786 try renderExtraNewline(ais, tree, next_expr);
1787 } else {
1788 const maybe_comma = tree.lastToken(expr) + 1;
1789 if (token_tags[maybe_comma] == .comma) {
1790 try renderExpression(gpa, ais, tree, expr, .none); // ,
1791 try renderToken(ais, tree, maybe_comma, .newline); // ,
1792 } else {
1793 try renderExpression(gpa, ais, tree, expr, .comma); // ,
1794 }
1795 }
1796 }
1797
1798 if (expr_index == array_init.ast.elements.len) {
1799 break;
1800 }
1801 }
1802
1803 ais.popIndent();
1804 return renderToken(ais, tree, rbrace, space); // rbrace
1650}1805}
16511806
1652fn renderContainerDecl(1807fn renderContainerDecl(
1808 gpa: *Allocator,
1653 ais: *Ais,1809 ais: *Ais,
1654 tree: ast.Tree,1810 tree: ast.Tree,
1655 container_decl: ast.full.ContainerDecl,1811 container_decl: ast.full.ContainerDecl,
...@@ -1669,7 +1825,7 @@ fn renderContainerDecl(...@@ -1669,7 +1825,7 @@ fn renderContainerDecl(
1669 try renderToken(ais, tree, enum_token, .none); // enum1825 try renderToken(ais, tree, enum_token, .none); // enum
1670 if (container_decl.ast.arg != 0) {1826 if (container_decl.ast.arg != 0) {
1671 try renderToken(ais, tree, enum_token + 1, .none); // lparen1827 try renderToken(ais, tree, enum_token + 1, .none); // lparen
1672 try renderExpression(ais, tree, container_decl.ast.arg, .none);1828 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);
1673 const rparen = tree.lastToken(container_decl.ast.arg) + 1;1829 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
1674 try renderToken(ais, tree, rparen, .none); // rparen1830 try renderToken(ais, tree, rparen, .none); // rparen
1675 try renderToken(ais, tree, rparen + 1, .space); // rparen1831 try renderToken(ais, tree, rparen + 1, .space); // rparen
...@@ -1681,7 +1837,7 @@ fn renderContainerDecl(...@@ -1681,7 +1837,7 @@ fn renderContainerDecl(
1681 } else if (container_decl.ast.arg != 0) {1837 } else if (container_decl.ast.arg != 0) {
1682 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union1838 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union
1683 try renderToken(ais, tree, container_decl.ast.main_token + 1, .none); // lparen1839 try renderToken(ais, tree, container_decl.ast.main_token + 1, .none); // lparen
1684 try renderExpression(ais, tree, container_decl.ast.arg, .none);1840 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);
1685 const rparen = tree.lastToken(container_decl.ast.arg) + 1;1841 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
1686 try renderToken(ais, tree, rparen, .space); // rparen1842 try renderToken(ais, tree, rparen, .space); // rparen
1687 lbrace = rparen + 1;1843 lbrace = rparen + 1;
...@@ -1717,7 +1873,7 @@ fn renderContainerDecl(...@@ -1717,7 +1873,7 @@ fn renderContainerDecl(
1717 // All the declarations on the same line.1873 // All the declarations on the same line.
1718 try renderToken(ais, tree, lbrace, .space); // lbrace1874 try renderToken(ais, tree, lbrace, .space); // lbrace
1719 for (container_decl.ast.members) |member| {1875 for (container_decl.ast.members) |member| {
1720 try renderMember(ais, tree, member, .space);1876 try renderMember(gpa, ais, tree, member, .space);
1721 }1877 }
1722 return renderToken(ais, tree, rbrace, space); // rbrace1878 return renderToken(ais, tree, rbrace, space); // rbrace
1723 }1879 }
...@@ -1725,13 +1881,14 @@ fn renderContainerDecl(...@@ -1725,13 +1881,14 @@ fn renderContainerDecl(
1725 // One member per line.1881 // One member per line.
1726 ais.pushIndentNextLine();1882 ais.pushIndentNextLine();
1727 try renderToken(ais, tree, lbrace, .newline); // lbrace1883 try renderToken(ais, tree, lbrace, .newline); // lbrace
1728 try renderMembers(ais, tree, container_decl.ast.members);1884 try renderMembers(gpa, ais, tree, container_decl.ast.members);
1729 ais.popIndent();1885 ais.popIndent();
17301886
1731 return renderToken(ais, tree, rbrace, space); // rbrace1887 return renderToken(ais, tree, rbrace, space); // rbrace
1732}1888}
17331889
1734fn renderAsm(1890fn renderAsm(
1891 gpa: *Allocator,
1735 ais: *Ais,1892 ais: *Ais,
1736 tree: ast.Tree,1893 tree: ast.Tree,
1737 asm_node: ast.full.Asm,1894 asm_node: ast.full.Asm,
...@@ -1749,7 +1906,7 @@ fn renderAsm(...@@ -1749,7 +1906,7 @@ fn renderAsm(
1749 }1906 }
17501907
1751 if (asm_node.ast.items.len == 0) {1908 if (asm_node.ast.items.len == 0) {
1752 try renderExpression(ais, tree, asm_node.ast.template, .none);1909 try renderExpression(gpa, ais, tree, asm_node.ast.template, .none);
1753 if (asm_node.first_clobber) |first_clobber| {1910 if (asm_node.first_clobber) |first_clobber| {
1754 // asm ("foo" ::: "a", "b")1911 // asm ("foo" ::: "a", "b")
1755 var tok_i = first_clobber;1912 var tok_i = first_clobber;
...@@ -1769,7 +1926,7 @@ fn renderAsm(...@@ -1769,7 +1926,7 @@ fn renderAsm(
1769 }1926 }
17701927
1771 ais.pushIndent();1928 ais.pushIndent();
1772 try renderExpression(ais, tree, asm_node.ast.template, .newline);1929 try renderExpression(gpa, ais, tree, asm_node.ast.template, .newline);
1773 ais.setIndentDelta(asm_indent_delta);1930 ais.setIndentDelta(asm_indent_delta);
1774 const colon1 = tree.lastToken(asm_node.ast.template) + 1;1931 const colon1 = tree.lastToken(asm_node.ast.template) + 1;
17751932
...@@ -1783,19 +1940,19 @@ fn renderAsm(...@@ -1783,19 +1940,19 @@ fn renderAsm(
1783 for (asm_node.outputs) |asm_output, i| {1940 for (asm_node.outputs) |asm_output, i| {
1784 if (i + 1 < asm_node.outputs.len) {1941 if (i + 1 < asm_node.outputs.len) {
1785 const next_asm_output = asm_node.outputs[i + 1];1942 const next_asm_output = asm_node.outputs[i + 1];
1786 try renderAsmOutput(ais, tree, asm_output, .none);1943 try renderAsmOutput(gpa, ais, tree, asm_output, .none);
17871944
1788 const comma = tree.firstToken(next_asm_output) - 1;1945 const comma = tree.firstToken(next_asm_output) - 1;
1789 try renderToken(ais, tree, comma, .newline); // ,1946 try renderToken(ais, tree, comma, .newline); // ,
1790 try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));1947 try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));
1791 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {1948 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
1792 try renderAsmOutput(ais, tree, asm_output, .newline);1949 try renderAsmOutput(gpa, ais, tree, asm_output, .newline);
1793 ais.popIndent();1950 ais.popIndent();
1794 ais.setIndentDelta(indent_delta);1951 ais.setIndentDelta(indent_delta);
1795 ais.popIndent();1952 ais.popIndent();
1796 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen1953 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
1797 } else {1954 } else {
1798 try renderAsmOutput(ais, tree, asm_output, .newline);1955 try renderAsmOutput(gpa, ais, tree, asm_output, .newline);
1799 const comma_or_colon = tree.lastToken(asm_output) + 1;1956 const comma_or_colon = tree.lastToken(asm_output) + 1;
1800 ais.popIndent();1957 ais.popIndent();
1801 break :colon2 switch (token_tags[comma_or_colon]) {1958 break :colon2 switch (token_tags[comma_or_colon]) {
...@@ -1815,19 +1972,19 @@ fn renderAsm(...@@ -1815,19 +1972,19 @@ fn renderAsm(
1815 for (asm_node.inputs) |asm_input, i| {1972 for (asm_node.inputs) |asm_input, i| {
1816 if (i + 1 < asm_node.inputs.len) {1973 if (i + 1 < asm_node.inputs.len) {
1817 const next_asm_input = asm_node.inputs[i + 1];1974 const next_asm_input = asm_node.inputs[i + 1];
1818 try renderAsmInput(ais, tree, asm_input, .none);1975 try renderAsmInput(gpa, ais, tree, asm_input, .none);
18191976
1820 const first_token = tree.firstToken(next_asm_input);1977 const first_token = tree.firstToken(next_asm_input);
1821 try renderToken(ais, tree, first_token - 1, .newline); // ,1978 try renderToken(ais, tree, first_token - 1, .newline); // ,
1822 try renderExtraNewlineToken(ais, tree, first_token);1979 try renderExtraNewlineToken(ais, tree, first_token);
1823 } else if (asm_node.first_clobber == null) {1980 } else if (asm_node.first_clobber == null) {
1824 try renderAsmInput(ais, tree, asm_input, .newline);1981 try renderAsmInput(gpa, ais, tree, asm_input, .newline);
1825 ais.popIndent();1982 ais.popIndent();
1826 ais.setIndentDelta(indent_delta);1983 ais.setIndentDelta(indent_delta);
1827 ais.popIndent();1984 ais.popIndent();
1828 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen1985 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
1829 } else {1986 } else {
1830 try renderAsmInput(ais, tree, asm_input, .newline);1987 try renderAsmInput(gpa, ais, tree, asm_input, .newline);
1831 const comma_or_colon = tree.lastToken(asm_input) + 1;1988 const comma_or_colon = tree.lastToken(asm_input) + 1;
1832 ais.popIndent();1989 ais.popIndent();
1833 break :colon3 switch (token_tags[comma_or_colon]) {1990 break :colon3 switch (token_tags[comma_or_colon]) {
...@@ -1861,6 +2018,7 @@ fn renderAsm(...@@ -1861,6 +2018,7 @@ fn renderAsm(
1861}2018}
18622019
1863fn renderCall(2020fn renderCall(
2021 gpa: *Allocator,
1864 ais: *Ais,2022 ais: *Ais,
1865 tree: ast.Tree,2023 tree: ast.Tree,
1866 call: ast.full.Call,2024 call: ast.full.Call,
...@@ -1872,7 +2030,7 @@ fn renderCall(...@@ -1872,7 +2030,7 @@ fn renderCall(
1872 if (call.async_token) |async_token| {2030 if (call.async_token) |async_token| {
1873 try renderToken(ais, tree, async_token, .space);2031 try renderToken(ais, tree, async_token, .space);
1874 }2032 }
1875 try renderExpression(ais, tree, call.ast.fn_expr, .none);2033 try renderExpression(gpa, ais, tree, call.ast.fn_expr, .none);
18762034
1877 const lparen = call.ast.lparen;2035 const lparen = call.ast.lparen;
1878 const params = call.ast.params;2036 const params = call.ast.params;
...@@ -1890,7 +2048,7 @@ fn renderCall(...@@ -1890,7 +2048,7 @@ fn renderCall(
1890 try renderToken(ais, tree, lparen, .newline); // (2048 try renderToken(ais, tree, lparen, .newline); // (
1891 for (params) |param_node, i| {2049 for (params) |param_node, i| {
1892 if (i + 1 < params.len) {2050 if (i + 1 < params.len) {
1893 try renderExpression(ais, tree, param_node, .none);2051 try renderExpression(gpa, ais, tree, param_node, .none);
18942052
1895 // Unindent the comma for multiline string literals.2053 // Unindent the comma for multiline string literals.
1896 const is_multiline_string =2054 const is_multiline_string =
...@@ -1904,7 +2062,7 @@ fn renderCall(...@@ -1904,7 +2062,7 @@ fn renderCall(
19042062
1905 try renderExtraNewline(ais, tree, params[i + 1]);2063 try renderExtraNewline(ais, tree, params[i + 1]);
1906 } else {2064 } else {
1907 try renderExpression(ais, tree, param_node, .comma);2065 try renderExpression(gpa, ais, tree, param_node, .comma);
1908 }2066 }
1909 }2067 }
1910 ais.popIndent();2068 ais.popIndent();
...@@ -1919,7 +2077,7 @@ fn renderCall(...@@ -1919,7 +2077,7 @@ fn renderCall(
1919 if (this_multiline_string) {2077 if (this_multiline_string) {
1920 ais.pushIndentOneShot();2078 ais.pushIndentOneShot();
1921 }2079 }
1922 try renderExpression(ais, tree, param_node, .none);2080 try renderExpression(gpa, ais, tree, param_node, .none);
19232081
1924 if (i + 1 < params.len) {2082 if (i + 1 < params.len) {
1925 const comma = tree.lastToken(param_node) + 1;2083 const comma = tree.lastToken(param_node) + 1;
...@@ -1934,14 +2092,14 @@ fn renderCall(...@@ -1934,14 +2092,14 @@ fn renderCall(
1934}2092}
19352093
1936/// Render an expression, and the comma that follows it, if it is present in the source.2094/// Render an expression, and the comma that follows it, if it is present in the source.
1937fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {2095fn renderExpressionComma(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
1938 const token_tags = tree.tokens.items(.tag);2096 const token_tags = tree.tokens.items(.tag);
1939 const maybe_comma = tree.lastToken(node) + 1;2097 const maybe_comma = tree.lastToken(node) + 1;
1940 if (token_tags[maybe_comma] == .comma) {2098 if (token_tags[maybe_comma] == .comma) {
1941 try renderExpression(ais, tree, node, .none);2099 try renderExpression(gpa, ais, tree, node, .none);
1942 return renderToken(ais, tree, maybe_comma, space);2100 return renderToken(ais, tree, maybe_comma, space);
1943 } else {2101 } else {
1944 return renderExpression(ais, tree, node, space);2102 return renderExpression(gpa, ais, tree, node, space);
1945 }2103 }
1946}2104}
19472105
...@@ -2218,6 +2376,32 @@ fn nodeCausesSliceOpSpace(tag: ast.Node.Tag) bool {...@@ -2218,6 +2376,32 @@ fn nodeCausesSliceOpSpace(tag: ast.Node.Tag) bool {
2218 };2376 };
2219}2377}
22202378
2379// Returns the number of nodes in `expr` that are on the same line as `rtoken`,
2380// or null if they all are on the same line.
2381fn rowSize(tree: ast.Tree, exprs: []const ast.Node.Index, rtoken: ast.TokenIndex) ?usize {
2382 const token_tags = tree.tokens.items(.tag);
2383
2384 const first_token = tree.firstToken(exprs[0]);
2385 if (tree.tokensOnSameLine(first_token, rtoken)) {
2386 const maybe_comma = rtoken - 1;
2387 if (token_tags[maybe_comma] == .comma)
2388 return 1;
2389 return null; // no newlines
2390 }
2391
2392 var count: usize = 1;
2393 for (exprs) |expr, i| {
2394 if (i + 1 < exprs.len) {
2395 const expr_last_token = tree.lastToken(expr) + 1;
2396 if (!tree.tokensOnSameLine(expr_last_token, tree.firstToken(exprs[i + 1]))) return count;
2397 count += 1;
2398 } else {
2399 return count;
2400 }
2401 }
2402 unreachable;
2403}
2404
2221/// Automatically inserts indentation of written data by keeping2405/// Automatically inserts indentation of written data by keeping
2222/// track of the current indentation level2406/// track of the current indentation level
2223fn AutoIndentingStream(comptime UnderlyingWriter: type) type {2407fn AutoIndentingStream(comptime UnderlyingWriter: type) type {