authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-02 14:44:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-03 20:05:32-07:00
log3263d6e6aba197656ba6b0e35330ce4d756eaf60
treef5179707f71963869c1b6041696cb30ee485d0e5
parentf8c24c2cd012a93fd005480411bf0936933e2fbb

std.zig: move render state to struct; add fixups


2 files changed, 710 insertions(+), 662 deletions(-)

lib/std/zig/Ast.zig+5-2
......@@ -117,8 +117,10 @@ pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 {
117117 return buffer.toOwnedSlice();
118118}
119119
120pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8)) RenderError!void {
121 return @import("./render.zig").renderTree(buffer, tree);
120pub const Fixups = private_render.Fixups;
121
122pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8), fixups: Fixups) RenderError!void {
123 return @import("./render.zig").renderTree(buffer, tree, fixups);
122124}
123125
124126/// Returns an extra offset for column and byte offset of errors that
......@@ -3530,6 +3532,7 @@ const Token = std.zig.Token;
35303532const Ast = @This();
35313533const Allocator = std.mem.Allocator;
35323534const Parse = @import("Parse.zig");
3535const private_render = @import("./render.zig");
35333536
35343537test {
35353538 testing.refAllDecls(@This());
lib/std/zig/render.zig+705-660
......@@ -14,49 +14,75 @@ pub const Error = Ast.RenderError;
1414
1515const Ais = AutoIndentingStream(std.ArrayList(u8).Writer);
1616
17pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast) Error!void {
17pub const Fixups = struct {
18 /// The key is the mut token (`var`/`const`) of the variable declaration
19 /// that should have a `_ = foo;` inserted afterwards.
20 unused_var_decls: std.AutoHashMapUnmanaged(Ast.TokenIndex, void) = .{},
21
22 pub fn count(f: Fixups) usize {
23 return f.unused_var_decls.count();
24 }
25
26 pub fn deinit(f: *Fixups, gpa: Allocator) void {
27 f.unused_var_decls.deinit(gpa);
28 f.* = undefined;
29 }
30};
31
32const Render = struct {
33 gpa: Allocator,
34 ais: *Ais,
35 tree: Ast,
36 fixups: Fixups,
37};
38
39pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!void {
1840 assert(tree.errors.len == 0); // Cannot render an invalid tree.
1941 var auto_indenting_stream = Ais{
2042 .indent_delta = indent_delta,
2143 .underlying_writer = buffer.writer(),
2244 };
23 const ais = &auto_indenting_stream;
45 var r: Render = .{
46 .gpa = buffer.allocator,
47 .ais = &auto_indenting_stream,
48 .tree = tree,
49 .fixups = fixups,
50 };
2451
2552 // Render all the line comments at the beginning of the file.
2653 const comment_end_loc = tree.tokens.items(.start)[0];
27 _ = try renderComments(ais, tree, 0, comment_end_loc);
54 _ = try renderComments(r, 0, comment_end_loc);
2855
2956 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {
30 try renderContainerDocComments(ais, tree, 0);
57 try renderContainerDocComments(r, 0);
3158 }
3259
3360 if (tree.mode == .zon) {
3461 try renderExpression(
35 buffer.allocator,
36 ais,
37 tree,
62 r,
3863 tree.nodes.items(.data)[0].lhs,
3964 .newline,
4065 );
4166 } else {
42 try renderMembers(buffer.allocator, ais, tree, tree.rootDecls());
67 try renderMembers(r, tree.rootDecls());
4368 }
4469
45 if (ais.disabled_offset) |disabled_offset| {
46 try writeFixingWhitespace(ais.underlying_writer, tree.source[disabled_offset..]);
70 if (auto_indenting_stream.disabled_offset) |disabled_offset| {
71 try writeFixingWhitespace(auto_indenting_stream.underlying_writer, tree.source[disabled_offset..]);
4772 }
4873}
4974
5075/// Render all members in the given slice, keeping empty lines where appropriate
51fn renderMembers(gpa: Allocator, ais: *Ais, tree: Ast, members: []const Ast.Node.Index) Error!void {
76fn renderMembers(r: Render, members: []const Ast.Node.Index) Error!void {
77 const tree = r.tree;
5278 if (members.len == 0) return;
5379 const container: Container = for (members) |member| {
5480 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
5581 } else .tuple;
56 try renderMember(gpa, ais, tree, container, members[0], .newline);
82 try renderMember(r, container, members[0], .newline);
5783 for (members[1..]) |member| {
58 try renderExtraNewline(ais, tree, member);
59 try renderMember(gpa, ais, tree, container, member, .newline);
84 try renderExtraNewline(r, member);
85 try renderMember(r, container, member, .newline);
6086 }
6187}
6288
......@@ -67,17 +93,17 @@ const Container = enum {
6793};
6894
6995fn renderMember(
70 gpa: Allocator,
71 ais: *Ais,
72 tree: Ast,
96 r: Render,
7397 container: Container,
7498 decl: Ast.Node.Index,
7599 space: Space,
76100) Error!void {
101 const tree = r.tree;
102 const ais = r.ais;
77103 const token_tags = tree.tokens.items(.tag);
78104 const main_tokens = tree.nodes.items(.main_token);
79105 const datas = tree.nodes.items(.data);
80 try renderDocComments(ais, tree, tree.firstToken(decl));
106 try renderDocComments(r, tree.firstToken(decl));
81107 switch (tree.nodes.items(.tag)[decl]) {
82108 .fn_decl => {
83109 // Some examples:
......@@ -105,7 +131,7 @@ fn renderMember(
105131 }
106132 }
107133 while (i < fn_token) : (i += 1) {
108 try renderToken(ais, tree, i, .space);
134 try renderToken(r, i, .space);
109135 }
110136 switch (tree.nodes.items(.tag)[fn_proto]) {
111137 .fn_proto_one, .fn_proto => {
......@@ -123,8 +149,8 @@ fn renderMember(
123149 else => unreachable,
124150 }
125151 assert(datas[decl].rhs != 0);
126 try renderExpression(gpa, ais, tree, fn_proto, .space);
127 return renderExpression(gpa, ais, tree, datas[decl].rhs, space);
152 try renderExpression(r, fn_proto, .space);
153 return renderExpression(r, datas[decl].rhs, space);
128154 },
129155 .fn_proto_simple,
130156 .fn_proto_multi,
......@@ -153,47 +179,47 @@ fn renderMember(
153179 }
154180 }
155181 while (i < fn_token) : (i += 1) {
156 try renderToken(ais, tree, i, .space);
182 try renderToken(r, i, .space);
157183 }
158 try renderExpression(gpa, ais, tree, decl, .none);
159 return renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon
184 try renderExpression(r, decl, .none);
185 return renderToken(r, tree.lastToken(decl) + 1, space); // semicolon
160186 },
161187
162188 .@"usingnamespace" => {
163189 const main_token = main_tokens[decl];
164190 const expr = datas[decl].lhs;
165191 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {
166 try renderToken(ais, tree, main_token - 1, .space); // pub
192 try renderToken(r, main_token - 1, .space); // pub
167193 }
168 try renderToken(ais, tree, main_token, .space); // usingnamespace
169 try renderExpression(gpa, ais, tree, expr, .none);
170 return renderToken(ais, tree, tree.lastToken(expr) + 1, space); // ;
194 try renderToken(r, main_token, .space); // usingnamespace
195 try renderExpression(r, expr, .none);
196 return renderToken(r, tree.lastToken(expr) + 1, space); // ;
171197 },
172198
173199 .global_var_decl,
174200 .local_var_decl,
175201 .simple_var_decl,
176202 .aligned_var_decl,
177 => return renderVarDecl(gpa, ais, tree, tree.fullVarDecl(decl).?, false, .semicolon),
203 => return renderVarDecl(r, tree.fullVarDecl(decl).?, false, .semicolon),
178204
179205 .test_decl => {
180206 const test_token = main_tokens[decl];
181 try renderToken(ais, tree, test_token, .space);
207 try renderToken(r, test_token, .space);
182208 const test_name_tag = token_tags[test_token + 1];
183209 switch (test_name_tag) {
184 .string_literal => try renderToken(ais, tree, test_token + 1, .space),
185 .identifier => try renderIdentifier(ais, tree, test_token + 1, .space, .preserve_when_shadowing),
210 .string_literal => try renderToken(r, test_token + 1, .space),
211 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),
186212 else => {},
187213 }
188 try renderExpression(gpa, ais, tree, datas[decl].rhs, space);
214 try renderExpression(r, datas[decl].rhs, space);
189215 },
190216
191217 .container_field_init,
192218 .container_field_align,
193219 .container_field,
194 => return renderContainerField(gpa, ais, tree, container, tree.fullContainerField(decl).?, space),
220 => return renderContainerField(r, container, tree.fullContainerField(decl).?, space),
195221
196 .@"comptime" => return renderExpression(gpa, ais, tree, decl, space),
222 .@"comptime" => return renderExpression(r, decl, space),
197223
198224 .root => unreachable,
199225 else => unreachable,
......@@ -201,16 +227,18 @@ fn renderMember(
201227}
202228
203229/// Render all expressions in the slice, keeping empty lines where appropriate
204fn renderExpressions(gpa: Allocator, ais: *Ais, tree: Ast, expressions: []const Ast.Node.Index, space: Space) Error!void {
230fn renderExpressions(r: Render, expressions: []const Ast.Node.Index, space: Space) Error!void {
205231 if (expressions.len == 0) return;
206 try renderExpression(gpa, ais, tree, expressions[0], space);
232 try renderExpression(r, expressions[0], space);
207233 for (expressions[1..]) |expression| {
208 try renderExtraNewline(ais, tree, expression);
209 try renderExpression(gpa, ais, tree, expression, space);
234 try renderExtraNewline(r, expression);
235 try renderExpression(r, expression, space);
210236 }
211237}
212238
213fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index, space: Space) Error!void {
239fn renderExpression(r: Render, node: Ast.Node.Index, space: Space) Error!void {
240 const tree = r.tree;
241 const ais = r.ais;
214242 const token_tags = tree.tokens.items(.tag);
215243 const main_tokens = tree.nodes.items(.main_token);
216244 const node_tags = tree.nodes.items(.tag);
......@@ -218,7 +246,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
218246 switch (node_tags[node]) {
219247 .identifier => {
220248 const token_index = main_tokens[node];
221 return renderIdentifier(ais, tree, token_index, space, .preserve_when_shadowing);
249 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);
222250 },
223251
224252 .number_literal,
......@@ -226,29 +254,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
226254 .unreachable_literal,
227255 .anyframe_literal,
228256 .string_literal,
229 => return renderToken(ais, tree, main_tokens[node], space),
257 => return renderToken(r, main_tokens[node], space),
230258
231259 .multiline_string_literal => {
232260 var locked_indents = ais.lockOneShotIndent();
233261 try ais.maybeInsertNewline();
234262
235263 var i = datas[node].lhs;
236 while (i <= datas[node].rhs) : (i += 1) try renderToken(ais, tree, i, .newline);
264 while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline);
237265
238266 while (locked_indents > 0) : (locked_indents -= 1) ais.popIndent();
239267
240268 switch (space) {
241269 .none, .space, .newline, .skip => {},
242 .semicolon => if (token_tags[i] == .semicolon) try renderToken(ais, tree, i, .newline),
243 .comma => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .newline),
244 .comma_space => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .space),
270 .semicolon => if (token_tags[i] == .semicolon) try renderToken(r, i, .newline),
271 .comma => if (token_tags[i] == .comma) try renderToken(r, i, .newline),
272 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),
245273 }
246274 },
247275
248276 .error_value => {
249 try renderToken(ais, tree, main_tokens[node], .none);
250 try renderToken(ais, tree, main_tokens[node] + 1, .none);
251 return renderIdentifier(ais, tree, main_tokens[node] + 2, space, .eagerly_unquote);
277 try renderToken(r, main_tokens[node], .none);
278 try renderToken(r, main_tokens[node] + 1, .none);
279 return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote);
252280 },
253281
254282 .block_two,
......@@ -256,18 +284,18 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
256284 => {
257285 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
258286 if (datas[node].lhs == 0) {
259 return renderBlock(gpa, ais, tree, node, statements[0..0], space);
287 return renderBlock(r, node, statements[0..0], space);
260288 } else if (datas[node].rhs == 0) {
261 return renderBlock(gpa, ais, tree, node, statements[0..1], space);
289 return renderBlock(r, node, statements[0..1], space);
262290 } else {
263 return renderBlock(gpa, ais, tree, node, statements[0..2], space);
291 return renderBlock(r, node, statements[0..2], space);
264292 }
265293 },
266294 .block,
267295 .block_semicolon,
268296 => {
269297 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];
270 return renderBlock(gpa, ais, tree, node, statements, space);
298 return renderBlock(r, node, statements, space);
271299 },
272300
273301 .@"errdefer" => {
......@@ -275,33 +303,33 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
275303 const payload_token = datas[node].lhs;
276304 const expr = datas[node].rhs;
277305
278 try renderToken(ais, tree, defer_token, .space);
306 try renderToken(r, defer_token, .space);
279307 if (payload_token != 0) {
280 try renderToken(ais, tree, payload_token - 1, .none); // |
281 try renderIdentifier(ais, tree, payload_token, .none, .preserve_when_shadowing); // identifier
282 try renderToken(ais, tree, payload_token + 1, .space); // |
308 try renderToken(r, payload_token - 1, .none); // |
309 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
310 try renderToken(r, payload_token + 1, .space); // |
283311 }
284 return renderExpression(gpa, ais, tree, expr, space);
312 return renderExpression(r, expr, space);
285313 },
286314
287315 .@"defer" => {
288316 const defer_token = main_tokens[node];
289317 const expr = datas[node].rhs;
290 try renderToken(ais, tree, defer_token, .space);
291 return renderExpression(gpa, ais, tree, expr, space);
318 try renderToken(r, defer_token, .space);
319 return renderExpression(r, expr, space);
292320 },
293321 .@"comptime", .@"nosuspend" => {
294322 const comptime_token = main_tokens[node];
295323 const block = datas[node].lhs;
296 try renderToken(ais, tree, comptime_token, .space);
297 return renderExpression(gpa, ais, tree, block, space);
324 try renderToken(r, comptime_token, .space);
325 return renderExpression(r, block, space);
298326 },
299327
300328 .@"suspend" => {
301329 const suspend_token = main_tokens[node];
302330 const body = datas[node].lhs;
303 try renderToken(ais, tree, suspend_token, .space);
304 return renderExpression(gpa, ais, tree, body, space);
331 try renderToken(r, suspend_token, .space);
332 return renderExpression(r, body, space);
305333 },
306334
307335 .@"catch" => {
......@@ -311,27 +339,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
311339 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
312340 const after_op_space = if (same_line) Space.space else Space.newline;
313341
314 try renderExpression(gpa, ais, tree, datas[node].lhs, .space); // target
342 try renderExpression(r, datas[node].lhs, .space); // target
315343
316344 if (token_tags[fallback_first - 1] == .pipe) {
317 try renderToken(ais, tree, main_token, .space); // catch keyword
318 try renderToken(ais, tree, main_token + 1, .none); // pipe
319 try renderIdentifier(ais, tree, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
320 try renderToken(ais, tree, main_token + 3, after_op_space); // pipe
345 try renderToken(r, main_token, .space); // catch keyword
346 try renderToken(r, main_token + 1, .none); // pipe
347 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
348 try renderToken(r, main_token + 3, after_op_space); // pipe
321349 } else {
322350 assert(token_tags[fallback_first - 1] == .keyword_catch);
323 try renderToken(ais, tree, main_token, after_op_space); // catch keyword
351 try renderToken(r, main_token, after_op_space); // catch keyword
324352 }
325353
326354 ais.pushIndentOneShot();
327 try renderExpression(gpa, ais, tree, datas[node].rhs, space); // fallback
355 try renderExpression(r, datas[node].rhs, space); // fallback
328356 },
329357
330358 .field_access => {
331359 const main_token = main_tokens[node];
332360 const field_access = datas[node];
333361
334 try renderExpression(gpa, ais, tree, field_access.lhs, .none);
362 try renderExpression(r, field_access.lhs, .none);
335363
336364 // Allow a line break between the lhs and the dot if the lhs and rhs
337365 // are on different lines.
......@@ -342,7 +370,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
342370 ais.pushIndentOneShot();
343371 }
344372
345 try renderToken(ais, tree, main_token, .none); // .
373 try renderToken(r, main_token, .none); // .
346374
347375 // This check ensures that zag() is indented in the following example:
348376 // const x = foo
......@@ -353,25 +381,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
353381 ais.pushIndentOneShot();
354382 }
355383
356 return renderIdentifier(ais, tree, field_access.rhs, space, .eagerly_unquote); // field
384 return renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field
357385 },
358386
359387 .error_union,
360388 .switch_range,
361389 => {
362390 const infix = datas[node];
363 try renderExpression(gpa, ais, tree, infix.lhs, .none);
364 try renderToken(ais, tree, main_tokens[node], .none);
365 return renderExpression(gpa, ais, tree, infix.rhs, space);
391 try renderExpression(r, infix.lhs, .none);
392 try renderToken(r, main_tokens[node], .none);
393 return renderExpression(r, infix.rhs, space);
366394 },
367395 .for_range => {
368396 const infix = datas[node];
369 try renderExpression(gpa, ais, tree, infix.lhs, .none);
397 try renderExpression(r, infix.lhs, .none);
370398 if (infix.rhs != 0) {
371 try renderToken(ais, tree, main_tokens[node], .none);
372 return renderExpression(gpa, ais, tree, infix.rhs, space);
399 try renderToken(r, main_tokens[node], .none);
400 return renderExpression(r, infix.rhs, space);
373401 } else {
374 return renderToken(ais, tree, main_tokens[node], space);
402 return renderToken(r, main_tokens[node], space);
375403 }
376404 },
377405
......@@ -424,17 +452,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
424452 .@"orelse",
425453 => {
426454 const infix = datas[node];
427 try renderExpression(gpa, ais, tree, infix.lhs, .space);
455 try renderExpression(r, infix.lhs, .space);
428456 const op_token = main_tokens[node];
429457 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
430 try renderToken(ais, tree, op_token, .space);
458 try renderToken(r, op_token, .space);
431459 } else {
432460 ais.pushIndent();
433 try renderToken(ais, tree, op_token, .newline);
461 try renderToken(r, op_token, .newline);
434462 ais.popIndent();
435463 }
436464 ais.pushIndentOneShot();
437 return renderExpression(gpa, ais, tree, infix.rhs, space);
465 return renderExpression(r, infix.rhs, space);
438466 },
439467
440468 .assign_destructure => {
......@@ -445,7 +473,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
445473
446474 const maybe_comptime_token = tree.firstToken(node) - 1;
447475 if (token_tags[maybe_comptime_token] == .keyword_comptime) {
448 try renderToken(ais, tree, maybe_comptime_token, .space);
476 try renderToken(r, maybe_comptime_token, .space);
449477 }
450478
451479 for (lhs_exprs, 0..) |lhs_node, i| {
......@@ -456,21 +484,21 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
456484 .simple_var_decl,
457485 .aligned_var_decl,
458486 => {
459 try renderVarDecl(gpa, ais, tree, tree.fullVarDecl(lhs_node).?, true, lhs_space);
487 try renderVarDecl(r, tree.fullVarDecl(lhs_node).?, true, lhs_space);
460488 },
461 else => try renderExpression(gpa, ais, tree, lhs_node, lhs_space),
489 else => try renderExpression(r, lhs_node, lhs_space),
462490 }
463491 }
464492 const equal_token = main_tokens[node];
465493 if (tree.tokensOnSameLine(equal_token, equal_token + 1)) {
466 try renderToken(ais, tree, equal_token, .space);
494 try renderToken(r, equal_token, .space);
467495 } else {
468496 ais.pushIndent();
469 try renderToken(ais, tree, equal_token, .newline);
497 try renderToken(r, equal_token, .newline);
470498 ais.popIndent();
471499 }
472500 ais.pushIndentOneShot();
473 return renderExpression(gpa, ais, tree, rhs, space);
501 return renderExpression(r, rhs, space);
474502 },
475503
476504 .bit_not,
......@@ -480,27 +508,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
480508 .optional_type,
481509 .address_of,
482510 => {
483 try renderToken(ais, tree, main_tokens[node], .none);
484 return renderExpression(gpa, ais, tree, datas[node].lhs, space);
511 try renderToken(r, main_tokens[node], .none);
512 return renderExpression(r, datas[node].lhs, space);
485513 },
486514
487515 .@"try",
488516 .@"resume",
489517 .@"await",
490518 => {
491 try renderToken(ais, tree, main_tokens[node], .space);
492 return renderExpression(gpa, ais, tree, datas[node].lhs, space);
519 try renderToken(r, main_tokens[node], .space);
520 return renderExpression(r, datas[node].lhs, space);
493521 },
494522
495523 .array_type,
496524 .array_type_sentinel,
497 => return renderArrayType(gpa, ais, tree, tree.fullArrayType(node).?, space),
525 => return renderArrayType(r, tree.fullArrayType(node).?, space),
498526
499527 .ptr_type_aligned,
500528 .ptr_type_sentinel,
501529 .ptr_type,
502530 .ptr_type_bit_range,
503 => return renderPtrType(gpa, ais, tree, tree.fullPtrType(node).?, space),
531 => return renderPtrType(r, tree.fullPtrType(node).?, space),
504532
505533 .array_init_one,
506534 .array_init_one_comma,
......@@ -512,7 +540,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
512540 .array_init_comma,
513541 => {
514542 var elements: [2]Ast.Node.Index = undefined;
515 return renderArrayInit(gpa, ais, tree, tree.fullArrayInit(&elements, node).?, space);
543 return renderArrayInit(r, tree.fullArrayInit(&elements, node).?, space);
516544 },
517545
518546 .struct_init_one,
......@@ -525,7 +553,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
525553 .struct_init_comma,
526554 => {
527555 var buf: [2]Ast.Node.Index = undefined;
528 return renderStructInit(gpa, ais, tree, node, tree.fullStructInit(&buf, node).?, space);
556 return renderStructInit(r, node, tree.fullStructInit(&buf, node).?, space);
529557 },
530558
531559 .call_one,
......@@ -538,7 +566,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
538566 .async_call_comma,
539567 => {
540568 var buf: [1]Ast.Node.Index = undefined;
541 return renderCall(gpa, ais, tree, tree.fullCall(&buf, node).?, space);
569 return renderCall(r, tree.fullCall(&buf, node).?, space);
542570 },
543571
544572 .array_access => {
......@@ -547,25 +575,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
547575 const rbracket = tree.lastToken(suffix.rhs) + 1;
548576 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
549577 const inner_space = if (one_line) Space.none else Space.newline;
550 try renderExpression(gpa, ais, tree, suffix.lhs, .none);
578 try renderExpression(r, suffix.lhs, .none);
551579 ais.pushIndentNextLine();
552 try renderToken(ais, tree, lbracket, inner_space); // [
553 try renderExpression(gpa, ais, tree, suffix.rhs, inner_space);
580 try renderToken(r, lbracket, inner_space); // [
581 try renderExpression(r, suffix.rhs, inner_space);
554582 ais.popIndent();
555 return renderToken(ais, tree, rbracket, space); // ]
583 return renderToken(r, rbracket, space); // ]
556584 },
557585
558 .slice_open, .slice, .slice_sentinel => return renderSlice(gpa, ais, tree, node, tree.fullSlice(node).?, space),
586 .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space),
559587
560588 .deref => {
561 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
562 return renderToken(ais, tree, main_tokens[node], space);
589 try renderExpression(r, datas[node].lhs, .none);
590 return renderToken(r, main_tokens[node], space);
563591 },
564592
565593 .unwrap_optional => {
566 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
567 try renderToken(ais, tree, main_tokens[node], .none);
568 return renderToken(ais, tree, datas[node].rhs, space);
594 try renderExpression(r, datas[node].lhs, .none);
595 try renderToken(r, main_tokens[node], .none);
596 return renderToken(r, datas[node].rhs, space);
569597 },
570598
571599 .@"break" => {
......@@ -573,19 +601,19 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
573601 const label_token = datas[node].lhs;
574602 const target = datas[node].rhs;
575603 if (label_token == 0 and target == 0) {
576 try renderToken(ais, tree, main_token, space); // break keyword
604 try renderToken(r, main_token, space); // break keyword
577605 } else if (label_token == 0 and target != 0) {
578 try renderToken(ais, tree, main_token, .space); // break keyword
579 try renderExpression(gpa, ais, tree, target, space);
606 try renderToken(r, main_token, .space); // break keyword
607 try renderExpression(r, target, space);
580608 } else if (label_token != 0 and target == 0) {
581 try renderToken(ais, tree, main_token, .space); // break keyword
582 try renderToken(ais, tree, label_token - 1, .none); // colon
583 try renderIdentifier(ais, tree, label_token, space, .eagerly_unquote); // identifier
609 try renderToken(r, main_token, .space); // break keyword
610 try renderToken(r, label_token - 1, .none); // colon
611 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
584612 } else if (label_token != 0 and target != 0) {
585 try renderToken(ais, tree, main_token, .space); // break keyword
586 try renderToken(ais, tree, label_token - 1, .none); // colon
587 try renderIdentifier(ais, tree, label_token, .space, .eagerly_unquote); // identifier
588 try renderExpression(gpa, ais, tree, target, space);
613 try renderToken(r, main_token, .space); // break keyword
614 try renderToken(r, label_token - 1, .none); // colon
615 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
616 try renderExpression(r, target, space);
589617 }
590618 },
591619
......@@ -593,28 +621,28 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
593621 const main_token = main_tokens[node];
594622 const label = datas[node].lhs;
595623 if (label != 0) {
596 try renderToken(ais, tree, main_token, .space); // continue
597 try renderToken(ais, tree, label - 1, .none); // :
598 return renderIdentifier(ais, tree, label, space, .eagerly_unquote); // label
624 try renderToken(r, main_token, .space); // continue
625 try renderToken(r, label - 1, .none); // :
626 return renderIdentifier(r, label, space, .eagerly_unquote); // label
599627 } else {
600 return renderToken(ais, tree, main_token, space); // continue
628 return renderToken(r, main_token, space); // continue
601629 }
602630 },
603631
604632 .@"return" => {
605633 if (datas[node].lhs != 0) {
606 try renderToken(ais, tree, main_tokens[node], .space);
607 try renderExpression(gpa, ais, tree, datas[node].lhs, space);
634 try renderToken(r, main_tokens[node], .space);
635 try renderExpression(r, datas[node].lhs, space);
608636 } else {
609 try renderToken(ais, tree, main_tokens[node], space);
637 try renderToken(r, main_tokens[node], space);
610638 }
611639 },
612640
613641 .grouped_expression => {
614 try renderToken(ais, tree, main_tokens[node], .none); // lparen
642 try renderToken(r, main_tokens[node], .none); // lparen
615643 ais.pushIndentOneShot();
616 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);
617 return renderToken(ais, tree, datas[node].rhs, space); // rparen
644 try renderExpression(r, datas[node].lhs, .none);
645 return renderToken(r, datas[node].rhs, space); // rparen
618646 },
619647
620648 .container_decl,
......@@ -631,7 +659,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
631659 .tagged_union_two_trailing,
632660 => {
633661 var buf: [2]Ast.Node.Index = undefined;
634 return renderContainerDecl(gpa, ais, tree, node, tree.fullContainerDecl(&buf, node).?, space);
662 return renderContainerDecl(r, node, tree.fullContainerDecl(&buf, node).?, space);
635663 },
636664
637665 .error_set_decl => {
......@@ -639,62 +667,62 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
639667 const lbrace = error_token + 1;
640668 const rbrace = datas[node].rhs;
641669
642 try renderToken(ais, tree, error_token, .none);
670 try renderToken(r, error_token, .none);
643671
644672 if (lbrace + 1 == rbrace) {
645673 // There is nothing between the braces so render condensed: `error{}`
646 try renderToken(ais, tree, lbrace, .none);
647 return renderToken(ais, tree, rbrace, space);
674 try renderToken(r, lbrace, .none);
675 return renderToken(r, rbrace, space);
648676 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {
649677 // There is exactly one member and no trailing comma or
650678 // comments, so render without surrounding spaces: `error{Foo}`
651 try renderToken(ais, tree, lbrace, .none);
652 try renderIdentifier(ais, tree, lbrace + 1, .none, .eagerly_unquote); // identifier
653 return renderToken(ais, tree, rbrace, space);
679 try renderToken(r, lbrace, .none);
680 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
681 return renderToken(r, rbrace, space);
654682 } else if (token_tags[rbrace - 1] == .comma) {
655683 // There is a trailing comma so render each member on a new line.
656684 ais.pushIndentNextLine();
657 try renderToken(ais, tree, lbrace, .newline);
685 try renderToken(r, lbrace, .newline);
658686 var i = lbrace + 1;
659687 while (i < rbrace) : (i += 1) {
660 if (i > lbrace + 1) try renderExtraNewlineToken(ais, tree, i);
688 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
661689 switch (token_tags[i]) {
662 .doc_comment => try renderToken(ais, tree, i, .newline),
663 .identifier => try renderIdentifier(ais, tree, i, .comma, .eagerly_unquote),
690 .doc_comment => try renderToken(r, i, .newline),
691 .identifier => try renderIdentifier(r, i, .comma, .eagerly_unquote),
664692 .comma => {},
665693 else => unreachable,
666694 }
667695 }
668696 ais.popIndent();
669 return renderToken(ais, tree, rbrace, space);
697 return renderToken(r, rbrace, space);
670698 } else {
671699 // There is no trailing comma so render everything on one line.
672 try renderToken(ais, tree, lbrace, .space);
700 try renderToken(r, lbrace, .space);
673701 var i = lbrace + 1;
674702 while (i < rbrace) : (i += 1) {
675703 switch (token_tags[i]) {
676704 .doc_comment => unreachable, // TODO
677 .identifier => try renderIdentifier(ais, tree, i, .comma_space, .eagerly_unquote),
705 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),
678706 .comma => {},
679707 else => unreachable,
680708 }
681709 }
682 return renderToken(ais, tree, rbrace, space);
710 return renderToken(r, rbrace, space);
683711 }
684712 },
685713
686714 .builtin_call_two, .builtin_call_two_comma => {
687715 if (datas[node].lhs == 0) {
688 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{}, space);
716 return renderBuiltinCall(r, main_tokens[node], &.{}, space);
689717 } else if (datas[node].rhs == 0) {
690 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{datas[node].lhs}, space);
718 return renderBuiltinCall(r, main_tokens[node], &.{datas[node].lhs}, space);
691719 } else {
692 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);
720 return renderBuiltinCall(r, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);
693721 }
694722 },
695723 .builtin_call, .builtin_call_comma => {
696724 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
697 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], params, space);
725 return renderBuiltinCall(r, main_tokens[node], params, space);
698726 },
699727
700728 .fn_proto_simple,
......@@ -703,17 +731,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
703731 .fn_proto,
704732 => {
705733 var buf: [1]Ast.Node.Index = undefined;
706 return renderFnProto(gpa, ais, tree, tree.fullFnProto(&buf, node).?, space);
734 return renderFnProto(r, tree.fullFnProto(&buf, node).?, space);
707735 },
708736
709737 .anyframe_type => {
710738 const main_token = main_tokens[node];
711739 if (datas[node].rhs != 0) {
712 try renderToken(ais, tree, main_token, .none); // anyframe
713 try renderToken(ais, tree, main_token + 1, .none); // ->
714 return renderExpression(gpa, ais, tree, datas[node].rhs, space);
740 try renderToken(r, main_token, .none); // anyframe
741 try renderToken(r, main_token + 1, .none); // ->
742 return renderExpression(r, datas[node].rhs, space);
715743 } else {
716 return renderToken(ais, tree, main_token, space); // anyframe
744 return renderToken(r, main_token, space); // anyframe
717745 }
718746 },
719747
......@@ -726,48 +754,48 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
726754 const cases = tree.extra_data[extra.start..extra.end];
727755 const rparen = tree.lastToken(condition) + 1;
728756
729 try renderToken(ais, tree, switch_token, .space); // switch keyword
730 try renderToken(ais, tree, switch_token + 1, .none); // lparen
731 try renderExpression(gpa, ais, tree, condition, .none); // condition expression
732 try renderToken(ais, tree, rparen, .space); // rparen
757 try renderToken(r, switch_token, .space); // switch keyword
758 try renderToken(r, switch_token + 1, .none); // lparen
759 try renderExpression(r, condition, .none); // condition expression
760 try renderToken(r, rparen, .space); // rparen
733761
734762 ais.pushIndentNextLine();
735763 if (cases.len == 0) {
736 try renderToken(ais, tree, rparen + 1, .none); // lbrace
764 try renderToken(r, rparen + 1, .none); // lbrace
737765 } else {
738 try renderToken(ais, tree, rparen + 1, .newline); // lbrace
739 try renderExpressions(gpa, ais, tree, cases, .comma);
766 try renderToken(r, rparen + 1, .newline); // lbrace
767 try renderExpressions(r, cases, .comma);
740768 }
741769 ais.popIndent();
742 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
770 return renderToken(r, tree.lastToken(node), space); // rbrace
743771 },
744772
745773 .switch_case_one,
746774 .switch_case_inline_one,
747775 .switch_case,
748776 .switch_case_inline,
749 => return renderSwitchCase(gpa, ais, tree, tree.fullSwitchCase(node).?, space),
777 => return renderSwitchCase(r, tree.fullSwitchCase(node).?, space),
750778
751779 .while_simple,
752780 .while_cont,
753781 .@"while",
754 => return renderWhile(gpa, ais, tree, tree.fullWhile(node).?, space),
782 => return renderWhile(r, tree.fullWhile(node).?, space),
755783
756784 .for_simple,
757785 .@"for",
758 => return renderFor(gpa, ais, tree, tree.fullFor(node).?, space),
786 => return renderFor(r, tree.fullFor(node).?, space),
759787
760788 .if_simple,
761789 .@"if",
762 => return renderIf(gpa, ais, tree, tree.fullIf(node).?, space),
790 => return renderIf(r, tree.fullIf(node).?, space),
763791
764792 .asm_simple,
765793 .@"asm",
766 => return renderAsm(gpa, ais, tree, tree.fullAsm(node).?, space),
794 => return renderAsm(r, tree.fullAsm(node).?, space),
767795
768796 .enum_literal => {
769 try renderToken(ais, tree, main_tokens[node] - 1, .none); // .
770 return renderIdentifier(ais, tree, main_tokens[node], space, .eagerly_unquote); // name
797 try renderToken(r, main_tokens[node] - 1, .none); // .
798 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name
771799 },
772800
773801 .fn_decl => unreachable,
......@@ -787,34 +815,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
787815}
788816
789817fn renderArrayType(
790 gpa: Allocator,
791 ais: *Ais,
792 tree: Ast,
818 r: Render,
793819 array_type: Ast.full.ArrayType,
794820 space: Space,
795821) Error!void {
822 const tree = r.tree;
823 const ais = r.ais;
796824 const rbracket = tree.firstToken(array_type.ast.elem_type) - 1;
797825 const one_line = tree.tokensOnSameLine(array_type.ast.lbracket, rbracket);
798826 const inner_space = if (one_line) Space.none else Space.newline;
799827 ais.pushIndentNextLine();
800 try renderToken(ais, tree, array_type.ast.lbracket, inner_space); // lbracket
801 try renderExpression(gpa, ais, tree, array_type.ast.elem_count, inner_space);
828 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
829 try renderExpression(r, array_type.ast.elem_count, inner_space);
802830 if (array_type.ast.sentinel != 0) {
803 try renderToken(ais, tree, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
804 try renderExpression(gpa, ais, tree, array_type.ast.sentinel, inner_space);
831 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
832 try renderExpression(r, array_type.ast.sentinel, inner_space);
805833 }
806834 ais.popIndent();
807 try renderToken(ais, tree, rbracket, .none); // rbracket
808 return renderExpression(gpa, ais, tree, array_type.ast.elem_type, space);
835 try renderToken(r, rbracket, .none); // rbracket
836 return renderExpression(r, array_type.ast.elem_type, space);
809837}
810838
811fn renderPtrType(
812 gpa: Allocator,
813 ais: *Ais,
814 tree: Ast,
815 ptr_type: Ast.full.PtrType,
816 space: Space,
817) Error!void {
839fn renderPtrType(r: Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
840 const tree = r.tree;
818841 switch (ptr_type.size) {
819842 .One => {
820843 // Since ** tokens exist and the same token is shared by two
......@@ -825,90 +848,89 @@ fn renderPtrType(
825848 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and
826849 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
827850 {
828 return renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);
851 return renderExpression(r, ptr_type.ast.child_type, space);
829852 }
830 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
853 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
831854 },
832855 .Many => {
833856 if (ptr_type.ast.sentinel == 0) {
834 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
835 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
836 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
857 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
858 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
859 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
837860 } else {
838 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
839 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
840 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
841 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);
842 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
861 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
862 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
863 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
864 try renderExpression(r, ptr_type.ast.sentinel, .none);
865 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
843866 }
844867 },
845868 .C => {
846 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
847 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
848 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // c
849 try renderToken(ais, tree, ptr_type.ast.main_token + 2, .none); // rbracket
869 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
870 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
871 try renderToken(r, ptr_type.ast.main_token + 1, .none); // c
872 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket
850873 },
851874 .Slice => {
852875 if (ptr_type.ast.sentinel == 0) {
853 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
854 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
876 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
877 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
855878 } else {
856 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
857 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
858 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);
859 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
879 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
880 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
881 try renderExpression(r, ptr_type.ast.sentinel, .none);
882 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
860883 }
861884 },
862885 }
863886
864887 if (ptr_type.allowzero_token) |allowzero_token| {
865 try renderToken(ais, tree, allowzero_token, .space);
888 try renderToken(r, allowzero_token, .space);
866889 }
867890
868891 if (ptr_type.ast.align_node != 0) {
869892 const align_first = tree.firstToken(ptr_type.ast.align_node);
870 try renderToken(ais, tree, align_first - 2, .none); // align
871 try renderToken(ais, tree, align_first - 1, .none); // lparen
872 try renderExpression(gpa, ais, tree, ptr_type.ast.align_node, .none);
893 try renderToken(r, align_first - 2, .none); // align
894 try renderToken(r, align_first - 1, .none); // lparen
895 try renderExpression(r, ptr_type.ast.align_node, .none);
873896 if (ptr_type.ast.bit_range_start != 0) {
874897 assert(ptr_type.ast.bit_range_end != 0);
875 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
876 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_start, .none);
877 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
878 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_end, .none);
879 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
898 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
899 try renderExpression(r, ptr_type.ast.bit_range_start, .none);
900 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
901 try renderExpression(r, ptr_type.ast.bit_range_end, .none);
902 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
880903 } else {
881 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
904 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
882905 }
883906 }
884907
885908 if (ptr_type.ast.addrspace_node != 0) {
886909 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);
887 try renderToken(ais, tree, addrspace_first - 2, .none); // addrspace
888 try renderToken(ais, tree, addrspace_first - 1, .none); // lparen
889 try renderExpression(gpa, ais, tree, ptr_type.ast.addrspace_node, .none);
890 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen
910 try renderToken(r, addrspace_first - 2, .none); // addrspace
911 try renderToken(r, addrspace_first - 1, .none); // lparen
912 try renderExpression(r, ptr_type.ast.addrspace_node, .none);
913 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen
891914 }
892915
893916 if (ptr_type.const_token) |const_token| {
894 try renderToken(ais, tree, const_token, .space);
917 try renderToken(r, const_token, .space);
895918 }
896919
897920 if (ptr_type.volatile_token) |volatile_token| {
898 try renderToken(ais, tree, volatile_token, .space);
921 try renderToken(r, volatile_token, .space);
899922 }
900923
901 try renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);
924 try renderExpression(r, ptr_type.ast.child_type, space);
902925}
903926
904927fn renderSlice(
905 gpa: Allocator,
906 ais: *Ais,
907 tree: Ast,
928 r: Render,
908929 slice_node: Ast.Node.Index,
909930 slice: Ast.full.Slice,
910931 space: Space,
911932) Error!void {
933 const tree = r.tree;
912934 const node_tags = tree.nodes.items(.tag);
913935 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
914936 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
......@@ -917,33 +939,32 @@ fn renderSlice(
917939 after_start_space
918940 else if (slice.ast.sentinel != 0) Space.space else Space.none;
919941
920 try renderExpression(gpa, ais, tree, slice.ast.sliced, .none);
921 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket
942 try renderExpression(r, slice.ast.sliced, .none);
943 try renderToken(r, slice.ast.lbracket, .none); // lbracket
922944
923945 const start_last = tree.lastToken(slice.ast.start);
924 try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space);
925 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")
946 try renderExpression(r, slice.ast.start, after_start_space);
947 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
926948
927949 if (slice.ast.end != 0) {
928950 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;
929 try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space);
951 try renderExpression(r, slice.ast.end, after_end_space);
930952 }
931953
932954 if (slice.ast.sentinel != 0) {
933 try renderToken(ais, tree, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
934 try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none);
955 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
956 try renderExpression(r, slice.ast.sentinel, .none);
935957 }
936958
937 try renderToken(ais, tree, tree.lastToken(slice_node), space); // rbracket
959 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
938960}
939961
940962fn renderAsmOutput(
941 gpa: Allocator,
942 ais: *Ais,
943 tree: Ast,
963 r: Render,
944964 asm_output: Ast.Node.Index,
945965 space: Space,
946966) Error!void {
967 const tree = r.tree;
947968 const token_tags = tree.tokens.items(.tag);
948969 const node_tags = tree.nodes.items(.tag);
949970 const main_tokens = tree.nodes.items(.main_token);
......@@ -951,77 +972,77 @@ fn renderAsmOutput(
951972 assert(node_tags[asm_output] == .asm_output);
952973 const symbolic_name = main_tokens[asm_output];
953974
954 try renderToken(ais, tree, symbolic_name - 1, .none); // lbracket
955 try renderIdentifier(ais, tree, symbolic_name, .none, .eagerly_unquote); // ident
956 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket
957 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"
958 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen
975 try renderToken(r, symbolic_name - 1, .none); // lbracket
976 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
977 try renderToken(r, symbolic_name + 1, .space); // rbracket
978 try renderToken(r, symbolic_name + 2, .space); // "constraint"
979 try renderToken(r, symbolic_name + 3, .none); // lparen
959980
960981 if (token_tags[symbolic_name + 4] == .arrow) {
961 try renderToken(ais, tree, symbolic_name + 4, .space); // ->
962 try renderExpression(gpa, ais, tree, datas[asm_output].lhs, Space.none);
963 return renderToken(ais, tree, datas[asm_output].rhs, space); // rparen
982 try renderToken(r, symbolic_name + 4, .space); // ->
983 try renderExpression(r, datas[asm_output].lhs, Space.none);
984 return renderToken(r, datas[asm_output].rhs, space); // rparen
964985 } else {
965 try renderIdentifier(ais, tree, symbolic_name + 4, .none, .eagerly_unquote); // ident
966 return renderToken(ais, tree, symbolic_name + 5, space); // rparen
986 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
987 return renderToken(r, symbolic_name + 5, space); // rparen
967988 }
968989}
969990
970991fn renderAsmInput(
971 gpa: Allocator,
972 ais: *Ais,
973 tree: Ast,
992 r: Render,
974993 asm_input: Ast.Node.Index,
975994 space: Space,
976995) Error!void {
996 const tree = r.tree;
977997 const node_tags = tree.nodes.items(.tag);
978998 const main_tokens = tree.nodes.items(.main_token);
979999 const datas = tree.nodes.items(.data);
9801000 assert(node_tags[asm_input] == .asm_input);
9811001 const symbolic_name = main_tokens[asm_input];
9821002
983 try renderToken(ais, tree, symbolic_name - 1, .none); // lbracket
984 try renderIdentifier(ais, tree, symbolic_name, .none, .eagerly_unquote); // ident
985 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket
986 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"
987 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen
988 try renderExpression(gpa, ais, tree, datas[asm_input].lhs, Space.none);
989 return renderToken(ais, tree, datas[asm_input].rhs, space); // rparen
1003 try renderToken(r, symbolic_name - 1, .none); // lbracket
1004 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
1005 try renderToken(r, symbolic_name + 1, .space); // rbracket
1006 try renderToken(r, symbolic_name + 2, .space); // "constraint"
1007 try renderToken(r, symbolic_name + 3, .none); // lparen
1008 try renderExpression(r, datas[asm_input].lhs, Space.none);
1009 return renderToken(r, datas[asm_input].rhs, space); // rparen
9901010}
9911011
9921012fn renderVarDecl(
993 gpa: Allocator,
994 ais: *Ais,
995 tree: Ast,
1013 r: Render,
9961014 var_decl: Ast.full.VarDecl,
9971015 /// Destructures intentionally ignore leading `comptime` tokens.
9981016 ignore_comptime_token: bool,
9991017 /// `comma_space` and `space` are used for destructure LHS decls.
10001018 space: Space,
10011019) Error!void {
1020 const tree = r.tree;
1021 const ais = r.ais;
1022
10021023 if (var_decl.visib_token) |visib_token| {
1003 try renderToken(ais, tree, visib_token, Space.space); // pub
1024 try renderToken(r, visib_token, Space.space); // pub
10041025 }
10051026
10061027 if (var_decl.extern_export_token) |extern_export_token| {
1007 try renderToken(ais, tree, extern_export_token, Space.space); // extern
1028 try renderToken(r, extern_export_token, Space.space); // extern
10081029
10091030 if (var_decl.lib_name) |lib_name| {
1010 try renderToken(ais, tree, lib_name, Space.space); // "lib"
1031 try renderToken(r, lib_name, Space.space); // "lib"
10111032 }
10121033 }
10131034
10141035 if (var_decl.threadlocal_token) |thread_local_token| {
1015 try renderToken(ais, tree, thread_local_token, Space.space); // threadlocal
1036 try renderToken(r, thread_local_token, Space.space); // threadlocal
10161037 }
10171038
10181039 if (!ignore_comptime_token) {
10191040 if (var_decl.comptime_token) |comptime_token| {
1020 try renderToken(ais, tree, comptime_token, Space.space); // comptime
1041 try renderToken(r, comptime_token, Space.space); // comptime
10211042 }
10221043 }
10231044
1024 try renderToken(ais, tree, var_decl.ast.mut_token, .space); // var
1045 try renderToken(r, var_decl.ast.mut_token, .space); // var
10251046
10261047 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or
10271048 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
......@@ -1036,19 +1057,19 @@ fn renderVarDecl(
10361057 else
10371058 Space.none;
10381059
1039 try renderIdentifier(ais, tree, var_decl.ast.mut_token + 1, name_space, .preserve_when_shadowing); // name
1060 try renderIdentifier(r, var_decl.ast.mut_token + 1, name_space, .preserve_when_shadowing); // name
10401061 } else {
1041 return renderIdentifier(ais, tree, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
1062 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
10421063 }
10431064
10441065 if (var_decl.ast.type_node != 0) {
1045 try renderToken(ais, tree, var_decl.ast.mut_token + 2, Space.space); // :
1066 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
10461067 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or
10471068 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)
10481069 {
1049 try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space);
1070 try renderExpression(r, var_decl.ast.type_node, .space);
10501071 } else {
1051 return renderExpression(gpa, ais, tree, var_decl.ast.type_node, space);
1072 return renderExpression(r, var_decl.ast.type_node, space);
10521073 }
10531074 }
10541075
......@@ -1056,15 +1077,15 @@ fn renderVarDecl(
10561077 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;
10571078 const align_kw = lparen - 1;
10581079 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;
1059 try renderToken(ais, tree, align_kw, Space.none); // align
1060 try renderToken(ais, tree, lparen, Space.none); // (
1061 try renderExpression(gpa, ais, tree, var_decl.ast.align_node, Space.none);
1080 try renderToken(r, align_kw, Space.none); // align
1081 try renderToken(r, lparen, Space.none); // (
1082 try renderExpression(r, var_decl.ast.align_node, Space.none);
10621083 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
10631084 var_decl.ast.init_node != 0)
10641085 {
1065 try renderToken(ais, tree, rparen, .space); // )
1086 try renderToken(r, rparen, .space); // )
10661087 } else {
1067 return renderToken(ais, tree, rparen, space); // )
1088 return renderToken(r, rparen, space); // )
10681089 }
10691090 }
10701091
......@@ -1072,14 +1093,14 @@ fn renderVarDecl(
10721093 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;
10731094 const addrspace_kw = lparen - 1;
10741095 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;
1075 try renderToken(ais, tree, addrspace_kw, Space.none); // addrspace
1076 try renderToken(ais, tree, lparen, Space.none); // (
1077 try renderExpression(gpa, ais, tree, var_decl.ast.addrspace_node, Space.none);
1096 try renderToken(r, addrspace_kw, Space.none); // addrspace
1097 try renderToken(r, lparen, Space.none); // (
1098 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);
10781099 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {
1079 try renderToken(ais, tree, rparen, .space); // )
1100 try renderToken(r, rparen, .space); // )
10801101 } else {
1081 try renderToken(ais, tree, rparen, .none); // )
1082 return renderToken(ais, tree, rparen + 1, Space.newline); // ;
1102 try renderToken(r, rparen, .none); // )
1103 return renderToken(r, rparen + 1, Space.newline); // ;
10831104 }
10841105 }
10851106
......@@ -1087,13 +1108,13 @@ fn renderVarDecl(
10871108 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;
10881109 const section_kw = lparen - 1;
10891110 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;
1090 try renderToken(ais, tree, section_kw, Space.none); // linksection
1091 try renderToken(ais, tree, lparen, Space.none); // (
1092 try renderExpression(gpa, ais, tree, var_decl.ast.section_node, Space.none);
1111 try renderToken(r, section_kw, Space.none); // linksection
1112 try renderToken(r, lparen, Space.none); // (
1113 try renderExpression(r, var_decl.ast.section_node, Space.none);
10931114 if (var_decl.ast.init_node != 0) {
1094 try renderToken(ais, tree, rparen, .space); // )
1115 try renderToken(r, rparen, .space); // )
10951116 } else {
1096 return renderToken(ais, tree, rparen, space); // )
1117 return renderToken(r, rparen, space); // )
10971118 }
10981119 }
10991120
......@@ -1103,15 +1124,15 @@ fn renderVarDecl(
11031124 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
11041125 {
11051126 ais.pushIndent();
1106 try renderToken(ais, tree, eq_token, eq_space); // =
1127 try renderToken(r, eq_token, eq_space); // =
11071128 ais.popIndent();
11081129 }
11091130 ais.pushIndentOneShot();
1110 return renderExpression(gpa, ais, tree, var_decl.ast.init_node, space); // ;
1131 return renderExpression(r, var_decl.ast.init_node, space); // ;
11111132}
11121133
1113fn renderIf(gpa: Allocator, ais: *Ais, tree: Ast, if_node: Ast.full.If, space: Space) Error!void {
1114 return renderWhile(gpa, ais, tree, .{
1134fn renderIf(r: Render, if_node: Ast.full.If, space: Space) Error!void {
1135 return renderWhile(r, .{
11151136 .ast = .{
11161137 .while_token = if_node.ast.if_token,
11171138 .cond_expr = if_node.ast.cond_expr,
......@@ -1129,40 +1150,41 @@ fn renderIf(gpa: Allocator, ais: *Ais, tree: Ast, if_node: Ast.full.If, space: S
11291150
11301151/// Note that this function is additionally used to render if expressions, with
11311152/// respective values set to null.
1132fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While, space: Space) Error!void {
1153fn renderWhile(r: Render, while_node: Ast.full.While, space: Space) Error!void {
1154 const tree = r.tree;
11331155 const token_tags = tree.tokens.items(.tag);
11341156
11351157 if (while_node.label_token) |label| {
1136 try renderIdentifier(ais, tree, label, .none, .eagerly_unquote); // label
1137 try renderToken(ais, tree, label + 1, .space); // :
1158 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
1159 try renderToken(r, label + 1, .space); // :
11381160 }
11391161
11401162 if (while_node.inline_token) |inline_token| {
1141 try renderToken(ais, tree, inline_token, .space); // inline
1163 try renderToken(r, inline_token, .space); // inline
11421164 }
11431165
1144 try renderToken(ais, tree, while_node.ast.while_token, .space); // if/for/while
1145 try renderToken(ais, tree, while_node.ast.while_token + 1, .none); // lparen
1146 try renderExpression(gpa, ais, tree, while_node.ast.cond_expr, .none); // condition
1166 try renderToken(r, while_node.ast.while_token, .space); // if/for/while
1167 try renderToken(r, while_node.ast.while_token + 1, .none); // lparen
1168 try renderExpression(r, while_node.ast.cond_expr, .none); // condition
11471169
11481170 var last_prefix_token = tree.lastToken(while_node.ast.cond_expr) + 1; // rparen
11491171
11501172 if (while_node.payload_token) |payload_token| {
1151 try renderToken(ais, tree, last_prefix_token, .space);
1152 try renderToken(ais, tree, payload_token - 1, .none); // |
1173 try renderToken(r, last_prefix_token, .space);
1174 try renderToken(r, payload_token - 1, .none); // |
11531175 const ident = blk: {
11541176 if (token_tags[payload_token] == .asterisk) {
1155 try renderToken(ais, tree, payload_token, .none); // *
1177 try renderToken(r, payload_token, .none); // *
11561178 break :blk payload_token + 1;
11571179 } else {
11581180 break :blk payload_token;
11591181 }
11601182 };
1161 try renderIdentifier(ais, tree, ident, .none, .preserve_when_shadowing); // identifier
1183 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
11621184 const pipe = blk: {
11631185 if (token_tags[ident + 1] == .comma) {
1164 try renderToken(ais, tree, ident + 1, .space); // ,
1165 try renderIdentifier(ais, tree, ident + 2, .none, .preserve_when_shadowing); // index
1186 try renderToken(r, ident + 1, .space); // ,
1187 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
11661188 break :blk ident + 3;
11671189 } else {
11681190 break :blk ident + 1;
......@@ -1172,18 +1194,16 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,
11721194 }
11731195
11741196 if (while_node.ast.cont_expr != 0) {
1175 try renderToken(ais, tree, last_prefix_token, .space);
1197 try renderToken(r, last_prefix_token, .space);
11761198 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1177 try renderToken(ais, tree, lparen - 1, .space); // :
1178 try renderToken(ais, tree, lparen, .none); // lparen
1179 try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none);
1199 try renderToken(r, lparen - 1, .space); // :
1200 try renderToken(r, lparen, .none); // lparen
1201 try renderExpression(r, while_node.ast.cont_expr, .none);
11801202 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen
11811203 }
11821204
11831205 try renderThenElse(
1184 gpa,
1185 ais,
1186 tree,
1206 r,
11871207 last_prefix_token,
11881208 while_node.ast.then_expr,
11891209 while_node.else_token,
......@@ -1194,9 +1214,7 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,
11941214}
11951215
11961216fn renderThenElse(
1197 gpa: Allocator,
1198 ais: *Ais,
1199 tree: Ast,
1217 r: Render,
12001218 last_prefix_token: Ast.TokenIndex,
12011219 then_expr: Ast.Node.Index,
12021220 else_token: Ast.TokenIndex,
......@@ -1204,33 +1222,35 @@ fn renderThenElse(
12041222 else_expr: Ast.Node.Index,
12051223 space: Space,
12061224) Error!void {
1225 const tree = r.tree;
1226 const ais = r.ais;
12071227 const node_tags = tree.nodes.items(.tag);
12081228 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
12091229 const indent_then_expr = !then_expr_is_block and
12101230 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
12111231 if (indent_then_expr or (then_expr_is_block and ais.isLineOverIndented())) {
12121232 ais.pushIndentNextLine();
1213 try renderToken(ais, tree, last_prefix_token, .newline);
1233 try renderToken(r, last_prefix_token, .newline);
12141234 ais.popIndent();
12151235 } else {
1216 try renderToken(ais, tree, last_prefix_token, .space);
1236 try renderToken(r, last_prefix_token, .space);
12171237 }
12181238
12191239 if (else_expr != 0) {
12201240 if (indent_then_expr) {
12211241 ais.pushIndent();
1222 try renderExpression(gpa, ais, tree, then_expr, .newline);
1242 try renderExpression(r, then_expr, .newline);
12231243 ais.popIndent();
12241244 } else {
1225 try renderExpression(gpa, ais, tree, then_expr, .space);
1245 try renderExpression(r, then_expr, .space);
12261246 }
12271247
12281248 var last_else_token = else_token;
12291249
12301250 if (maybe_error_token) |error_token| {
1231 try renderToken(ais, tree, else_token, .space); // else
1232 try renderToken(ais, tree, error_token - 1, .none); // |
1233 try renderIdentifier(ais, tree, error_token, .none, .preserve_when_shadowing); // identifier
1251 try renderToken(r, else_token, .space); // else
1252 try renderToken(r, error_token - 1, .none); // |
1253 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
12341254 last_else_token = error_token + 1; // |
12351255 }
12361256
......@@ -1239,53 +1259,55 @@ fn renderThenElse(
12391259 !nodeIsIfForWhileSwitch(node_tags[else_expr]);
12401260 if (indent_else_expr) {
12411261 ais.pushIndentNextLine();
1242 try renderToken(ais, tree, last_else_token, .newline);
1262 try renderToken(r, last_else_token, .newline);
12431263 ais.popIndent();
1244 try renderExpressionIndented(gpa, ais, tree, else_expr, space);
1264 try renderExpressionIndented(r, else_expr, space);
12451265 } else {
1246 try renderToken(ais, tree, last_else_token, .space);
1247 try renderExpression(gpa, ais, tree, else_expr, space);
1266 try renderToken(r, last_else_token, .space);
1267 try renderExpression(r, else_expr, space);
12481268 }
12491269 } else {
12501270 if (indent_then_expr) {
1251 try renderExpressionIndented(gpa, ais, tree, then_expr, space);
1271 try renderExpressionIndented(r, then_expr, space);
12521272 } else {
1253 try renderExpression(gpa, ais, tree, then_expr, space);
1273 try renderExpression(r, then_expr, space);
12541274 }
12551275 }
12561276}
12571277
1258fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space: Space) Error!void {
1278fn renderFor(r: Render, for_node: Ast.full.For, space: Space) Error!void {
1279 const tree = r.tree;
1280 const ais = r.ais;
12591281 const token_tags = tree.tokens.items(.tag);
12601282
12611283 if (for_node.label_token) |label| {
1262 try renderIdentifier(ais, tree, label, .none, .eagerly_unquote); // label
1263 try renderToken(ais, tree, label + 1, .space); // :
1284 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
1285 try renderToken(r, label + 1, .space); // :
12641286 }
12651287
12661288 if (for_node.inline_token) |inline_token| {
1267 try renderToken(ais, tree, inline_token, .space); // inline
1289 try renderToken(r, inline_token, .space); // inline
12681290 }
12691291
1270 try renderToken(ais, tree, for_node.ast.for_token, .space); // if/for/while
1292 try renderToken(r, for_node.ast.for_token, .space); // if/for/while
12711293
12721294 const lparen = for_node.ast.for_token + 1;
1273 try renderParamList(gpa, ais, tree, lparen, for_node.ast.inputs, .space);
1295 try renderParamList(r, lparen, for_node.ast.inputs, .space);
12741296
12751297 var cur = for_node.payload_token;
12761298 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
12771299 if (token_tags[pipe - 1] == .comma) {
12781300 ais.pushIndentNextLine();
1279 try renderToken(ais, tree, cur - 1, .newline); // |
1301 try renderToken(r, cur - 1, .newline); // |
12801302 while (true) {
12811303 if (token_tags[cur] == .asterisk) {
1282 try renderToken(ais, tree, cur, .none); // *
1304 try renderToken(r, cur, .none); // *
12831305 cur += 1;
12841306 }
1285 try renderIdentifier(ais, tree, cur, .none, .preserve_when_shadowing); // identifier
1307 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
12861308 cur += 1;
12871309 if (token_tags[cur] == .comma) {
1288 try renderToken(ais, tree, cur, .newline); // ,
1310 try renderToken(r, cur, .newline); // ,
12891311 cur += 1;
12901312 }
12911313 if (token_tags[cur] == .pipe) {
......@@ -1294,16 +1316,16 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
12941316 }
12951317 ais.popIndent();
12961318 } else {
1297 try renderToken(ais, tree, cur - 1, .none); // |
1319 try renderToken(r, cur - 1, .none); // |
12981320 while (true) {
12991321 if (token_tags[cur] == .asterisk) {
1300 try renderToken(ais, tree, cur, .none); // *
1322 try renderToken(r, cur, .none); // *
13011323 cur += 1;
13021324 }
1303 try renderIdentifier(ais, tree, cur, .none, .preserve_when_shadowing); // identifier
1325 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
13041326 cur += 1;
13051327 if (token_tags[cur] == .comma) {
1306 try renderToken(ais, tree, cur, .space); // ,
1328 try renderToken(r, cur, .space); // ,
13071329 cur += 1;
13081330 }
13091331 if (token_tags[cur] == .pipe) {
......@@ -1313,9 +1335,7 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
13131335 }
13141336
13151337 try renderThenElse(
1316 gpa,
1317 ais,
1318 tree,
1338 r,
13191339 cur,
13201340 for_node.ast.then_expr,
13211341 for_node.else_token,
......@@ -1326,13 +1346,13 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
13261346}
13271347
13281348fn renderContainerField(
1329 gpa: Allocator,
1330 ais: *Ais,
1331 tree: Ast,
1349 r: Render,
13321350 container: Container,
13331351 field_param: Ast.full.ContainerField,
13341352 space: Space,
13351353) Error!void {
1354 const tree = r.tree;
1355 const ais = r.ais;
13361356 var field = field_param;
13371357 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);
13381358 const quote: QuoteBehavior = switch (container) {
......@@ -1341,102 +1361,102 @@ fn renderContainerField(
13411361 };
13421362
13431363 if (field.comptime_token) |t| {
1344 try renderToken(ais, tree, t, .space); // comptime
1364 try renderToken(r, t, .space); // comptime
13451365 }
13461366 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {
13471367 if (field.ast.align_expr != 0) {
1348 try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name
1368 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
13491369 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
13501370 const align_kw = lparen_token - 1;
13511371 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1352 try renderToken(ais, tree, align_kw, .none); // align
1353 try renderToken(ais, tree, lparen_token, .none); // (
1354 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1355 return renderToken(ais, tree, rparen_token, .space); // )
1372 try renderToken(r, align_kw, .none); // align
1373 try renderToken(r, lparen_token, .none); // (
1374 try renderExpression(r, field.ast.align_expr, .none); // alignment
1375 return renderToken(r, rparen_token, .space); // )
13561376 }
1357 return renderIdentifierComma(ais, tree, field.ast.main_token, space, quote); // name
1377 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
13581378 }
13591379 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {
13601380 if (!field.ast.tuple_like) {
1361 try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name
1362 try renderToken(ais, tree, field.ast.main_token + 1, .space); // :
1381 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1382 try renderToken(r, field.ast.main_token + 1, .space); // :
13631383 }
13641384
13651385 if (field.ast.align_expr != 0) {
1366 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type
1386 try renderExpression(r, field.ast.type_expr, .space); // type
13671387 const align_token = tree.firstToken(field.ast.align_expr) - 2;
1368 try renderToken(ais, tree, align_token, .none); // align
1369 try renderToken(ais, tree, align_token + 1, .none); // (
1370 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1388 try renderToken(r, align_token, .none); // align
1389 try renderToken(r, align_token + 1, .none); // (
1390 try renderExpression(r, field.ast.align_expr, .none); // alignment
13711391 const rparen = tree.lastToken(field.ast.align_expr) + 1;
1372 return renderTokenComma(ais, tree, rparen, space); // )
1392 return renderTokenComma(r, rparen, space); // )
13731393 } else {
1374 return renderExpressionComma(gpa, ais, tree, field.ast.type_expr, space); // type
1394 return renderExpressionComma(r, field.ast.type_expr, space); // type
13751395 }
13761396 }
13771397 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
1378 try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name
1398 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
13791399 if (field.ast.align_expr != 0) {
13801400 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
13811401 const align_kw = lparen_token - 1;
13821402 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1383 try renderToken(ais, tree, align_kw, .none); // align
1384 try renderToken(ais, tree, lparen_token, .none); // (
1385 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1386 try renderToken(ais, tree, rparen_token, .space); // )
1403 try renderToken(r, align_kw, .none); // align
1404 try renderToken(r, lparen_token, .none); // (
1405 try renderExpression(r, field.ast.align_expr, .none); // alignment
1406 try renderToken(r, rparen_token, .space); // )
13871407 }
1388 try renderToken(ais, tree, field.ast.main_token + 1, .space); // =
1389 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value
1408 try renderToken(r, field.ast.main_token + 1, .space); // =
1409 return renderExpressionComma(r, field.ast.value_expr, space); // value
13901410 }
13911411 if (!field.ast.tuple_like) {
1392 try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name
1393 try renderToken(ais, tree, field.ast.main_token + 1, .space); // :
1412 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1413 try renderToken(r, field.ast.main_token + 1, .space); // :
13941414 }
1395 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type
1415 try renderExpression(r, field.ast.type_expr, .space); // type
13961416
13971417 if (field.ast.align_expr != 0) {
13981418 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
13991419 const align_kw = lparen_token - 1;
14001420 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1401 try renderToken(ais, tree, align_kw, .none); // align
1402 try renderToken(ais, tree, lparen_token, .none); // (
1403 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment
1404 try renderToken(ais, tree, rparen_token, .space); // )
1421 try renderToken(r, align_kw, .none); // align
1422 try renderToken(r, lparen_token, .none); // (
1423 try renderExpression(r, field.ast.align_expr, .none); // alignment
1424 try renderToken(r, rparen_token, .space); // )
14051425 }
14061426 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
14071427 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
14081428 {
14091429 ais.pushIndent();
1410 try renderToken(ais, tree, eq_token, eq_space); // =
1430 try renderToken(r, eq_token, eq_space); // =
14111431 ais.popIndent();
14121432 }
14131433
14141434 if (eq_space == .space)
1415 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value
1435 return renderExpressionComma(r, field.ast.value_expr, space); // value
14161436
14171437 const token_tags = tree.tokens.items(.tag);
14181438 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
14191439
14201440 if (token_tags[maybe_comma] == .comma) {
14211441 ais.pushIndent();
1422 try renderExpression(gpa, ais, tree, field.ast.value_expr, .none); // value
1442 try renderExpression(r, field.ast.value_expr, .none); // value
14231443 ais.popIndent();
1424 try renderToken(ais, tree, maybe_comma, .newline);
1444 try renderToken(r, maybe_comma, .newline);
14251445 } else {
14261446 ais.pushIndent();
1427 try renderExpression(gpa, ais, tree, field.ast.value_expr, space); // value
1447 try renderExpression(r, field.ast.value_expr, space); // value
14281448 ais.popIndent();
14291449 }
14301450}
14311451
14321452fn renderBuiltinCall(
1433 gpa: Allocator,
1434 ais: *Ais,
1435 tree: Ast,
1453 r: Render,
14361454 builtin_token: Ast.TokenIndex,
14371455 params: []const Ast.Node.Index,
14381456 space: Space,
14391457) Error!void {
1458 const tree = r.tree;
1459 const ais = r.ais;
14401460 const token_tags = tree.tokens.items(.tag);
14411461
14421462 // TODO remove before release of 0.12.0
......@@ -1465,14 +1485,14 @@ fn renderBuiltinCall(
14651485 if (token_tags[after_last_param_token] != .comma) {
14661486 // Render all on one line, no trailing comma.
14671487 try ais.writer().writeAll("@as");
1468 try renderToken(ais, tree, builtin_token + 1, .none); // (
1469 try renderExpression(gpa, ais, tree, params[0], .comma_space);
1488 try renderToken(r, builtin_token + 1, .none); // (
1489 try renderExpression(r, params[0], .comma_space);
14701490 } else {
14711491 // Render one param per line.
14721492 try ais.writer().writeAll("@as");
14731493 ais.pushIndent();
1474 try renderToken(ais, tree, builtin_token + 1, .newline); // (
1475 try renderExpression(gpa, ais, tree, params[0], .comma);
1494 try renderToken(r, builtin_token + 1, .newline); // (
1495 try renderExpression(r, params[0], .comma);
14761496 }
14771497 }
14781498 // Corresponding logic below builtin name rewrite below
......@@ -1507,29 +1527,29 @@ fn renderBuiltinCall(
15071527 } else if (mem.eql(u8, slice, "@errSetCast")) {
15081528 try ais.writer().writeAll("@errorCast");
15091529 } else {
1510 try renderToken(ais, tree, builtin_token, .none); // @name
1530 try renderToken(r, builtin_token, .none); // @name
15111531 }
15121532
15131533 if (rewrite_two_param_cast) {
15141534 // Matches with corresponding logic above builtin name rewrite
15151535 const after_last_param_token = tree.lastToken(params[1]) + 1;
15161536 try ais.writer().writeAll("(");
1517 try renderExpression(gpa, ais, tree, params[1], .none);
1537 try renderExpression(r, params[1], .none);
15181538 try ais.writer().writeAll(")");
15191539 if (token_tags[after_last_param_token] != .comma) {
15201540 // Render all on one line, no trailing comma.
1521 return renderToken(ais, tree, after_last_param_token, space); // )
1541 return renderToken(r, after_last_param_token, space); // )
15221542 } else {
15231543 // Render one param per line.
15241544 ais.popIndent();
1525 try renderToken(ais, tree, after_last_param_token, .newline); // ,
1526 return renderToken(ais, tree, after_last_param_token + 1, space); // )
1545 try renderToken(r, after_last_param_token, .newline); // ,
1546 return renderToken(r, after_last_param_token + 1, space); // )
15271547 }
15281548 }
15291549
15301550 if (params.len == 0) {
1531 try renderToken(ais, tree, builtin_token + 1, .none); // (
1532 return renderToken(ais, tree, builtin_token + 2, space); // )
1551 try renderToken(r, builtin_token + 1, .none); // (
1552 return renderToken(r, builtin_token + 2, space); // )
15331553 }
15341554
15351555 const last_param = params[params.len - 1];
......@@ -1537,7 +1557,7 @@ fn renderBuiltinCall(
15371557
15381558 if (token_tags[after_last_param_token] != .comma) {
15391559 // Render all on one line, no trailing comma.
1540 try renderToken(ais, tree, builtin_token + 1, .none); // (
1560 try renderToken(r, builtin_token + 1, .none); // (
15411561
15421562 for (params, 0..) |param_node, i| {
15431563 const first_param_token = tree.firstToken(param_node);
......@@ -1546,39 +1566,41 @@ fn renderBuiltinCall(
15461566 {
15471567 ais.pushIndentOneShot();
15481568 }
1549 try renderExpression(gpa, ais, tree, param_node, .none);
1569 try renderExpression(r, param_node, .none);
15501570
15511571 if (i + 1 < params.len) {
15521572 const comma_token = tree.lastToken(param_node) + 1;
1553 try renderToken(ais, tree, comma_token, .space); // ,
1573 try renderToken(r, comma_token, .space); // ,
15541574 }
15551575 }
1556 return renderToken(ais, tree, after_last_param_token, space); // )
1576 return renderToken(r, after_last_param_token, space); // )
15571577 } else {
15581578 // Render one param per line.
15591579 ais.pushIndent();
1560 try renderToken(ais, tree, builtin_token + 1, Space.newline); // (
1580 try renderToken(r, builtin_token + 1, Space.newline); // (
15611581
15621582 for (params) |param_node| {
1563 try renderExpression(gpa, ais, tree, param_node, .comma);
1583 try renderExpression(r, param_node, .comma);
15641584 }
15651585 ais.popIndent();
15661586
1567 return renderToken(ais, tree, after_last_param_token + 1, space); // )
1587 return renderToken(r, after_last_param_token + 1, space); // )
15681588 }
15691589}
15701590
1571fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProto, space: Space) Error!void {
1591fn renderFnProto(r: Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
1592 const tree = r.tree;
1593 const ais = r.ais;
15721594 const token_tags = tree.tokens.items(.tag);
15731595 const token_starts = tree.tokens.items(.start);
15741596
15751597 const after_fn_token = fn_proto.ast.fn_token + 1;
15761598 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {
1577 try renderToken(ais, tree, fn_proto.ast.fn_token, .space); // fn
1578 try renderIdentifier(ais, tree, after_fn_token, .none, .preserve_when_shadowing); // name
1599 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1600 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
15791601 break :blk after_fn_token + 1;
15801602 } else blk: {
1581 try renderToken(ais, tree, fn_proto.ast.fn_token, .space); // fn
1603 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
15821604 break :blk fn_proto.ast.fn_token + 1;
15831605 };
15841606 assert(token_tags[lparen] == .l_paren);
......@@ -1630,7 +1652,7 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
16301652 const trailing_comma = token_tags[rparen - 1] == .comma;
16311653 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
16321654 // Render all on one line, no trailing comma.
1633 try renderToken(ais, tree, lparen, .none); // (
1655 try renderToken(r, lparen, .none); // (
16341656
16351657 var param_i: usize = 0;
16361658 var last_param_token = lparen;
......@@ -1638,25 +1660,25 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
16381660 last_param_token += 1;
16391661 switch (token_tags[last_param_token]) {
16401662 .doc_comment => {
1641 try renderToken(ais, tree, last_param_token, .newline);
1663 try renderToken(r, last_param_token, .newline);
16421664 continue;
16431665 },
16441666 .ellipsis3 => {
1645 try renderToken(ais, tree, last_param_token, .none); // ...
1667 try renderToken(r, last_param_token, .none); // ...
16461668 break;
16471669 },
16481670 .keyword_noalias, .keyword_comptime => {
1649 try renderToken(ais, tree, last_param_token, .space);
1671 try renderToken(r, last_param_token, .space);
16501672 last_param_token += 1;
16511673 },
16521674 .identifier => {},
16531675 .keyword_anytype => {
1654 try renderToken(ais, tree, last_param_token, .none); // anytype
1676 try renderToken(r, last_param_token, .none); // anytype
16551677 continue;
16561678 },
16571679 .r_paren => break,
16581680 .comma => {
1659 try renderToken(ais, tree, last_param_token, .space); // ,
1681 try renderToken(r, last_param_token, .space); // ,
16601682 continue;
16611683 },
16621684 else => {}, // Parameter type without a name.
......@@ -1664,24 +1686,24 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
16641686 if (token_tags[last_param_token] == .identifier and
16651687 token_tags[last_param_token + 1] == .colon)
16661688 {
1667 try renderIdentifier(ais, tree, last_param_token, .none, .preserve_when_shadowing); // name
1689 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
16681690 last_param_token += 1;
1669 try renderToken(ais, tree, last_param_token, .space); // :
1691 try renderToken(r, last_param_token, .space); // :
16701692 last_param_token += 1;
16711693 }
16721694 if (token_tags[last_param_token] == .keyword_anytype) {
1673 try renderToken(ais, tree, last_param_token, .none); // anytype
1695 try renderToken(r, last_param_token, .none); // anytype
16741696 continue;
16751697 }
16761698 const param = fn_proto.ast.params[param_i];
16771699 param_i += 1;
1678 try renderExpression(gpa, ais, tree, param, .none);
1700 try renderExpression(r, param, .none);
16791701 last_param_token = tree.lastToken(param);
16801702 }
16811703 } else {
16821704 // One param per line.
16831705 ais.pushIndent();
1684 try renderToken(ais, tree, lparen, .newline); // (
1706 try renderToken(r, lparen, .newline); // (
16851707
16861708 var param_i: usize = 0;
16871709 var last_param_token = lparen;
......@@ -1689,20 +1711,20 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
16891711 last_param_token += 1;
16901712 switch (token_tags[last_param_token]) {
16911713 .doc_comment => {
1692 try renderToken(ais, tree, last_param_token, .newline);
1714 try renderToken(r, last_param_token, .newline);
16931715 continue;
16941716 },
16951717 .ellipsis3 => {
1696 try renderToken(ais, tree, last_param_token, .comma); // ...
1718 try renderToken(r, last_param_token, .comma); // ...
16971719 break;
16981720 },
16991721 .keyword_noalias, .keyword_comptime => {
1700 try renderToken(ais, tree, last_param_token, .space);
1722 try renderToken(r, last_param_token, .space);
17011723 last_param_token += 1;
17021724 },
17031725 .identifier => {},
17041726 .keyword_anytype => {
1705 try renderToken(ais, tree, last_param_token, .comma); // anytype
1727 try renderToken(r, last_param_token, .comma); // anytype
17061728 if (token_tags[last_param_token + 1] == .comma)
17071729 last_param_token += 1;
17081730 continue;
......@@ -1713,56 +1735,56 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
17131735 if (token_tags[last_param_token] == .identifier and
17141736 token_tags[last_param_token + 1] == .colon)
17151737 {
1716 try renderIdentifier(ais, tree, last_param_token, .none, .preserve_when_shadowing); // name
1738 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
17171739 last_param_token += 1;
1718 try renderToken(ais, tree, last_param_token, .space); // :
1740 try renderToken(r, last_param_token, .space); // :
17191741 last_param_token += 1;
17201742 }
17211743 if (token_tags[last_param_token] == .keyword_anytype) {
1722 try renderToken(ais, tree, last_param_token, .comma); // anytype
1744 try renderToken(r, last_param_token, .comma); // anytype
17231745 if (token_tags[last_param_token + 1] == .comma)
17241746 last_param_token += 1;
17251747 continue;
17261748 }
17271749 const param = fn_proto.ast.params[param_i];
17281750 param_i += 1;
1729 try renderExpression(gpa, ais, tree, param, .comma);
1751 try renderExpression(r, param, .comma);
17301752 last_param_token = tree.lastToken(param);
17311753 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;
17321754 }
17331755 ais.popIndent();
17341756 }
17351757
1736 try renderToken(ais, tree, rparen, .space); // )
1758 try renderToken(r, rparen, .space); // )
17371759
17381760 if (fn_proto.ast.align_expr != 0) {
17391761 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;
17401762 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;
17411763
1742 try renderToken(ais, tree, align_lparen - 1, .none); // align
1743 try renderToken(ais, tree, align_lparen, .none); // (
1744 try renderExpression(gpa, ais, tree, fn_proto.ast.align_expr, .none);
1745 try renderToken(ais, tree, align_rparen, .space); // )
1764 try renderToken(r, align_lparen - 1, .none); // align
1765 try renderToken(r, align_lparen, .none); // (
1766 try renderExpression(r, fn_proto.ast.align_expr, .none);
1767 try renderToken(r, align_rparen, .space); // )
17461768 }
17471769
17481770 if (fn_proto.ast.addrspace_expr != 0) {
17491771 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;
17501772 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;
17511773
1752 try renderToken(ais, tree, align_lparen - 1, .none); // addrspace
1753 try renderToken(ais, tree, align_lparen, .none); // (
1754 try renderExpression(gpa, ais, tree, fn_proto.ast.addrspace_expr, .none);
1755 try renderToken(ais, tree, align_rparen, .space); // )
1774 try renderToken(r, align_lparen - 1, .none); // addrspace
1775 try renderToken(r, align_lparen, .none); // (
1776 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);
1777 try renderToken(r, align_rparen, .space); // )
17561778 }
17571779
17581780 if (fn_proto.ast.section_expr != 0) {
17591781 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;
17601782 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;
17611783
1762 try renderToken(ais, tree, section_lparen - 1, .none); // section
1763 try renderToken(ais, tree, section_lparen, .none); // (
1764 try renderExpression(gpa, ais, tree, fn_proto.ast.section_expr, .none);
1765 try renderToken(ais, tree, section_rparen, .space); // )
1784 try renderToken(r, section_lparen - 1, .none); // section
1785 try renderToken(r, section_lparen, .none); // (
1786 try renderExpression(r, fn_proto.ast.section_expr, .none);
1787 try renderToken(r, section_rparen, .space); // )
17661788 }
17671789
17681790 const is_callconv_inline = mem.eql(u8, "Inline", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));
......@@ -1771,25 +1793,24 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
17711793 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;
17721794 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;
17731795
1774 try renderToken(ais, tree, callconv_lparen - 1, .none); // callconv
1775 try renderToken(ais, tree, callconv_lparen, .none); // (
1776 try renderExpression(gpa, ais, tree, fn_proto.ast.callconv_expr, .none);
1777 try renderToken(ais, tree, callconv_rparen, .space); // )
1796 try renderToken(r, callconv_lparen - 1, .none); // callconv
1797 try renderToken(r, callconv_lparen, .none); // (
1798 try renderExpression(r, fn_proto.ast.callconv_expr, .none);
1799 try renderToken(r, callconv_rparen, .space); // )
17781800 }
17791801
17801802 if (token_tags[maybe_bang] == .bang) {
1781 try renderToken(ais, tree, maybe_bang, .none); // !
1803 try renderToken(r, maybe_bang, .none); // !
17821804 }
1783 return renderExpression(gpa, ais, tree, fn_proto.ast.return_type, space);
1805 return renderExpression(r, fn_proto.ast.return_type, space);
17841806}
17851807
17861808fn renderSwitchCase(
1787 gpa: Allocator,
1788 ais: *Ais,
1789 tree: Ast,
1809 r: Render,
17901810 switch_case: Ast.full.SwitchCase,
17911811 space: Space,
17921812) Error!void {
1813 const tree = r.tree;
17931814 const node_tags = tree.nodes.items(.tag);
17941815 const token_tags = tree.tokens.items(.tag);
17951816 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
......@@ -1800,22 +1821,22 @@ fn renderSwitchCase(
18001821
18011822 // render inline keyword
18021823 if (switch_case.inline_token) |some| {
1803 try renderToken(ais, tree, some, .space);
1824 try renderToken(r, some, .space);
18041825 }
18051826
18061827 // Render everything before the arrow
18071828 if (switch_case.ast.values.len == 0) {
1808 try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .space); // else keyword
1829 try renderToken(r, switch_case.ast.arrow_token - 1, .space); // else keyword
18091830 } else if (switch_case.ast.values.len == 1 and !has_comment_before_arrow) {
18101831 // render on one line and drop the trailing comma if any
1811 try renderExpression(gpa, ais, tree, switch_case.ast.values[0], .space);
1832 try renderExpression(r, switch_case.ast.values[0], .space);
18121833 } else if (trailing_comma or has_comment_before_arrow) {
18131834 // Render each value on a new line
1814 try renderExpressions(gpa, ais, tree, switch_case.ast.values, .comma);
1835 try renderExpressions(r, switch_case.ast.values, .comma);
18151836 } else {
18161837 // Render on one line
18171838 for (switch_case.ast.values) |value_expr| {
1818 try renderExpression(gpa, ais, tree, value_expr, .comma_space);
1839 try renderExpression(r, value_expr, .comma_space);
18191840 }
18201841 }
18211842
......@@ -1826,35 +1847,35 @@ fn renderSwitchCase(
18261847 else
18271848 Space.space;
18281849 const after_arrow_space: Space = if (switch_case.payload_token == null) pre_target_space else .space;
1829 try renderToken(ais, tree, switch_case.ast.arrow_token, after_arrow_space); // =>
1850 try renderToken(r, switch_case.ast.arrow_token, after_arrow_space); // =>
18301851
18311852 if (switch_case.payload_token) |payload_token| {
1832 try renderToken(ais, tree, payload_token - 1, .none); // pipe
1853 try renderToken(r, payload_token - 1, .none); // pipe
18331854 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);
18341855 if (token_tags[payload_token] == .asterisk) {
1835 try renderToken(ais, tree, payload_token, .none); // asterisk
1856 try renderToken(r, payload_token, .none); // asterisk
18361857 }
1837 try renderIdentifier(ais, tree, ident, .none, .preserve_when_shadowing); // identifier
1858 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
18381859 if (token_tags[ident + 1] == .comma) {
1839 try renderToken(ais, tree, ident + 1, .space); // ,
1840 try renderIdentifier(ais, tree, ident + 2, .none, .preserve_when_shadowing); // identifier
1841 try renderToken(ais, tree, ident + 3, pre_target_space); // pipe
1860 try renderToken(r, ident + 1, .space); // ,
1861 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
1862 try renderToken(r, ident + 3, pre_target_space); // pipe
18421863 } else {
1843 try renderToken(ais, tree, ident + 1, pre_target_space); // pipe
1864 try renderToken(r, ident + 1, pre_target_space); // pipe
18441865 }
18451866 }
18461867
1847 try renderExpression(gpa, ais, tree, switch_case.ast.target_expr, space);
1868 try renderExpression(r, switch_case.ast.target_expr, space);
18481869}
18491870
18501871fn renderBlock(
1851 gpa: Allocator,
1852 ais: *Ais,
1853 tree: Ast,
1872 r: Render,
18541873 block_node: Ast.Node.Index,
18551874 statements: []const Ast.Node.Index,
18561875 space: Space,
18571876) Error!void {
1877 const tree = r.tree;
1878 const ais = r.ais;
18581879 const token_tags = tree.tokens.items(.tag);
18591880 const node_tags = tree.nodes.items(.tag);
18601881 const lbrace = tree.nodes.items(.main_token)[block_node];
......@@ -1862,51 +1883,51 @@ fn renderBlock(
18621883 if (token_tags[lbrace - 1] == .colon and
18631884 token_tags[lbrace - 2] == .identifier)
18641885 {
1865 try renderIdentifier(ais, tree, lbrace - 2, .none, .eagerly_unquote); // identifier
1866 try renderToken(ais, tree, lbrace - 1, .space); // :
1886 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
1887 try renderToken(r, lbrace - 1, .space); // :
18671888 }
18681889
18691890 ais.pushIndentNextLine();
18701891 if (statements.len == 0) {
1871 try renderToken(ais, tree, lbrace, .none);
1892 try renderToken(r, lbrace, .none);
18721893 } else {
1873 try renderToken(ais, tree, lbrace, .newline);
1894 try renderToken(r, lbrace, .newline);
18741895 for (statements, 0..) |stmt, i| {
1875 if (i != 0) try renderExtraNewline(ais, tree, stmt);
1896 if (i != 0) try renderExtraNewline(r, stmt);
18761897 switch (node_tags[stmt]) {
18771898 .global_var_decl,
18781899 .local_var_decl,
18791900 .simple_var_decl,
18801901 .aligned_var_decl,
1881 => try renderVarDecl(gpa, ais, tree, tree.fullVarDecl(stmt).?, false, .semicolon),
1882 else => try renderExpression(gpa, ais, tree, stmt, .semicolon),
1902 => try renderVarDecl(r, tree.fullVarDecl(stmt).?, false, .semicolon),
1903 else => try renderExpression(r, stmt, .semicolon),
18831904 }
18841905 }
18851906 }
18861907 ais.popIndent();
18871908
1888 try renderToken(ais, tree, tree.lastToken(block_node), space); // rbrace
1909 try renderToken(r, tree.lastToken(block_node), space); // rbrace
18891910}
18901911
18911912fn renderStructInit(
1892 gpa: Allocator,
1893 ais: *Ais,
1894 tree: Ast,
1913 r: Render,
18951914 struct_node: Ast.Node.Index,
18961915 struct_init: Ast.full.StructInit,
18971916 space: Space,
18981917) Error!void {
1918 const tree = r.tree;
1919 const ais = r.ais;
18991920 const token_tags = tree.tokens.items(.tag);
19001921 if (struct_init.ast.type_expr == 0) {
1901 try renderToken(ais, tree, struct_init.ast.lbrace - 1, .none); // .
1922 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
19021923 } else {
1903 try renderExpression(gpa, ais, tree, struct_init.ast.type_expr, .none); // T
1924 try renderExpression(r, struct_init.ast.type_expr, .none); // T
19041925 }
19051926 if (struct_init.ast.fields.len == 0) {
19061927 ais.pushIndentNextLine();
1907 try renderToken(ais, tree, struct_init.ast.lbrace, .none); // lbrace
1928 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
19081929 ais.popIndent();
1909 return renderToken(ais, tree, struct_init.ast.lbrace + 1, space); // rbrace
1930 return renderToken(r, struct_init.ast.lbrace + 1, space); // rbrace
19101931 }
19111932
19121933 const rbrace = tree.lastToken(struct_node);
......@@ -1914,65 +1935,66 @@ fn renderStructInit(
19141935 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
19151936 // Render one field init per line.
19161937 ais.pushIndentNextLine();
1917 try renderToken(ais, tree, struct_init.ast.lbrace, .newline);
1938 try renderToken(r, struct_init.ast.lbrace, .newline);
19181939
1919 try renderToken(ais, tree, struct_init.ast.lbrace + 1, .none); // .
1920 try renderIdentifier(ais, tree, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
1940 try renderToken(r, struct_init.ast.lbrace + 1, .none); // .
1941 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
19211942 // Don't output a space after the = if expression is a multiline string,
19221943 // since then it will start on the next line.
19231944 const nodes = tree.nodes.items(.tag);
19241945 const expr = nodes[struct_init.ast.fields[0]];
19251946 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
1926 try renderToken(ais, tree, struct_init.ast.lbrace + 3, space_after_equal); // =
1927 try renderExpression(gpa, ais, tree, struct_init.ast.fields[0], .comma);
1947 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
1948 try renderExpression(r, struct_init.ast.fields[0], .comma);
19281949
19291950 for (struct_init.ast.fields[1..]) |field_init| {
19301951 const init_token = tree.firstToken(field_init);
1931 try renderExtraNewlineToken(ais, tree, init_token - 3);
1932 try renderToken(ais, tree, init_token - 3, .none); // .
1933 try renderIdentifier(ais, tree, init_token - 2, .space, .eagerly_unquote); // name
1952 try renderExtraNewlineToken(r, init_token - 3);
1953 try renderToken(r, init_token - 3, .none); // .
1954 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
19341955 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;
1935 try renderToken(ais, tree, init_token - 1, space_after_equal); // =
1936 try renderExpression(gpa, ais, tree, field_init, .comma);
1956 try renderToken(r, init_token - 1, space_after_equal); // =
1957 try renderExpression(r, field_init, .comma);
19371958 }
19381959
19391960 ais.popIndent();
19401961 } else {
19411962 // Render all on one line, no trailing comma.
1942 try renderToken(ais, tree, struct_init.ast.lbrace, .space);
1963 try renderToken(r, struct_init.ast.lbrace, .space);
19431964
19441965 for (struct_init.ast.fields) |field_init| {
19451966 const init_token = tree.firstToken(field_init);
1946 try renderToken(ais, tree, init_token - 3, .none); // .
1947 try renderIdentifier(ais, tree, init_token - 2, .space, .eagerly_unquote); // name
1948 try renderToken(ais, tree, init_token - 1, .space); // =
1949 try renderExpression(gpa, ais, tree, field_init, .comma_space);
1967 try renderToken(r, init_token - 3, .none); // .
1968 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
1969 try renderToken(r, init_token - 1, .space); // =
1970 try renderExpression(r, field_init, .comma_space);
19501971 }
19511972 }
19521973
1953 return renderToken(ais, tree, rbrace, space);
1974 return renderToken(r, rbrace, space);
19541975}
19551976
19561977fn renderArrayInit(
1957 gpa: Allocator,
1958 ais: *Ais,
1959 tree: Ast,
1978 r: Render,
19601979 array_init: Ast.full.ArrayInit,
19611980 space: Space,
19621981) Error!void {
1982 const tree = r.tree;
1983 const ais = r.ais;
1984 const gpa = r.gpa;
19631985 const token_tags = tree.tokens.items(.tag);
19641986
19651987 if (array_init.ast.type_expr == 0) {
1966 try renderToken(ais, tree, array_init.ast.lbrace - 1, .none); // .
1988 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
19671989 } else {
1968 try renderExpression(gpa, ais, tree, array_init.ast.type_expr, .none); // T
1990 try renderExpression(r, array_init.ast.type_expr, .none); // T
19691991 }
19701992
19711993 if (array_init.ast.elements.len == 0) {
19721994 ais.pushIndentNextLine();
1973 try renderToken(ais, tree, array_init.ast.lbrace, .none); // lbrace
1995 try renderToken(r, array_init.ast.lbrace, .none); // lbrace
19741996 ais.popIndent();
1975 return renderToken(ais, tree, array_init.ast.lbrace + 1, space); // rbrace
1997 return renderToken(r, array_init.ast.lbrace + 1, space); // rbrace
19761998 }
19771999
19782000 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
......@@ -1987,9 +2009,9 @@ fn renderArrayInit(
19872009 if (token_tags[first_token] != .multiline_string_literal_line and
19882010 !anythingBetween(tree, last_elem_token, rbrace))
19892011 {
1990 try renderToken(ais, tree, array_init.ast.lbrace, .none);
1991 try renderExpression(gpa, ais, tree, only_elem, .none);
1992 return renderToken(ais, tree, rbrace, space);
2012 try renderToken(r, array_init.ast.lbrace, .none);
2013 try renderExpression(r, only_elem, .none);
2014 return renderToken(r, rbrace, space);
19932015 }
19942016 }
19952017
......@@ -2000,19 +2022,19 @@ fn renderArrayInit(
20002022 // Render all on one line, no trailing comma.
20012023 if (array_init.ast.elements.len == 1) {
20022024 // If there is only one element, we don't use spaces
2003 try renderToken(ais, tree, array_init.ast.lbrace, .none);
2004 try renderExpression(gpa, ais, tree, array_init.ast.elements[0], .none);
2025 try renderToken(r, array_init.ast.lbrace, .none);
2026 try renderExpression(r, array_init.ast.elements[0], .none);
20052027 } else {
2006 try renderToken(ais, tree, array_init.ast.lbrace, .space);
2028 try renderToken(r, array_init.ast.lbrace, .space);
20072029 for (array_init.ast.elements) |elem| {
2008 try renderExpression(gpa, ais, tree, elem, .comma_space);
2030 try renderExpression(r, elem, .comma_space);
20092031 }
20102032 }
2011 return renderToken(ais, tree, last_elem_token + 1, space); // rbrace
2033 return renderToken(r, last_elem_token + 1, space); // rbrace
20122034 }
20132035
20142036 ais.pushIndentNextLine();
2015 try renderToken(ais, tree, array_init.ast.lbrace, .newline);
2037 try renderToken(r, array_init.ast.lbrace, .newline);
20162038
20172039 var expr_index: usize = 0;
20182040 while (true) {
......@@ -2068,6 +2090,12 @@ fn renderArrayInit(
20682090 .indent_delta = indent_delta,
20692091 .underlying_writer = sub_expr_buffer.writer(),
20702092 };
2093 var sub_render: Render = .{
2094 .gpa = r.gpa,
2095 .ais = &auto_indenting_stream,
2096 .tree = r.tree,
2097 .fixups = r.fixups,
2098 };
20712099
20722100 // Calculate size of columns in current section
20732101 var column_counter: usize = 0;
......@@ -2078,7 +2106,7 @@ fn renderArrayInit(
20782106 sub_expr_buffer_starts[i] = start;
20792107
20802108 if (i + 1 < section_exprs.len) {
2081 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .none);
2109 try renderExpression(sub_render, expr, .none);
20822110 const width = sub_expr_buffer.items.len - start;
20832111 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;
20842112 contains_newline = contains_newline or this_contains_newline;
......@@ -2098,7 +2126,7 @@ fn renderArrayInit(
20982126 column_counter = 0;
20992127 }
21002128 } else {
2101 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .comma);
2129 try renderExpression(sub_render, expr, .comma);
21022130 const width = sub_expr_buffer.items.len - start - 2;
21032131 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;
21042132 contains_newline = contains_newline or this_contains_newline;
......@@ -2143,7 +2171,7 @@ fn renderArrayInit(
21432171 if (column_counter != row_size - 1) {
21442172 if (!expr_newlines[i] and !expr_newlines[i + 1]) {
21452173 // Neither the current or next expression is multiline
2146 try renderToken(ais, tree, comma, .space); // ,
2174 try renderToken(r, comma, .space); // ,
21472175 assert(column_widths[column_counter % row_size] >= expr_widths[i]);
21482176 const padding = column_widths[column_counter % row_size] - expr_widths[i];
21492177 try ais.writer().writeByteNTimes(' ', padding);
......@@ -2154,13 +2182,13 @@ fn renderArrayInit(
21542182 }
21552183
21562184 if (single_line and row_size != 1) {
2157 try renderToken(ais, tree, comma, .space); // ,
2185 try renderToken(r, comma, .space); // ,
21582186 continue;
21592187 }
21602188
21612189 column_counter = 0;
2162 try renderToken(ais, tree, comma, .newline); // ,
2163 try renderExtraNewline(ais, tree, next_expr);
2190 try renderToken(r, comma, .newline); // ,
2191 try renderExtraNewline(r, next_expr);
21642192 }
21652193 }
21662194
......@@ -2169,21 +2197,21 @@ fn renderArrayInit(
21692197 }
21702198
21712199 ais.popIndent();
2172 return renderToken(ais, tree, rbrace, space); // rbrace
2200 return renderToken(r, rbrace, space); // rbrace
21732201}
21742202
21752203fn renderContainerDecl(
2176 gpa: Allocator,
2177 ais: *Ais,
2178 tree: Ast,
2204 r: Render,
21792205 container_decl_node: Ast.Node.Index,
21802206 container_decl: Ast.full.ContainerDecl,
21812207 space: Space,
21822208) Error!void {
2209 const tree = r.tree;
2210 const ais = r.ais;
21832211 const token_tags = tree.tokens.items(.tag);
21842212
21852213 if (container_decl.layout_token) |layout_token| {
2186 try renderToken(ais, tree, layout_token, .space);
2214 try renderToken(r, layout_token, .space);
21872215 }
21882216
21892217 const container: Container = switch (token_tags[container_decl.ast.main_token]) {
......@@ -2196,29 +2224,29 @@ fn renderContainerDecl(
21962224
21972225 var lbrace: Ast.TokenIndex = undefined;
21982226 if (container_decl.ast.enum_token) |enum_token| {
2199 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union
2200 try renderToken(ais, tree, enum_token - 1, .none); // lparen
2201 try renderToken(ais, tree, enum_token, .none); // enum
2227 try renderToken(r, container_decl.ast.main_token, .none); // union
2228 try renderToken(r, enum_token - 1, .none); // lparen
2229 try renderToken(r, enum_token, .none); // enum
22022230 if (container_decl.ast.arg != 0) {
2203 try renderToken(ais, tree, enum_token + 1, .none); // lparen
2204 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);
2231 try renderToken(r, enum_token + 1, .none); // lparen
2232 try renderExpression(r, container_decl.ast.arg, .none);
22052233 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2206 try renderToken(ais, tree, rparen, .none); // rparen
2207 try renderToken(ais, tree, rparen + 1, .space); // rparen
2234 try renderToken(r, rparen, .none); // rparen
2235 try renderToken(r, rparen + 1, .space); // rparen
22082236 lbrace = rparen + 2;
22092237 } else {
2210 try renderToken(ais, tree, enum_token + 1, .space); // rparen
2238 try renderToken(r, enum_token + 1, .space); // rparen
22112239 lbrace = enum_token + 2;
22122240 }
22132241 } else if (container_decl.ast.arg != 0) {
2214 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union
2215 try renderToken(ais, tree, container_decl.ast.main_token + 1, .none); // lparen
2216 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);
2242 try renderToken(r, container_decl.ast.main_token, .none); // union
2243 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2244 try renderExpression(r, container_decl.ast.arg, .none);
22172245 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2218 try renderToken(ais, tree, rparen, .space); // rparen
2246 try renderToken(r, rparen, .space); // rparen
22192247 lbrace = rparen + 1;
22202248 } else {
2221 try renderToken(ais, tree, container_decl.ast.main_token, .space); // union
2249 try renderToken(r, container_decl.ast.main_token, .space); // union
22222250 lbrace = container_decl.ast.main_token + 1;
22232251 }
22242252
......@@ -2226,13 +2254,13 @@ fn renderContainerDecl(
22262254 if (container_decl.ast.members.len == 0) {
22272255 ais.pushIndentNextLine();
22282256 if (token_tags[lbrace + 1] == .container_doc_comment) {
2229 try renderToken(ais, tree, lbrace, .newline); // lbrace
2230 try renderContainerDocComments(ais, tree, lbrace + 1);
2257 try renderToken(r, lbrace, .newline); // lbrace
2258 try renderContainerDocComments(r, lbrace + 1);
22312259 } else {
2232 try renderToken(ais, tree, lbrace, .none); // lbrace
2260 try renderToken(r, lbrace, .none); // lbrace
22332261 }
22342262 ais.popIndent();
2235 return renderToken(ais, tree, rbrace, space); // rbrace
2263 return renderToken(r, rbrace, space); // rbrace
22362264 }
22372265
22382266 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;
......@@ -2258,52 +2286,52 @@ fn renderContainerDecl(
22582286 }
22592287
22602288 // Print all the declarations on the same line.
2261 try renderToken(ais, tree, lbrace, .space); // lbrace
2289 try renderToken(r, lbrace, .space); // lbrace
22622290 for (container_decl.ast.members) |member| {
2263 try renderMember(gpa, ais, tree, container, member, .space);
2291 try renderMember(r, container, member, .space);
22642292 }
2265 return renderToken(ais, tree, rbrace, space); // rbrace
2293 return renderToken(r, rbrace, space); // rbrace
22662294 }
22672295
22682296 // One member per line.
22692297 ais.pushIndentNextLine();
2270 try renderToken(ais, tree, lbrace, .newline); // lbrace
2298 try renderToken(r, lbrace, .newline); // lbrace
22712299 if (token_tags[lbrace + 1] == .container_doc_comment) {
2272 try renderContainerDocComments(ais, tree, lbrace + 1);
2300 try renderContainerDocComments(r, lbrace + 1);
22732301 }
22742302 for (container_decl.ast.members, 0..) |member, i| {
2275 if (i != 0) try renderExtraNewline(ais, tree, member);
2303 if (i != 0) try renderExtraNewline(r, member);
22762304 switch (tree.nodes.items(.tag)[member]) {
22772305 // For container fields, ensure a trailing comma is added if necessary.
22782306 .container_field_init,
22792307 .container_field_align,
22802308 .container_field,
2281 => try renderMember(gpa, ais, tree, container, member, .comma),
2309 => try renderMember(r, container, member, .comma),
22822310
2283 else => try renderMember(gpa, ais, tree, container, member, .newline),
2311 else => try renderMember(r, container, member, .newline),
22842312 }
22852313 }
22862314 ais.popIndent();
22872315
2288 return renderToken(ais, tree, rbrace, space); // rbrace
2316 return renderToken(r, rbrace, space); // rbrace
22892317}
22902318
22912319fn renderAsm(
2292 gpa: Allocator,
2293 ais: *Ais,
2294 tree: Ast,
2320 r: Render,
22952321 asm_node: Ast.full.Asm,
22962322 space: Space,
22972323) Error!void {
2324 const tree = r.tree;
2325 const ais = r.ais;
22982326 const token_tags = tree.tokens.items(.tag);
22992327
2300 try renderToken(ais, tree, asm_node.ast.asm_token, .space); // asm
2328 try renderToken(r, asm_node.ast.asm_token, .space); // asm
23012329
23022330 if (asm_node.volatile_token) |volatile_token| {
2303 try renderToken(ais, tree, volatile_token, .space); // volatile
2304 try renderToken(ais, tree, volatile_token + 1, .none); // lparen
2331 try renderToken(r, volatile_token, .space); // volatile
2332 try renderToken(r, volatile_token + 1, .none); // lparen
23052333 } else {
2306 try renderToken(ais, tree, asm_node.ast.asm_token + 1, .none); // lparen
2334 try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen
23072335 }
23082336
23092337 if (asm_node.ast.items.len == 0) {
......@@ -2311,27 +2339,27 @@ fn renderAsm(
23112339 if (asm_node.first_clobber) |first_clobber| {
23122340 // asm ("foo" ::: "a", "b")
23132341 // asm ("foo" ::: "a", "b",)
2314 try renderExpression(gpa, ais, tree, asm_node.ast.template, .space);
2342 try renderExpression(r, asm_node.ast.template, .space);
23152343 // Render the three colons.
2316 try renderToken(ais, tree, first_clobber - 3, .none);
2317 try renderToken(ais, tree, first_clobber - 2, .none);
2318 try renderToken(ais, tree, first_clobber - 1, .space);
2344 try renderToken(r, first_clobber - 3, .none);
2345 try renderToken(r, first_clobber - 2, .none);
2346 try renderToken(r, first_clobber - 1, .space);
23192347
23202348 var tok_i = first_clobber;
23212349 while (true) : (tok_i += 1) {
2322 try renderToken(ais, tree, tok_i, .none);
2350 try renderToken(r, tok_i, .none);
23232351 tok_i += 1;
23242352 switch (token_tags[tok_i]) {
23252353 .r_paren => {
23262354 ais.popIndent();
2327 return renderToken(ais, tree, tok_i, space);
2355 return renderToken(r, tok_i, space);
23282356 },
23292357 .comma => {
23302358 if (token_tags[tok_i + 1] == .r_paren) {
23312359 ais.popIndent();
2332 return renderToken(ais, tree, tok_i + 1, space);
2360 return renderToken(r, tok_i + 1, space);
23332361 } else {
2334 try renderToken(ais, tree, tok_i, .space);
2362 try renderToken(r, tok_i, .space);
23352363 }
23362364 },
23372365 else => unreachable,
......@@ -2339,40 +2367,40 @@ fn renderAsm(
23392367 }
23402368 } else {
23412369 // asm ("foo")
2342 try renderExpression(gpa, ais, tree, asm_node.ast.template, .none);
2370 try renderExpression(r, asm_node.ast.template, .none);
23432371 ais.popIndent();
2344 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
2372 return renderToken(r, asm_node.ast.rparen, space); // rparen
23452373 }
23462374 }
23472375
23482376 ais.pushIndent();
2349 try renderExpression(gpa, ais, tree, asm_node.ast.template, .newline);
2377 try renderExpression(r, asm_node.ast.template, .newline);
23502378 ais.setIndentDelta(asm_indent_delta);
23512379 const colon1 = tree.lastToken(asm_node.ast.template) + 1;
23522380
23532381 const colon2 = if (asm_node.outputs.len == 0) colon2: {
2354 try renderToken(ais, tree, colon1, .newline); // :
2382 try renderToken(r, colon1, .newline); // :
23552383 break :colon2 colon1 + 1;
23562384 } else colon2: {
2357 try renderToken(ais, tree, colon1, .space); // :
2385 try renderToken(r, colon1, .space); // :
23582386
23592387 ais.pushIndent();
23602388 for (asm_node.outputs, 0..) |asm_output, i| {
23612389 if (i + 1 < asm_node.outputs.len) {
23622390 const next_asm_output = asm_node.outputs[i + 1];
2363 try renderAsmOutput(gpa, ais, tree, asm_output, .none);
2391 try renderAsmOutput(r, asm_output, .none);
23642392
23652393 const comma = tree.firstToken(next_asm_output) - 1;
2366 try renderToken(ais, tree, comma, .newline); // ,
2367 try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));
2394 try renderToken(r, comma, .newline); // ,
2395 try renderExtraNewlineToken(r, tree.firstToken(next_asm_output));
23682396 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
2369 try renderAsmOutput(gpa, ais, tree, asm_output, .comma);
2397 try renderAsmOutput(r, asm_output, .comma);
23702398 ais.popIndent();
23712399 ais.setIndentDelta(indent_delta);
23722400 ais.popIndent();
2373 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
2401 return renderToken(r, asm_node.ast.rparen, space); // rparen
23742402 } else {
2375 try renderAsmOutput(gpa, ais, tree, asm_output, .comma);
2403 try renderAsmOutput(r, asm_output, .comma);
23762404 const comma_or_colon = tree.lastToken(asm_output) + 1;
23772405 ais.popIndent();
23782406 break :colon2 switch (token_tags[comma_or_colon]) {
......@@ -2384,27 +2412,27 @@ fn renderAsm(
23842412 };
23852413
23862414 const colon3 = if (asm_node.inputs.len == 0) colon3: {
2387 try renderToken(ais, tree, colon2, .newline); // :
2415 try renderToken(r, colon2, .newline); // :
23882416 break :colon3 colon2 + 1;
23892417 } else colon3: {
2390 try renderToken(ais, tree, colon2, .space); // :
2418 try renderToken(r, colon2, .space); // :
23912419 ais.pushIndent();
23922420 for (asm_node.inputs, 0..) |asm_input, i| {
23932421 if (i + 1 < asm_node.inputs.len) {
23942422 const next_asm_input = asm_node.inputs[i + 1];
2395 try renderAsmInput(gpa, ais, tree, asm_input, .none);
2423 try renderAsmInput(r, asm_input, .none);
23962424
23972425 const first_token = tree.firstToken(next_asm_input);
2398 try renderToken(ais, tree, first_token - 1, .newline); // ,
2399 try renderExtraNewlineToken(ais, tree, first_token);
2426 try renderToken(r, first_token - 1, .newline); // ,
2427 try renderExtraNewlineToken(r, first_token);
24002428 } else if (asm_node.first_clobber == null) {
2401 try renderAsmInput(gpa, ais, tree, asm_input, .comma);
2429 try renderAsmInput(r, asm_input, .comma);
24022430 ais.popIndent();
24032431 ais.setIndentDelta(indent_delta);
24042432 ais.popIndent();
2405 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen
2433 return renderToken(r, asm_node.ast.rparen, space); // rparen
24062434 } else {
2407 try renderAsmInput(gpa, ais, tree, asm_input, .comma);
2435 try renderAsmInput(r, asm_input, .comma);
24082436 const comma_or_colon = tree.lastToken(asm_input) + 1;
24092437 ais.popIndent();
24102438 break :colon3 switch (token_tags[comma_or_colon]) {
......@@ -2416,7 +2444,7 @@ fn renderAsm(
24162444 unreachable;
24172445 };
24182446
2419 try renderToken(ais, tree, colon3, .space); // :
2447 try renderToken(r, colon3, .space); // :
24202448 const first_clobber = asm_node.first_clobber.?;
24212449 var tok_i = first_clobber;
24222450 while (true) {
......@@ -2424,20 +2452,20 @@ fn renderAsm(
24242452 .r_paren => {
24252453 ais.setIndentDelta(indent_delta);
24262454 ais.popIndent();
2427 try renderToken(ais, tree, tok_i, .newline);
2428 return renderToken(ais, tree, tok_i + 1, space);
2455 try renderToken(r, tok_i, .newline);
2456 return renderToken(r, tok_i + 1, space);
24292457 },
24302458 .comma => {
24312459 switch (token_tags[tok_i + 2]) {
24322460 .r_paren => {
24332461 ais.setIndentDelta(indent_delta);
24342462 ais.popIndent();
2435 try renderToken(ais, tree, tok_i, .newline);
2436 return renderToken(ais, tree, tok_i + 2, space);
2463 try renderToken(r, tok_i, .newline);
2464 return renderToken(r, tok_i + 2, space);
24372465 },
24382466 else => {
2439 try renderToken(ais, tree, tok_i, .none);
2440 try renderToken(ais, tree, tok_i + 1, .space);
2467 try renderToken(r, tok_i, .none);
2468 try renderToken(r, tok_i + 1, .space);
24412469 tok_i += 2;
24422470 },
24432471 }
......@@ -2448,44 +2476,42 @@ fn renderAsm(
24482476}
24492477
24502478fn renderCall(
2451 gpa: Allocator,
2452 ais: *Ais,
2453 tree: Ast,
2479 r: Render,
24542480 call: Ast.full.Call,
24552481 space: Space,
24562482) Error!void {
24572483 if (call.async_token) |async_token| {
2458 try renderToken(ais, tree, async_token, .space);
2484 try renderToken(r, async_token, .space);
24592485 }
2460 try renderExpression(gpa, ais, tree, call.ast.fn_expr, .none);
2461 try renderParamList(gpa, ais, tree, call.ast.lparen, call.ast.params, space);
2486 try renderExpression(r, call.ast.fn_expr, .none);
2487 try renderParamList(r, call.ast.lparen, call.ast.params, space);
24622488}
24632489
24642490fn renderParamList(
2465 gpa: Allocator,
2466 ais: *Ais,
2467 tree: Ast,
2491 r: Render,
24682492 lparen: Ast.TokenIndex,
24692493 params: []const Ast.Node.Index,
24702494 space: Space,
24712495) Error!void {
2496 const tree = r.tree;
2497 const ais = r.ais;
24722498 const token_tags = tree.tokens.items(.tag);
24732499
24742500 if (params.len == 0) {
24752501 ais.pushIndentNextLine();
2476 try renderToken(ais, tree, lparen, .none);
2502 try renderToken(r, lparen, .none);
24772503 ais.popIndent();
2478 return renderToken(ais, tree, lparen + 1, space); // )
2504 return renderToken(r, lparen + 1, space); // )
24792505 }
24802506
24812507 const last_param = params[params.len - 1];
24822508 const after_last_param_tok = tree.lastToken(last_param) + 1;
24832509 if (token_tags[after_last_param_tok] == .comma) {
24842510 ais.pushIndentNextLine();
2485 try renderToken(ais, tree, lparen, .newline); // (
2511 try renderToken(r, lparen, .newline); // (
24862512 for (params, 0..) |param_node, i| {
24872513 if (i + 1 < params.len) {
2488 try renderExpression(gpa, ais, tree, param_node, .none);
2514 try renderExpression(r, param_node, .none);
24892515
24902516 // Unindent the comma for multiline string literals.
24912517 const is_multiline_string =
......@@ -2493,20 +2519,20 @@ fn renderParamList(
24932519 if (is_multiline_string) ais.popIndent();
24942520
24952521 const comma = tree.lastToken(param_node) + 1;
2496 try renderToken(ais, tree, comma, .newline); // ,
2522 try renderToken(r, comma, .newline); // ,
24972523
24982524 if (is_multiline_string) ais.pushIndent();
24992525
2500 try renderExtraNewline(ais, tree, params[i + 1]);
2526 try renderExtraNewline(r, params[i + 1]);
25012527 } else {
2502 try renderExpression(gpa, ais, tree, param_node, .comma);
2528 try renderExpression(r, param_node, .comma);
25032529 }
25042530 }
25052531 ais.popIndent();
2506 return renderToken(ais, tree, after_last_param_tok + 1, space); // )
2532 return renderToken(r, after_last_param_tok + 1, space); // )
25072533 }
25082534
2509 try renderToken(ais, tree, lparen, .none); // (
2535 try renderToken(r, lparen, .none); // (
25102536
25112537 for (params, 0..) |param_node, i| {
25122538 const first_param_token = tree.firstToken(param_node);
......@@ -2515,23 +2541,25 @@ fn renderParamList(
25152541 {
25162542 ais.pushIndentOneShot();
25172543 }
2518 try renderExpression(gpa, ais, tree, param_node, .none);
2544 try renderExpression(r, param_node, .none);
25192545
25202546 if (i + 1 < params.len) {
25212547 const comma = tree.lastToken(param_node) + 1;
25222548 const next_multiline_string =
25232549 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;
25242550 const comma_space: Space = if (next_multiline_string) .none else .space;
2525 try renderToken(ais, tree, comma, comma_space);
2551 try renderToken(r, comma, comma_space);
25262552 }
25272553 }
25282554
2529 return renderToken(ais, tree, after_last_param_tok, space); // )
2555 return renderToken(r, after_last_param_tok, space); // )
25302556}
25312557
25322558/// Renders the given expression indented, popping the indent before rendering
25332559/// any following line comments
2534fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index, space: Space) Error!void {
2560fn renderExpressionIndented(r: Render, node: Ast.Node.Index, space: Space) Error!void {
2561 const tree = r.tree;
2562 const ais = r.ais;
25352563 const token_starts = tree.tokens.items(.start);
25362564 const token_tags = tree.tokens.items(.tag);
25372565
......@@ -2545,24 +2573,24 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
25452573 .semicolon => token_tags[last_token + 1] == .semicolon,
25462574 };
25472575
2548 try renderExpression(gpa, ais, tree, node, if (punctuation) .none else .skip);
2576 try renderExpression(r, node, if (punctuation) .none else .skip);
25492577
25502578 switch (space) {
25512579 .none, .space, .newline, .skip => {},
25522580 .comma => {
25532581 if (token_tags[last_token + 1] == .comma) {
2554 try renderToken(ais, tree, last_token + 1, .skip);
2582 try renderToken(r, last_token + 1, .skip);
25552583 last_token += 1;
25562584 } else {
25572585 try ais.writer().writeByte(',');
25582586 }
25592587 },
25602588 .comma_space => if (token_tags[last_token + 1] == .comma) {
2561 try renderToken(ais, tree, last_token + 1, .skip);
2589 try renderToken(r, last_token + 1, .skip);
25622590 last_token += 1;
25632591 },
25642592 .semicolon => if (token_tags[last_token + 1] == .semicolon) {
2565 try renderToken(ais, tree, last_token + 1, .skip);
2593 try renderToken(r, last_token + 1, .skip);
25662594 last_token += 1;
25672595 },
25682596 }
......@@ -2572,7 +2600,7 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
25722600 if (space == .skip) return;
25732601
25742602 const comment_start = token_starts[last_token] + tokenSliceForRender(tree, last_token).len;
2575 const comment = try renderComments(ais, tree, comment_start, token_starts[last_token + 1]);
2603 const comment = try renderComments(r, comment_start, token_starts[last_token + 1]);
25762604
25772605 if (!comment) switch (space) {
25782606 .none => {},
......@@ -2589,40 +2617,43 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
25892617
25902618/// Render an expression, and the comma that follows it, if it is present in the source.
25912619/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2592fn renderExpressionComma(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index, space: Space) Error!void {
2620fn renderExpressionComma(r: Render, node: Ast.Node.Index, space: Space) Error!void {
2621 const tree = r.tree;
25932622 const token_tags = tree.tokens.items(.tag);
25942623 const maybe_comma = tree.lastToken(node) + 1;
25952624 if (token_tags[maybe_comma] == .comma and space != .comma) {
2596 try renderExpression(gpa, ais, tree, node, .none);
2597 return renderToken(ais, tree, maybe_comma, space);
2625 try renderExpression(r, node, .none);
2626 return renderToken(r, maybe_comma, space);
25982627 } else {
2599 return renderExpression(gpa, ais, tree, node, space);
2628 return renderExpression(r, node, space);
26002629 }
26012630}
26022631
26032632/// Render a token, and the comma that follows it, if it is present in the source.
26042633/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2605fn renderTokenComma(ais: *Ais, tree: Ast, token: Ast.TokenIndex, space: Space) Error!void {
2634fn renderTokenComma(r: Render, token: Ast.TokenIndex, space: Space) Error!void {
2635 const tree = r.tree;
26062636 const token_tags = tree.tokens.items(.tag);
26072637 const maybe_comma = token + 1;
26082638 if (token_tags[maybe_comma] == .comma and space != .comma) {
2609 try renderToken(ais, tree, token, .none);
2610 return renderToken(ais, tree, maybe_comma, space);
2639 try renderToken(r, token, .none);
2640 return renderToken(r, maybe_comma, space);
26112641 } else {
2612 return renderToken(ais, tree, token, space);
2642 return renderToken(r, token, space);
26132643 }
26142644}
26152645
26162646/// Render an identifier, and the comma that follows it, if it is present in the source.
26172647/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2618fn renderIdentifierComma(ais: *Ais, tree: Ast, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2648fn renderIdentifierComma(r: Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2649 const tree = r.tree;
26192650 const token_tags = tree.tokens.items(.tag);
26202651 const maybe_comma = token + 1;
26212652 if (token_tags[maybe_comma] == .comma and space != .comma) {
2622 try renderIdentifier(ais, tree, token, .none, quote);
2623 return renderToken(ais, tree, maybe_comma, space);
2653 try renderIdentifier(r, token, .none, quote);
2654 return renderToken(r, maybe_comma, space);
26242655 } else {
2625 return renderIdentifier(ais, tree, token, space, quote);
2656 return renderIdentifier(r, token, space, quote);
26262657 }
26272658}
26282659
......@@ -2647,13 +2678,17 @@ const Space = enum {
26472678 skip,
26482679};
26492680
2650fn renderToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Space) Error!void {
2681fn renderToken(r: Render, token_index: Ast.TokenIndex, space: Space) Error!void {
2682 const tree = r.tree;
2683 const ais = r.ais;
26512684 const lexeme = tokenSliceForRender(tree, token_index);
26522685 try ais.writer().writeAll(lexeme);
2653 try renderSpace(ais, tree, token_index, lexeme.len, space);
2686 try renderSpace(r, token_index, lexeme.len, space);
26542687}
26552688
2656fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2689fn renderSpace(r: Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2690 const tree = r.tree;
2691 const ais = r.ais;
26572692 const token_tags = tree.tokens.items(.tag);
26582693 const token_starts = tree.tokens.items(.start);
26592694
......@@ -2665,26 +2700,26 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us
26652700 try ais.writer().writeByte(',');
26662701 }
26672702
2668 const comment = try renderComments(ais, tree, token_start + lexeme_len, token_starts[token_index + 1]);
2703 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);
26692704 switch (space) {
26702705 .none => {},
26712706 .space => if (!comment) try ais.writer().writeByte(' '),
26722707 .newline => if (!comment) try ais.insertNewline(),
26732708
26742709 .comma => if (token_tags[token_index + 1] == .comma) {
2675 try renderToken(ais, tree, token_index + 1, .newline);
2710 try renderToken(r, token_index + 1, .newline);
26762711 } else if (!comment) {
26772712 try ais.insertNewline();
26782713 },
26792714
26802715 .comma_space => if (token_tags[token_index + 1] == .comma) {
2681 try renderToken(ais, tree, token_index + 1, .space);
2716 try renderToken(r, token_index + 1, .space);
26822717 } else if (!comment) {
26832718 try ais.writer().writeByte(' ');
26842719 },
26852720
26862721 .semicolon => if (token_tags[token_index + 1] == .semicolon) {
2687 try renderToken(ais, tree, token_index + 1, .newline);
2722 try renderToken(r, token_index + 1, .newline);
26882723 } else if (!comment) {
26892724 try ais.insertNewline();
26902725 },
......@@ -2699,12 +2734,13 @@ const QuoteBehavior = enum {
26992734 eagerly_unquote_except_underscore,
27002735};
27012736
2702fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2737fn renderIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2738 const tree = r.tree;
27032739 const token_tags = tree.tokens.items(.tag);
27042740 assert(token_tags[token_index] == .identifier);
27052741 const lexeme = tokenSliceForRender(tree, token_index);
27062742 if (lexeme[0] != '@') {
2707 return renderToken(ais, tree, token_index, space);
2743 return renderToken(r, token_index, space);
27082744 }
27092745
27102746 assert(lexeme.len >= 3);
......@@ -2715,15 +2751,15 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
27152751
27162752 // Empty name can't be unquoted.
27172753 if (contents.len == 0) {
2718 return renderQuotedIdentifier(ais, tree, token_index, space, false);
2754 return renderQuotedIdentifier(r, token_index, space, false);
27192755 }
27202756
27212757 // Special case for _ which would incorrectly be rejected by isValidId below.
27222758 if (contents.len == 1 and contents[0] == '_') switch (quote) {
2723 .eagerly_unquote => return renderQuotedIdentifier(ais, tree, token_index, space, true),
2759 .eagerly_unquote => return renderQuotedIdentifier(r, token_index, space, true),
27242760 .eagerly_unquote_except_underscore,
27252761 .preserve_when_shadowing,
2726 => return renderQuotedIdentifier(ais, tree, token_index, space, false),
2762 => return renderQuotedIdentifier(r, token_index, space, false),
27272763 };
27282764
27292765 // Scan the entire name for characters that would (after un-escaping) be illegal in a symbol,
......@@ -2731,23 +2767,23 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
27312767 var contents_i: usize = 0;
27322768 while (contents_i < contents.len) {
27332769 switch (contents[contents_i]) {
2734 '0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(ais, tree, token_index, space, false),
2770 '0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(r, token_index, space, false),
27352771 'A'...'Z', 'a'...'z', '_' => {},
27362772 '\\' => {
27372773 var esc_offset = contents_i;
27382774 const res = std.zig.string_literal.parseEscapeSequence(contents, &esc_offset);
27392775 switch (res) {
27402776 .success => |char| switch (char) {
2741 '0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(ais, tree, token_index, space, false),
2777 '0'...'9' => if (contents_i == 0) return renderQuotedIdentifier(r, token_index, space, false),
27422778 'A'...'Z', 'a'...'z', '_' => {},
2743 else => return renderQuotedIdentifier(ais, tree, token_index, space, false),
2779 else => return renderQuotedIdentifier(r, token_index, space, false),
27442780 },
2745 .failure => return renderQuotedIdentifier(ais, tree, token_index, space, false),
2781 .failure => return renderQuotedIdentifier(r, token_index, space, false),
27462782 }
27472783 contents_i += esc_offset;
27482784 continue;
27492785 },
2750 else => return renderQuotedIdentifier(ais, tree, token_index, space, false),
2786 else => return renderQuotedIdentifier(r, token_index, space, false),
27512787 }
27522788 contents_i += 1;
27532789 }
......@@ -2784,23 +2820,25 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
27842820 // We read the whole thing, so it could be a keyword or primitive.
27852821 if (contents_i == contents.len) {
27862822 if (!std.zig.isValidId(buf[0..buf_i])) {
2787 return renderQuotedIdentifier(ais, tree, token_index, space, false);
2823 return renderQuotedIdentifier(r, token_index, space, false);
27882824 }
27892825 if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) {
27902826 .eagerly_unquote,
27912827 .eagerly_unquote_except_underscore,
2792 => return renderQuotedIdentifier(ais, tree, token_index, space, true),
2793 .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false),
2828 => return renderQuotedIdentifier(r, token_index, space, true),
2829 .preserve_when_shadowing => return renderQuotedIdentifier(r, token_index, space, false),
27942830 };
27952831 }
27962832
2797 try renderQuotedIdentifier(ais, tree, token_index, space, true);
2833 try renderQuotedIdentifier(r, token_index, space, true);
27982834}
27992835
28002836// Renders a @"" quoted identifier, normalizing escapes.
28012837// Unnecessary escapes are un-escaped, and \u escapes are normalized to \x when they fit.
28022838// If unquote is true, the @"" is removed and the result is a bare symbol whose validity is asserted.
2803fn renderQuotedIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
2839fn renderQuotedIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
2840 const tree = r.tree;
2841 const ais = r.ais;
28042842 const token_tags = tree.tokens.items(.tag);
28052843 assert(token_tags[token_index] == .identifier);
28062844 const lexeme = tokenSliceForRender(tree, token_index);
......@@ -2811,7 +2849,7 @@ fn renderQuotedIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, spa
28112849 try renderIdentifierContents(ais.writer(), contents);
28122850 if (!unquote) try ais.writer().writeByte('\"');
28132851
2814 try renderSpace(ais, tree, token_index, lexeme.len, space);
2852 try renderSpace(r, token_index, lexeme.len, space);
28152853}
28162854
28172855fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
......@@ -2884,7 +2922,10 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
28842922
28852923/// Assumes that start is the first byte past the previous token and
28862924/// that end is the last byte before the next token.
2887fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {
2925fn renderComments(r: Render, start: usize, end: usize) Error!bool {
2926 const tree = r.tree;
2927 const ais = r.ais;
2928
28882929 var index: usize = start;
28892930 while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| {
28902931 const comment_start = index + offset;
......@@ -2944,12 +2985,14 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {
29442985 return index != start;
29452986}
29462987
2947fn renderExtraNewline(ais: *Ais, tree: Ast, node: Ast.Node.Index) Error!void {
2948 return renderExtraNewlineToken(ais, tree, tree.firstToken(node));
2988fn renderExtraNewline(r: Render, node: Ast.Node.Index) Error!void {
2989 return renderExtraNewlineToken(r, r.tree.firstToken(node));
29492990}
29502991
29512992/// Check if there is an empty line immediately before the given token. If so, render it.
2952fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Error!void {
2993fn renderExtraNewlineToken(r: Render, token_index: Ast.TokenIndex) Error!void {
2994 const tree = r.tree;
2995 const ais = r.ais;
29532996 const token_starts = tree.tokens.items(.start);
29542997 const token_start = token_starts[token_index];
29552998 if (token_start == 0) return;
......@@ -2974,7 +3017,8 @@ fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Er
29743017
29753018/// end_token is the token one past the last doc comment token. This function
29763019/// searches backwards from there.
2977fn renderDocComments(ais: *Ais, tree: Ast, end_token: Ast.TokenIndex) Error!void {
3020fn renderDocComments(r: Render, end_token: Ast.TokenIndex) Error!void {
3021 const tree = r.tree;
29783022 // Search backwards for the first doc comment.
29793023 const token_tags = tree.tokens.items(.tag);
29803024 if (end_token == 0) return;
......@@ -2995,27 +3039,28 @@ fn renderDocComments(ais: *Ais, tree: Ast, end_token: Ast.TokenIndex) Error!void
29953039 assert(prev_token_tag != .l_paren);
29963040
29973041 if (prev_token_tag != .l_brace) {
2998 try renderExtraNewlineToken(ais, tree, first_tok);
3042 try renderExtraNewlineToken(r, first_tok);
29993043 }
30003044 }
30013045
30023046 while (token_tags[tok] == .doc_comment) : (tok += 1) {
3003 try renderToken(ais, tree, tok, .newline);
3047 try renderToken(r, tok, .newline);
30043048 }
30053049}
30063050
30073051/// start_token is first container doc comment token.
3008fn renderContainerDocComments(ais: *Ais, tree: Ast, start_token: Ast.TokenIndex) Error!void {
3052fn renderContainerDocComments(r: Render, start_token: Ast.TokenIndex) Error!void {
3053 const tree = r.tree;
30093054 const token_tags = tree.tokens.items(.tag);
30103055 var tok = start_token;
30113056 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {
3012 try renderToken(ais, tree, tok, .newline);
3057 try renderToken(r, tok, .newline);
30133058 }
30143059 // Render extra newline if there is one between final container doc comment and
30153060 // the next token. If the next token is a doc comment, that code path
30163061 // will have its own logic to insert a newline.
30173062 if (token_tags[tok] != .doc_comment) {
3018 try renderExtraNewlineToken(ais, tree, tok);
3063 try renderExtraNewlineToken(r, tok);
30193064 }
30203065}
30213066