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 {...@@ -117,8 +117,10 @@ pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 {
117 return buffer.toOwnedSlice();117 return buffer.toOwnedSlice();
118}118}
119119
120pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8)) RenderError!void {120pub const Fixups = private_render.Fixups;
121 return @import("./render.zig").renderTree(buffer, tree);121
122pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8), fixups: Fixups) RenderError!void {
123 return @import("./render.zig").renderTree(buffer, tree, fixups);
122}124}
123125
124/// Returns an extra offset for column and byte offset of errors that126/// Returns an extra offset for column and byte offset of errors that
...@@ -3530,6 +3532,7 @@ const Token = std.zig.Token;...@@ -3530,6 +3532,7 @@ const Token = std.zig.Token;
3530const Ast = @This();3532const Ast = @This();
3531const Allocator = std.mem.Allocator;3533const Allocator = std.mem.Allocator;
3532const Parse = @import("Parse.zig");3534const Parse = @import("Parse.zig");
3535const private_render = @import("./render.zig");
35333536
3534test {3537test {
3535 testing.refAllDecls(@This());3538 testing.refAllDecls(@This());
lib/std/zig/render.zig+705-660
...@@ -14,49 +14,75 @@ pub const Error = Ast.RenderError;...@@ -14,49 +14,75 @@ pub const Error = Ast.RenderError;
1414
15const Ais = AutoIndentingStream(std.ArrayList(u8).Writer);15const 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 {
18 assert(tree.errors.len == 0); // Cannot render an invalid tree.40 assert(tree.errors.len == 0); // Cannot render an invalid tree.
19 var auto_indenting_stream = Ais{41 var auto_indenting_stream = Ais{
20 .indent_delta = indent_delta,42 .indent_delta = indent_delta,
21 .underlying_writer = buffer.writer(),43 .underlying_writer = buffer.writer(),
22 };44 };
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
25 // Render all the line comments at the beginning of the file.52 // Render all the line comments at the beginning of the file.
26 const comment_end_loc = tree.tokens.items(.start)[0];53 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
29 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {56 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {
30 try renderContainerDocComments(ais, tree, 0);57 try renderContainerDocComments(r, 0);
31 }58 }
3259
33 if (tree.mode == .zon) {60 if (tree.mode == .zon) {
34 try renderExpression(61 try renderExpression(
35 buffer.allocator,62 r,
36 ais,
37 tree,
38 tree.nodes.items(.data)[0].lhs,63 tree.nodes.items(.data)[0].lhs,
39 .newline,64 .newline,
40 );65 );
41 } else {66 } else {
42 try renderMembers(buffer.allocator, ais, tree, tree.rootDecls());67 try renderMembers(r, tree.rootDecls());
43 }68 }
4469
45 if (ais.disabled_offset) |disabled_offset| {70 if (auto_indenting_stream.disabled_offset) |disabled_offset| {
46 try writeFixingWhitespace(ais.underlying_writer, tree.source[disabled_offset..]);71 try writeFixingWhitespace(auto_indenting_stream.underlying_writer, tree.source[disabled_offset..]);
47 }72 }
48}73}
4974
50/// Render all members in the given slice, keeping empty lines where appropriate75/// 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;
52 if (members.len == 0) return;78 if (members.len == 0) return;
53 const container: Container = for (members) |member| {79 const container: Container = for (members) |member| {
54 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;80 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
55 } else .tuple;81 } else .tuple;
56 try renderMember(gpa, ais, tree, container, members[0], .newline);82 try renderMember(r, container, members[0], .newline);
57 for (members[1..]) |member| {83 for (members[1..]) |member| {
58 try renderExtraNewline(ais, tree, member);84 try renderExtraNewline(r, member);
59 try renderMember(gpa, ais, tree, container, member, .newline);85 try renderMember(r, container, member, .newline);
60 }86 }
61}87}
6288
...@@ -67,17 +93,17 @@ const Container = enum {...@@ -67,17 +93,17 @@ const Container = enum {
67};93};
6894
69fn renderMember(95fn renderMember(
70 gpa: Allocator,96 r: Render,
71 ais: *Ais,
72 tree: Ast,
73 container: Container,97 container: Container,
74 decl: Ast.Node.Index,98 decl: Ast.Node.Index,
75 space: Space,99 space: Space,
76) Error!void {100) Error!void {
101 const tree = r.tree;
102 const ais = r.ais;
77 const token_tags = tree.tokens.items(.tag);103 const token_tags = tree.tokens.items(.tag);
78 const main_tokens = tree.nodes.items(.main_token);104 const main_tokens = tree.nodes.items(.main_token);
79 const datas = tree.nodes.items(.data);105 const datas = tree.nodes.items(.data);
80 try renderDocComments(ais, tree, tree.firstToken(decl));106 try renderDocComments(r, tree.firstToken(decl));
81 switch (tree.nodes.items(.tag)[decl]) {107 switch (tree.nodes.items(.tag)[decl]) {
82 .fn_decl => {108 .fn_decl => {
83 // Some examples:109 // Some examples:
...@@ -105,7 +131,7 @@ fn renderMember(...@@ -105,7 +131,7 @@ fn renderMember(
105 }131 }
106 }132 }
107 while (i < fn_token) : (i += 1) {133 while (i < fn_token) : (i += 1) {
108 try renderToken(ais, tree, i, .space);134 try renderToken(r, i, .space);
109 }135 }
110 switch (tree.nodes.items(.tag)[fn_proto]) {136 switch (tree.nodes.items(.tag)[fn_proto]) {
111 .fn_proto_one, .fn_proto => {137 .fn_proto_one, .fn_proto => {
...@@ -123,8 +149,8 @@ fn renderMember(...@@ -123,8 +149,8 @@ fn renderMember(
123 else => unreachable,149 else => unreachable,
124 }150 }
125 assert(datas[decl].rhs != 0);151 assert(datas[decl].rhs != 0);
126 try renderExpression(gpa, ais, tree, fn_proto, .space);152 try renderExpression(r, fn_proto, .space);
127 return renderExpression(gpa, ais, tree, datas[decl].rhs, space);153 return renderExpression(r, datas[decl].rhs, space);
128 },154 },
129 .fn_proto_simple,155 .fn_proto_simple,
130 .fn_proto_multi,156 .fn_proto_multi,
...@@ -153,47 +179,47 @@ fn renderMember(...@@ -153,47 +179,47 @@ fn renderMember(
153 }179 }
154 }180 }
155 while (i < fn_token) : (i += 1) {181 while (i < fn_token) : (i += 1) {
156 try renderToken(ais, tree, i, .space);182 try renderToken(r, i, .space);
157 }183 }
158 try renderExpression(gpa, ais, tree, decl, .none);184 try renderExpression(r, decl, .none);
159 return renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon185 return renderToken(r, tree.lastToken(decl) + 1, space); // semicolon
160 },186 },
161187
162 .@"usingnamespace" => {188 .@"usingnamespace" => {
163 const main_token = main_tokens[decl];189 const main_token = main_tokens[decl];
164 const expr = datas[decl].lhs;190 const expr = datas[decl].lhs;
165 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {191 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {
166 try renderToken(ais, tree, main_token - 1, .space); // pub192 try renderToken(r, main_token - 1, .space); // pub
167 }193 }
168 try renderToken(ais, tree, main_token, .space); // usingnamespace194 try renderToken(r, main_token, .space); // usingnamespace
169 try renderExpression(gpa, ais, tree, expr, .none);195 try renderExpression(r, expr, .none);
170 return renderToken(ais, tree, tree.lastToken(expr) + 1, space); // ;196 return renderToken(r, tree.lastToken(expr) + 1, space); // ;
171 },197 },
172198
173 .global_var_decl,199 .global_var_decl,
174 .local_var_decl,200 .local_var_decl,
175 .simple_var_decl,201 .simple_var_decl,
176 .aligned_var_decl,202 .aligned_var_decl,
177 => return renderVarDecl(gpa, ais, tree, tree.fullVarDecl(decl).?, false, .semicolon),203 => return renderVarDecl(r, tree.fullVarDecl(decl).?, false, .semicolon),
178204
179 .test_decl => {205 .test_decl => {
180 const test_token = main_tokens[decl];206 const test_token = main_tokens[decl];
181 try renderToken(ais, tree, test_token, .space);207 try renderToken(r, test_token, .space);
182 const test_name_tag = token_tags[test_token + 1];208 const test_name_tag = token_tags[test_token + 1];
183 switch (test_name_tag) {209 switch (test_name_tag) {
184 .string_literal => try renderToken(ais, tree, test_token + 1, .space),210 .string_literal => try renderToken(r, test_token + 1, .space),
185 .identifier => try renderIdentifier(ais, tree, test_token + 1, .space, .preserve_when_shadowing),211 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),
186 else => {},212 else => {},
187 }213 }
188 try renderExpression(gpa, ais, tree, datas[decl].rhs, space);214 try renderExpression(r, datas[decl].rhs, space);
189 },215 },
190216
191 .container_field_init,217 .container_field_init,
192 .container_field_align,218 .container_field_align,
193 .container_field,219 .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
198 .root => unreachable,224 .root => unreachable,
199 else => unreachable,225 else => unreachable,
...@@ -201,16 +227,18 @@ fn renderMember(...@@ -201,16 +227,18 @@ fn renderMember(
201}227}
202228
203/// Render all expressions in the slice, keeping empty lines where appropriate229/// 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 {
205 if (expressions.len == 0) return;231 if (expressions.len == 0) return;
206 try renderExpression(gpa, ais, tree, expressions[0], space);232 try renderExpression(r, expressions[0], space);
207 for (expressions[1..]) |expression| {233 for (expressions[1..]) |expression| {
208 try renderExtraNewline(ais, tree, expression);234 try renderExtraNewline(r, expression);
209 try renderExpression(gpa, ais, tree, expression, space);235 try renderExpression(r, expression, space);
210 }236 }
211}237}
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;
214 const token_tags = tree.tokens.items(.tag);242 const token_tags = tree.tokens.items(.tag);
215 const main_tokens = tree.nodes.items(.main_token);243 const main_tokens = tree.nodes.items(.main_token);
216 const node_tags = tree.nodes.items(.tag);244 const node_tags = tree.nodes.items(.tag);
...@@ -218,7 +246,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -218,7 +246,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
218 switch (node_tags[node]) {246 switch (node_tags[node]) {
219 .identifier => {247 .identifier => {
220 const token_index = main_tokens[node];248 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);
222 },250 },
223251
224 .number_literal,252 .number_literal,
...@@ -226,29 +254,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -226,29 +254,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
226 .unreachable_literal,254 .unreachable_literal,
227 .anyframe_literal,255 .anyframe_literal,
228 .string_literal,256 .string_literal,
229 => return renderToken(ais, tree, main_tokens[node], space),257 => return renderToken(r, main_tokens[node], space),
230258
231 .multiline_string_literal => {259 .multiline_string_literal => {
232 var locked_indents = ais.lockOneShotIndent();260 var locked_indents = ais.lockOneShotIndent();
233 try ais.maybeInsertNewline();261 try ais.maybeInsertNewline();
234262
235 var i = datas[node].lhs;263 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
238 while (locked_indents > 0) : (locked_indents -= 1) ais.popIndent();266 while (locked_indents > 0) : (locked_indents -= 1) ais.popIndent();
239267
240 switch (space) {268 switch (space) {
241 .none, .space, .newline, .skip => {},269 .none, .space, .newline, .skip => {},
242 .semicolon => if (token_tags[i] == .semicolon) try renderToken(ais, tree, i, .newline),270 .semicolon => if (token_tags[i] == .semicolon) try renderToken(r, i, .newline),
243 .comma => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .newline),271 .comma => if (token_tags[i] == .comma) try renderToken(r, i, .newline),
244 .comma_space => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .space),272 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),
245 }273 }
246 },274 },
247275
248 .error_value => {276 .error_value => {
249 try renderToken(ais, tree, main_tokens[node], .none);277 try renderToken(r, main_tokens[node], .none);
250 try renderToken(ais, tree, main_tokens[node] + 1, .none);278 try renderToken(r, main_tokens[node] + 1, .none);
251 return renderIdentifier(ais, tree, main_tokens[node] + 2, space, .eagerly_unquote);279 return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote);
252 },280 },
253281
254 .block_two,282 .block_two,
...@@ -256,18 +284,18 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -256,18 +284,18 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
256 => {284 => {
257 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };285 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
258 if (datas[node].lhs == 0) {286 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);
260 } else if (datas[node].rhs == 0) {288 } 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);
262 } else {290 } else {
263 return renderBlock(gpa, ais, tree, node, statements[0..2], space);291 return renderBlock(r, node, statements[0..2], space);
264 }292 }
265 },293 },
266 .block,294 .block,
267 .block_semicolon,295 .block_semicolon,
268 => {296 => {
269 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];297 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);
271 },299 },
272300
273 .@"errdefer" => {301 .@"errdefer" => {
...@@ -275,33 +303,33 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -275,33 +303,33 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
275 const payload_token = datas[node].lhs;303 const payload_token = datas[node].lhs;
276 const expr = datas[node].rhs;304 const expr = datas[node].rhs;
277305
278 try renderToken(ais, tree, defer_token, .space);306 try renderToken(r, defer_token, .space);
279 if (payload_token != 0) {307 if (payload_token != 0) {
280 try renderToken(ais, tree, payload_token - 1, .none); // |308 try renderToken(r, payload_token - 1, .none); // |
281 try renderIdentifier(ais, tree, payload_token, .none, .preserve_when_shadowing); // identifier309 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
282 try renderToken(ais, tree, payload_token + 1, .space); // |310 try renderToken(r, payload_token + 1, .space); // |
283 }311 }
284 return renderExpression(gpa, ais, tree, expr, space);312 return renderExpression(r, expr, space);
285 },313 },
286314
287 .@"defer" => {315 .@"defer" => {
288 const defer_token = main_tokens[node];316 const defer_token = main_tokens[node];
289 const expr = datas[node].rhs;317 const expr = datas[node].rhs;
290 try renderToken(ais, tree, defer_token, .space);318 try renderToken(r, defer_token, .space);
291 return renderExpression(gpa, ais, tree, expr, space);319 return renderExpression(r, expr, space);
292 },320 },
293 .@"comptime", .@"nosuspend" => {321 .@"comptime", .@"nosuspend" => {
294 const comptime_token = main_tokens[node];322 const comptime_token = main_tokens[node];
295 const block = datas[node].lhs;323 const block = datas[node].lhs;
296 try renderToken(ais, tree, comptime_token, .space);324 try renderToken(r, comptime_token, .space);
297 return renderExpression(gpa, ais, tree, block, space);325 return renderExpression(r, block, space);
298 },326 },
299327
300 .@"suspend" => {328 .@"suspend" => {
301 const suspend_token = main_tokens[node];329 const suspend_token = main_tokens[node];
302 const body = datas[node].lhs;330 const body = datas[node].lhs;
303 try renderToken(ais, tree, suspend_token, .space);331 try renderToken(r, suspend_token, .space);
304 return renderExpression(gpa, ais, tree, body, space);332 return renderExpression(r, body, space);
305 },333 },
306334
307 .@"catch" => {335 .@"catch" => {
...@@ -311,27 +339,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -311,27 +339,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
311 const same_line = tree.tokensOnSameLine(main_token, fallback_first);339 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
312 const after_op_space = if (same_line) Space.space else Space.newline;340 const after_op_space = if (same_line) Space.space else Space.newline;
313341
314 try renderExpression(gpa, ais, tree, datas[node].lhs, .space); // target342 try renderExpression(r, datas[node].lhs, .space); // target
315343
316 if (token_tags[fallback_first - 1] == .pipe) {344 if (token_tags[fallback_first - 1] == .pipe) {
317 try renderToken(ais, tree, main_token, .space); // catch keyword345 try renderToken(r, main_token, .space); // catch keyword
318 try renderToken(ais, tree, main_token + 1, .none); // pipe346 try renderToken(r, main_token + 1, .none); // pipe
319 try renderIdentifier(ais, tree, main_token + 2, .none, .preserve_when_shadowing); // payload identifier347 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
320 try renderToken(ais, tree, main_token + 3, after_op_space); // pipe348 try renderToken(r, main_token + 3, after_op_space); // pipe
321 } else {349 } else {
322 assert(token_tags[fallback_first - 1] == .keyword_catch);350 assert(token_tags[fallback_first - 1] == .keyword_catch);
323 try renderToken(ais, tree, main_token, after_op_space); // catch keyword351 try renderToken(r, main_token, after_op_space); // catch keyword
324 }352 }
325353
326 ais.pushIndentOneShot();354 ais.pushIndentOneShot();
327 try renderExpression(gpa, ais, tree, datas[node].rhs, space); // fallback355 try renderExpression(r, datas[node].rhs, space); // fallback
328 },356 },
329357
330 .field_access => {358 .field_access => {
331 const main_token = main_tokens[node];359 const main_token = main_tokens[node];
332 const field_access = datas[node];360 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
336 // Allow a line break between the lhs and the dot if the lhs and rhs364 // Allow a line break between the lhs and the dot if the lhs and rhs
337 // are on different lines.365 // are on different lines.
...@@ -342,7 +370,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -342,7 +370,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
342 ais.pushIndentOneShot();370 ais.pushIndentOneShot();
343 }371 }
344372
345 try renderToken(ais, tree, main_token, .none); // .373 try renderToken(r, main_token, .none); // .
346374
347 // This check ensures that zag() is indented in the following example:375 // This check ensures that zag() is indented in the following example:
348 // const x = foo376 // const x = foo
...@@ -353,25 +381,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -353,25 +381,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
353 ais.pushIndentOneShot();381 ais.pushIndentOneShot();
354 }382 }
355383
356 return renderIdentifier(ais, tree, field_access.rhs, space, .eagerly_unquote); // field384 return renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field
357 },385 },
358386
359 .error_union,387 .error_union,
360 .switch_range,388 .switch_range,
361 => {389 => {
362 const infix = datas[node];390 const infix = datas[node];
363 try renderExpression(gpa, ais, tree, infix.lhs, .none);391 try renderExpression(r, infix.lhs, .none);
364 try renderToken(ais, tree, main_tokens[node], .none);392 try renderToken(r, main_tokens[node], .none);
365 return renderExpression(gpa, ais, tree, infix.rhs, space);393 return renderExpression(r, infix.rhs, space);
366 },394 },
367 .for_range => {395 .for_range => {
368 const infix = datas[node];396 const infix = datas[node];
369 try renderExpression(gpa, ais, tree, infix.lhs, .none);397 try renderExpression(r, infix.lhs, .none);
370 if (infix.rhs != 0) {398 if (infix.rhs != 0) {
371 try renderToken(ais, tree, main_tokens[node], .none);399 try renderToken(r, main_tokens[node], .none);
372 return renderExpression(gpa, ais, tree, infix.rhs, space);400 return renderExpression(r, infix.rhs, space);
373 } else {401 } else {
374 return renderToken(ais, tree, main_tokens[node], space);402 return renderToken(r, main_tokens[node], space);
375 }403 }
376 },404 },
377405
...@@ -424,17 +452,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -424,17 +452,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
424 .@"orelse",452 .@"orelse",
425 => {453 => {
426 const infix = datas[node];454 const infix = datas[node];
427 try renderExpression(gpa, ais, tree, infix.lhs, .space);455 try renderExpression(r, infix.lhs, .space);
428 const op_token = main_tokens[node];456 const op_token = main_tokens[node];
429 if (tree.tokensOnSameLine(op_token, op_token + 1)) {457 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
430 try renderToken(ais, tree, op_token, .space);458 try renderToken(r, op_token, .space);
431 } else {459 } else {
432 ais.pushIndent();460 ais.pushIndent();
433 try renderToken(ais, tree, op_token, .newline);461 try renderToken(r, op_token, .newline);
434 ais.popIndent();462 ais.popIndent();
435 }463 }
436 ais.pushIndentOneShot();464 ais.pushIndentOneShot();
437 return renderExpression(gpa, ais, tree, infix.rhs, space);465 return renderExpression(r, infix.rhs, space);
438 },466 },
439467
440 .assign_destructure => {468 .assign_destructure => {
...@@ -445,7 +473,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -445,7 +473,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
445473
446 const maybe_comptime_token = tree.firstToken(node) - 1;474 const maybe_comptime_token = tree.firstToken(node) - 1;
447 if (token_tags[maybe_comptime_token] == .keyword_comptime) {475 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);
449 }477 }
450478
451 for (lhs_exprs, 0..) |lhs_node, i| {479 for (lhs_exprs, 0..) |lhs_node, i| {
...@@ -456,21 +484,21 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -456,21 +484,21 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
456 .simple_var_decl,484 .simple_var_decl,
457 .aligned_var_decl,485 .aligned_var_decl,
458 => {486 => {
459 try renderVarDecl(gpa, ais, tree, tree.fullVarDecl(lhs_node).?, true, lhs_space);487 try renderVarDecl(r, tree.fullVarDecl(lhs_node).?, true, lhs_space);
460 },488 },
461 else => try renderExpression(gpa, ais, tree, lhs_node, lhs_space),489 else => try renderExpression(r, lhs_node, lhs_space),
462 }490 }
463 }491 }
464 const equal_token = main_tokens[node];492 const equal_token = main_tokens[node];
465 if (tree.tokensOnSameLine(equal_token, equal_token + 1)) {493 if (tree.tokensOnSameLine(equal_token, equal_token + 1)) {
466 try renderToken(ais, tree, equal_token, .space);494 try renderToken(r, equal_token, .space);
467 } else {495 } else {
468 ais.pushIndent();496 ais.pushIndent();
469 try renderToken(ais, tree, equal_token, .newline);497 try renderToken(r, equal_token, .newline);
470 ais.popIndent();498 ais.popIndent();
471 }499 }
472 ais.pushIndentOneShot();500 ais.pushIndentOneShot();
473 return renderExpression(gpa, ais, tree, rhs, space);501 return renderExpression(r, rhs, space);
474 },502 },
475503
476 .bit_not,504 .bit_not,
...@@ -480,27 +508,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -480,27 +508,27 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
480 .optional_type,508 .optional_type,
481 .address_of,509 .address_of,
482 => {510 => {
483 try renderToken(ais, tree, main_tokens[node], .none);511 try renderToken(r, main_tokens[node], .none);
484 return renderExpression(gpa, ais, tree, datas[node].lhs, space);512 return renderExpression(r, datas[node].lhs, space);
485 },513 },
486514
487 .@"try",515 .@"try",
488 .@"resume",516 .@"resume",
489 .@"await",517 .@"await",
490 => {518 => {
491 try renderToken(ais, tree, main_tokens[node], .space);519 try renderToken(r, main_tokens[node], .space);
492 return renderExpression(gpa, ais, tree, datas[node].lhs, space);520 return renderExpression(r, datas[node].lhs, space);
493 },521 },
494522
495 .array_type,523 .array_type,
496 .array_type_sentinel,524 .array_type_sentinel,
497 => return renderArrayType(gpa, ais, tree, tree.fullArrayType(node).?, space),525 => return renderArrayType(r, tree.fullArrayType(node).?, space),
498526
499 .ptr_type_aligned,527 .ptr_type_aligned,
500 .ptr_type_sentinel,528 .ptr_type_sentinel,
501 .ptr_type,529 .ptr_type,
502 .ptr_type_bit_range,530 .ptr_type_bit_range,
503 => return renderPtrType(gpa, ais, tree, tree.fullPtrType(node).?, space),531 => return renderPtrType(r, tree.fullPtrType(node).?, space),
504532
505 .array_init_one,533 .array_init_one,
506 .array_init_one_comma,534 .array_init_one_comma,
...@@ -512,7 +540,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -512,7 +540,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
512 .array_init_comma,540 .array_init_comma,
513 => {541 => {
514 var elements: [2]Ast.Node.Index = undefined;542 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);
516 },544 },
517545
518 .struct_init_one,546 .struct_init_one,
...@@ -525,7 +553,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -525,7 +553,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
525 .struct_init_comma,553 .struct_init_comma,
526 => {554 => {
527 var buf: [2]Ast.Node.Index = undefined;555 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);
529 },557 },
530558
531 .call_one,559 .call_one,
...@@ -538,7 +566,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -538,7 +566,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
538 .async_call_comma,566 .async_call_comma,
539 => {567 => {
540 var buf: [1]Ast.Node.Index = undefined;568 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);
542 },570 },
543571
544 .array_access => {572 .array_access => {
...@@ -547,25 +575,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -547,25 +575,25 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
547 const rbracket = tree.lastToken(suffix.rhs) + 1;575 const rbracket = tree.lastToken(suffix.rhs) + 1;
548 const one_line = tree.tokensOnSameLine(lbracket, rbracket);576 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
549 const inner_space = if (one_line) Space.none else Space.newline;577 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);
551 ais.pushIndentNextLine();579 ais.pushIndentNextLine();
552 try renderToken(ais, tree, lbracket, inner_space); // [580 try renderToken(r, lbracket, inner_space); // [
553 try renderExpression(gpa, ais, tree, suffix.rhs, inner_space);581 try renderExpression(r, suffix.rhs, inner_space);
554 ais.popIndent();582 ais.popIndent();
555 return renderToken(ais, tree, rbracket, space); // ]583 return renderToken(r, rbracket, space); // ]
556 },584 },
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
560 .deref => {588 .deref => {
561 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);589 try renderExpression(r, datas[node].lhs, .none);
562 return renderToken(ais, tree, main_tokens[node], space);590 return renderToken(r, main_tokens[node], space);
563 },591 },
564592
565 .unwrap_optional => {593 .unwrap_optional => {
566 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);594 try renderExpression(r, datas[node].lhs, .none);
567 try renderToken(ais, tree, main_tokens[node], .none);595 try renderToken(r, main_tokens[node], .none);
568 return renderToken(ais, tree, datas[node].rhs, space);596 return renderToken(r, datas[node].rhs, space);
569 },597 },
570598
571 .@"break" => {599 .@"break" => {
...@@ -573,19 +601,19 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -573,19 +601,19 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
573 const label_token = datas[node].lhs;601 const label_token = datas[node].lhs;
574 const target = datas[node].rhs;602 const target = datas[node].rhs;
575 if (label_token == 0 and target == 0) {603 if (label_token == 0 and target == 0) {
576 try renderToken(ais, tree, main_token, space); // break keyword604 try renderToken(r, main_token, space); // break keyword
577 } else if (label_token == 0 and target != 0) {605 } else if (label_token == 0 and target != 0) {
578 try renderToken(ais, tree, main_token, .space); // break keyword606 try renderToken(r, main_token, .space); // break keyword
579 try renderExpression(gpa, ais, tree, target, space);607 try renderExpression(r, target, space);
580 } else if (label_token != 0 and target == 0) {608 } else if (label_token != 0 and target == 0) {
581 try renderToken(ais, tree, main_token, .space); // break keyword609 try renderToken(r, main_token, .space); // break keyword
582 try renderToken(ais, tree, label_token - 1, .none); // colon610 try renderToken(r, label_token - 1, .none); // colon
583 try renderIdentifier(ais, tree, label_token, space, .eagerly_unquote); // identifier611 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
584 } else if (label_token != 0 and target != 0) {612 } else if (label_token != 0 and target != 0) {
585 try renderToken(ais, tree, main_token, .space); // break keyword613 try renderToken(r, main_token, .space); // break keyword
586 try renderToken(ais, tree, label_token - 1, .none); // colon614 try renderToken(r, label_token - 1, .none); // colon
587 try renderIdentifier(ais, tree, label_token, .space, .eagerly_unquote); // identifier615 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
588 try renderExpression(gpa, ais, tree, target, space);616 try renderExpression(r, target, space);
589 }617 }
590 },618 },
591619
...@@ -593,28 +621,28 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -593,28 +621,28 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
593 const main_token = main_tokens[node];621 const main_token = main_tokens[node];
594 const label = datas[node].lhs;622 const label = datas[node].lhs;
595 if (label != 0) {623 if (label != 0) {
596 try renderToken(ais, tree, main_token, .space); // continue624 try renderToken(r, main_token, .space); // continue
597 try renderToken(ais, tree, label - 1, .none); // :625 try renderToken(r, label - 1, .none); // :
598 return renderIdentifier(ais, tree, label, space, .eagerly_unquote); // label626 return renderIdentifier(r, label, space, .eagerly_unquote); // label
599 } else {627 } else {
600 return renderToken(ais, tree, main_token, space); // continue628 return renderToken(r, main_token, space); // continue
601 }629 }
602 },630 },
603631
604 .@"return" => {632 .@"return" => {
605 if (datas[node].lhs != 0) {633 if (datas[node].lhs != 0) {
606 try renderToken(ais, tree, main_tokens[node], .space);634 try renderToken(r, main_tokens[node], .space);
607 try renderExpression(gpa, ais, tree, datas[node].lhs, space);635 try renderExpression(r, datas[node].lhs, space);
608 } else {636 } else {
609 try renderToken(ais, tree, main_tokens[node], space);637 try renderToken(r, main_tokens[node], space);
610 }638 }
611 },639 },
612640
613 .grouped_expression => {641 .grouped_expression => {
614 try renderToken(ais, tree, main_tokens[node], .none); // lparen642 try renderToken(r, main_tokens[node], .none); // lparen
615 ais.pushIndentOneShot();643 ais.pushIndentOneShot();
616 try renderExpression(gpa, ais, tree, datas[node].lhs, .none);644 try renderExpression(r, datas[node].lhs, .none);
617 return renderToken(ais, tree, datas[node].rhs, space); // rparen645 return renderToken(r, datas[node].rhs, space); // rparen
618 },646 },
619647
620 .container_decl,648 .container_decl,
...@@ -631,7 +659,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -631,7 +659,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
631 .tagged_union_two_trailing,659 .tagged_union_two_trailing,
632 => {660 => {
633 var buf: [2]Ast.Node.Index = undefined;661 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);
635 },663 },
636664
637 .error_set_decl => {665 .error_set_decl => {
...@@ -639,62 +667,62 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -639,62 +667,62 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
639 const lbrace = error_token + 1;667 const lbrace = error_token + 1;
640 const rbrace = datas[node].rhs;668 const rbrace = datas[node].rhs;
641669
642 try renderToken(ais, tree, error_token, .none);670 try renderToken(r, error_token, .none);
643671
644 if (lbrace + 1 == rbrace) {672 if (lbrace + 1 == rbrace) {
645 // There is nothing between the braces so render condensed: `error{}`673 // There is nothing between the braces so render condensed: `error{}`
646 try renderToken(ais, tree, lbrace, .none);674 try renderToken(r, lbrace, .none);
647 return renderToken(ais, tree, rbrace, space);675 return renderToken(r, rbrace, space);
648 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {676 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {
649 // There is exactly one member and no trailing comma or677 // There is exactly one member and no trailing comma or
650 // comments, so render without surrounding spaces: `error{Foo}`678 // comments, so render without surrounding spaces: `error{Foo}`
651 try renderToken(ais, tree, lbrace, .none);679 try renderToken(r, lbrace, .none);
652 try renderIdentifier(ais, tree, lbrace + 1, .none, .eagerly_unquote); // identifier680 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
653 return renderToken(ais, tree, rbrace, space);681 return renderToken(r, rbrace, space);
654 } else if (token_tags[rbrace - 1] == .comma) {682 } else if (token_tags[rbrace - 1] == .comma) {
655 // There is a trailing comma so render each member on a new line.683 // There is a trailing comma so render each member on a new line.
656 ais.pushIndentNextLine();684 ais.pushIndentNextLine();
657 try renderToken(ais, tree, lbrace, .newline);685 try renderToken(r, lbrace, .newline);
658 var i = lbrace + 1;686 var i = lbrace + 1;
659 while (i < rbrace) : (i += 1) {687 while (i < rbrace) : (i += 1) {
660 if (i > lbrace + 1) try renderExtraNewlineToken(ais, tree, i);688 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
661 switch (token_tags[i]) {689 switch (token_tags[i]) {
662 .doc_comment => try renderToken(ais, tree, i, .newline),690 .doc_comment => try renderToken(r, i, .newline),
663 .identifier => try renderIdentifier(ais, tree, i, .comma, .eagerly_unquote),691 .identifier => try renderIdentifier(r, i, .comma, .eagerly_unquote),
664 .comma => {},692 .comma => {},
665 else => unreachable,693 else => unreachable,
666 }694 }
667 }695 }
668 ais.popIndent();696 ais.popIndent();
669 return renderToken(ais, tree, rbrace, space);697 return renderToken(r, rbrace, space);
670 } else {698 } else {
671 // There is no trailing comma so render everything on one line.699 // There is no trailing comma so render everything on one line.
672 try renderToken(ais, tree, lbrace, .space);700 try renderToken(r, lbrace, .space);
673 var i = lbrace + 1;701 var i = lbrace + 1;
674 while (i < rbrace) : (i += 1) {702 while (i < rbrace) : (i += 1) {
675 switch (token_tags[i]) {703 switch (token_tags[i]) {
676 .doc_comment => unreachable, // TODO704 .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),
678 .comma => {},706 .comma => {},
679 else => unreachable,707 else => unreachable,
680 }708 }
681 }709 }
682 return renderToken(ais, tree, rbrace, space);710 return renderToken(r, rbrace, space);
683 }711 }
684 },712 },
685713
686 .builtin_call_two, .builtin_call_two_comma => {714 .builtin_call_two, .builtin_call_two_comma => {
687 if (datas[node].lhs == 0) {715 if (datas[node].lhs == 0) {
688 return renderBuiltinCall(gpa, ais, tree, main_tokens[node], &.{}, space);716 return renderBuiltinCall(r, main_tokens[node], &.{}, space);
689 } else if (datas[node].rhs == 0) {717 } 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);
691 } else {719 } 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);
693 }721 }
694 },722 },
695 .builtin_call, .builtin_call_comma => {723 .builtin_call, .builtin_call_comma => {
696 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];724 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);
698 },726 },
699727
700 .fn_proto_simple,728 .fn_proto_simple,
...@@ -703,17 +731,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -703,17 +731,17 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
703 .fn_proto,731 .fn_proto,
704 => {732 => {
705 var buf: [1]Ast.Node.Index = undefined;733 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);
707 },735 },
708736
709 .anyframe_type => {737 .anyframe_type => {
710 const main_token = main_tokens[node];738 const main_token = main_tokens[node];
711 if (datas[node].rhs != 0) {739 if (datas[node].rhs != 0) {
712 try renderToken(ais, tree, main_token, .none); // anyframe740 try renderToken(r, main_token, .none); // anyframe
713 try renderToken(ais, tree, main_token + 1, .none); // ->741 try renderToken(r, main_token + 1, .none); // ->
714 return renderExpression(gpa, ais, tree, datas[node].rhs, space);742 return renderExpression(r, datas[node].rhs, space);
715 } else {743 } else {
716 return renderToken(ais, tree, main_token, space); // anyframe744 return renderToken(r, main_token, space); // anyframe
717 }745 }
718 },746 },
719747
...@@ -726,48 +754,48 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -726,48 +754,48 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
726 const cases = tree.extra_data[extra.start..extra.end];754 const cases = tree.extra_data[extra.start..extra.end];
727 const rparen = tree.lastToken(condition) + 1;755 const rparen = tree.lastToken(condition) + 1;
728756
729 try renderToken(ais, tree, switch_token, .space); // switch keyword757 try renderToken(r, switch_token, .space); // switch keyword
730 try renderToken(ais, tree, switch_token + 1, .none); // lparen758 try renderToken(r, switch_token + 1, .none); // lparen
731 try renderExpression(gpa, ais, tree, condition, .none); // condition expression759 try renderExpression(r, condition, .none); // condition expression
732 try renderToken(ais, tree, rparen, .space); // rparen760 try renderToken(r, rparen, .space); // rparen
733761
734 ais.pushIndentNextLine();762 ais.pushIndentNextLine();
735 if (cases.len == 0) {763 if (cases.len == 0) {
736 try renderToken(ais, tree, rparen + 1, .none); // lbrace764 try renderToken(r, rparen + 1, .none); // lbrace
737 } else {765 } else {
738 try renderToken(ais, tree, rparen + 1, .newline); // lbrace766 try renderToken(r, rparen + 1, .newline); // lbrace
739 try renderExpressions(gpa, ais, tree, cases, .comma);767 try renderExpressions(r, cases, .comma);
740 }768 }
741 ais.popIndent();769 ais.popIndent();
742 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace770 return renderToken(r, tree.lastToken(node), space); // rbrace
743 },771 },
744772
745 .switch_case_one,773 .switch_case_one,
746 .switch_case_inline_one,774 .switch_case_inline_one,
747 .switch_case,775 .switch_case,
748 .switch_case_inline,776 .switch_case_inline,
749 => return renderSwitchCase(gpa, ais, tree, tree.fullSwitchCase(node).?, space),777 => return renderSwitchCase(r, tree.fullSwitchCase(node).?, space),
750778
751 .while_simple,779 .while_simple,
752 .while_cont,780 .while_cont,
753 .@"while",781 .@"while",
754 => return renderWhile(gpa, ais, tree, tree.fullWhile(node).?, space),782 => return renderWhile(r, tree.fullWhile(node).?, space),
755783
756 .for_simple,784 .for_simple,
757 .@"for",785 .@"for",
758 => return renderFor(gpa, ais, tree, tree.fullFor(node).?, space),786 => return renderFor(r, tree.fullFor(node).?, space),
759787
760 .if_simple,788 .if_simple,
761 .@"if",789 .@"if",
762 => return renderIf(gpa, ais, tree, tree.fullIf(node).?, space),790 => return renderIf(r, tree.fullIf(node).?, space),
763791
764 .asm_simple,792 .asm_simple,
765 .@"asm",793 .@"asm",
766 => return renderAsm(gpa, ais, tree, tree.fullAsm(node).?, space),794 => return renderAsm(r, tree.fullAsm(node).?, space),
767795
768 .enum_literal => {796 .enum_literal => {
769 try renderToken(ais, tree, main_tokens[node] - 1, .none); // .797 try renderToken(r, main_tokens[node] - 1, .none); // .
770 return renderIdentifier(ais, tree, main_tokens[node], space, .eagerly_unquote); // name798 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name
771 },799 },
772800
773 .fn_decl => unreachable,801 .fn_decl => unreachable,
...@@ -787,34 +815,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,...@@ -787,34 +815,29 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
787}815}
788816
789fn renderArrayType(817fn renderArrayType(
790 gpa: Allocator,818 r: Render,
791 ais: *Ais,
792 tree: Ast,
793 array_type: Ast.full.ArrayType,819 array_type: Ast.full.ArrayType,
794 space: Space,820 space: Space,
795) Error!void {821) Error!void {
822 const tree = r.tree;
823 const ais = r.ais;
796 const rbracket = tree.firstToken(array_type.ast.elem_type) - 1;824 const rbracket = tree.firstToken(array_type.ast.elem_type) - 1;
797 const one_line = tree.tokensOnSameLine(array_type.ast.lbracket, rbracket);825 const one_line = tree.tokensOnSameLine(array_type.ast.lbracket, rbracket);
798 const inner_space = if (one_line) Space.none else Space.newline;826 const inner_space = if (one_line) Space.none else Space.newline;
799 ais.pushIndentNextLine();827 ais.pushIndentNextLine();
800 try renderToken(ais, tree, array_type.ast.lbracket, inner_space); // lbracket828 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
801 try renderExpression(gpa, ais, tree, array_type.ast.elem_count, inner_space);829 try renderExpression(r, array_type.ast.elem_count, inner_space);
802 if (array_type.ast.sentinel != 0) {830 if (array_type.ast.sentinel != 0) {
803 try renderToken(ais, tree, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon831 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
804 try renderExpression(gpa, ais, tree, array_type.ast.sentinel, inner_space);832 try renderExpression(r, array_type.ast.sentinel, inner_space);
805 }833 }
806 ais.popIndent();834 ais.popIndent();
807 try renderToken(ais, tree, rbracket, .none); // rbracket835 try renderToken(r, rbracket, .none); // rbracket
808 return renderExpression(gpa, ais, tree, array_type.ast.elem_type, space);836 return renderExpression(r, array_type.ast.elem_type, space);
809}837}
810838
811fn renderPtrType(839fn renderPtrType(r: Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
812 gpa: Allocator,840 const tree = r.tree;
813 ais: *Ais,
814 tree: Ast,
815 ptr_type: Ast.full.PtrType,
816 space: Space,
817) Error!void {
818 switch (ptr_type.size) {841 switch (ptr_type.size) {
819 .One => {842 .One => {
820 // Since ** tokens exist and the same token is shared by two843 // Since ** tokens exist and the same token is shared by two
...@@ -825,90 +848,89 @@ fn renderPtrType(...@@ -825,90 +848,89 @@ fn renderPtrType(
825 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and848 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and
826 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])849 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
827 {850 {
828 return renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);851 return renderExpression(r, ptr_type.ast.child_type, space);
829 }852 }
830 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk853 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
831 },854 },
832 .Many => {855 .Many => {
833 if (ptr_type.ast.sentinel == 0) {856 if (ptr_type.ast.sentinel == 0) {
834 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket857 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
835 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk858 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
836 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket859 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
837 } else {860 } else {
838 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket861 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
839 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk862 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
840 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon863 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
841 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);864 try renderExpression(r, ptr_type.ast.sentinel, .none);
842 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket865 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
843 }866 }
844 },867 },
845 .C => {868 .C => {
846 try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket869 try renderToken(r, ptr_type.ast.main_token - 1, .none); // lbracket
847 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk870 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
848 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // c871 try renderToken(r, ptr_type.ast.main_token + 1, .none); // c
849 try renderToken(ais, tree, ptr_type.ast.main_token + 2, .none); // rbracket872 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket
850 },873 },
851 .Slice => {874 .Slice => {
852 if (ptr_type.ast.sentinel == 0) {875 if (ptr_type.ast.sentinel == 0) {
853 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket876 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
854 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket877 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
855 } else {878 } else {
856 try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket879 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
857 try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon880 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
858 try renderExpression(gpa, ais, tree, ptr_type.ast.sentinel, .none);881 try renderExpression(r, ptr_type.ast.sentinel, .none);
859 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket882 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
860 }883 }
861 },884 },
862 }885 }
863886
864 if (ptr_type.allowzero_token) |allowzero_token| {887 if (ptr_type.allowzero_token) |allowzero_token| {
865 try renderToken(ais, tree, allowzero_token, .space);888 try renderToken(r, allowzero_token, .space);
866 }889 }
867890
868 if (ptr_type.ast.align_node != 0) {891 if (ptr_type.ast.align_node != 0) {
869 const align_first = tree.firstToken(ptr_type.ast.align_node);892 const align_first = tree.firstToken(ptr_type.ast.align_node);
870 try renderToken(ais, tree, align_first - 2, .none); // align893 try renderToken(r, align_first - 2, .none); // align
871 try renderToken(ais, tree, align_first - 1, .none); // lparen894 try renderToken(r, align_first - 1, .none); // lparen
872 try renderExpression(gpa, ais, tree, ptr_type.ast.align_node, .none);895 try renderExpression(r, ptr_type.ast.align_node, .none);
873 if (ptr_type.ast.bit_range_start != 0) {896 if (ptr_type.ast.bit_range_start != 0) {
874 assert(ptr_type.ast.bit_range_end != 0);897 assert(ptr_type.ast.bit_range_end != 0);
875 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon898 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
876 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_start, .none);899 try renderExpression(r, ptr_type.ast.bit_range_start, .none);
877 try renderToken(ais, tree, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon900 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
878 try renderExpression(gpa, ais, tree, ptr_type.ast.bit_range_end, .none);901 try renderExpression(r, ptr_type.ast.bit_range_end, .none);
879 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen902 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
880 } else {903 } else {
881 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen904 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
882 }905 }
883 }906 }
884907
885 if (ptr_type.ast.addrspace_node != 0) {908 if (ptr_type.ast.addrspace_node != 0) {
886 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);909 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);
887 try renderToken(ais, tree, addrspace_first - 2, .none); // addrspace910 try renderToken(r, addrspace_first - 2, .none); // addrspace
888 try renderToken(ais, tree, addrspace_first - 1, .none); // lparen911 try renderToken(r, addrspace_first - 1, .none); // lparen
889 try renderExpression(gpa, ais, tree, ptr_type.ast.addrspace_node, .none);912 try renderExpression(r, ptr_type.ast.addrspace_node, .none);
890 try renderToken(ais, tree, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen913 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen
891 }914 }
892915
893 if (ptr_type.const_token) |const_token| {916 if (ptr_type.const_token) |const_token| {
894 try renderToken(ais, tree, const_token, .space);917 try renderToken(r, const_token, .space);
895 }918 }
896919
897 if (ptr_type.volatile_token) |volatile_token| {920 if (ptr_type.volatile_token) |volatile_token| {
898 try renderToken(ais, tree, volatile_token, .space);921 try renderToken(r, volatile_token, .space);
899 }922 }
900923
901 try renderExpression(gpa, ais, tree, ptr_type.ast.child_type, space);924 try renderExpression(r, ptr_type.ast.child_type, space);
902}925}
903926
904fn renderSlice(927fn renderSlice(
905 gpa: Allocator,928 r: Render,
906 ais: *Ais,
907 tree: Ast,
908 slice_node: Ast.Node.Index,929 slice_node: Ast.Node.Index,
909 slice: Ast.full.Slice,930 slice: Ast.full.Slice,
910 space: Space,931 space: Space,
911) Error!void {932) Error!void {
933 const tree = r.tree;
912 const node_tags = tree.nodes.items(.tag);934 const node_tags = tree.nodes.items(.tag);
913 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or935 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
914 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;936 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
...@@ -917,33 +939,32 @@ fn renderSlice(...@@ -917,33 +939,32 @@ fn renderSlice(
917 after_start_space939 after_start_space
918 else if (slice.ast.sentinel != 0) Space.space else Space.none;940 else if (slice.ast.sentinel != 0) Space.space else Space.none;
919941
920 try renderExpression(gpa, ais, tree, slice.ast.sliced, .none);942 try renderExpression(r, slice.ast.sliced, .none);
921 try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket943 try renderToken(r, slice.ast.lbracket, .none); // lbracket
922944
923 const start_last = tree.lastToken(slice.ast.start);945 const start_last = tree.lastToken(slice.ast.start);
924 try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space);946 try renderExpression(r, slice.ast.start, after_start_space);
925 try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")947 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
926948
927 if (slice.ast.end != 0) {949 if (slice.ast.end != 0) {
928 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;950 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);
930 }952 }
931953
932 if (slice.ast.sentinel != 0) {954 if (slice.ast.sentinel != 0) {
933 try renderToken(ais, tree, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon955 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
934 try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none);956 try renderExpression(r, slice.ast.sentinel, .none);
935 }957 }
936958
937 try renderToken(ais, tree, tree.lastToken(slice_node), space); // rbracket959 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
938}960}
939961
940fn renderAsmOutput(962fn renderAsmOutput(
941 gpa: Allocator,963 r: Render,
942 ais: *Ais,
943 tree: Ast,
944 asm_output: Ast.Node.Index,964 asm_output: Ast.Node.Index,
945 space: Space,965 space: Space,
946) Error!void {966) Error!void {
967 const tree = r.tree;
947 const token_tags = tree.tokens.items(.tag);968 const token_tags = tree.tokens.items(.tag);
948 const node_tags = tree.nodes.items(.tag);969 const node_tags = tree.nodes.items(.tag);
949 const main_tokens = tree.nodes.items(.main_token);970 const main_tokens = tree.nodes.items(.main_token);
...@@ -951,77 +972,77 @@ fn renderAsmOutput(...@@ -951,77 +972,77 @@ fn renderAsmOutput(
951 assert(node_tags[asm_output] == .asm_output);972 assert(node_tags[asm_output] == .asm_output);
952 const symbolic_name = main_tokens[asm_output];973 const symbolic_name = main_tokens[asm_output];
953974
954 try renderToken(ais, tree, symbolic_name - 1, .none); // lbracket975 try renderToken(r, symbolic_name - 1, .none); // lbracket
955 try renderIdentifier(ais, tree, symbolic_name, .none, .eagerly_unquote); // ident976 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
956 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket977 try renderToken(r, symbolic_name + 1, .space); // rbracket
957 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"978 try renderToken(r, symbolic_name + 2, .space); // "constraint"
958 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen979 try renderToken(r, symbolic_name + 3, .none); // lparen
959980
960 if (token_tags[symbolic_name + 4] == .arrow) {981 if (token_tags[symbolic_name + 4] == .arrow) {
961 try renderToken(ais, tree, symbolic_name + 4, .space); // ->982 try renderToken(r, symbolic_name + 4, .space); // ->
962 try renderExpression(gpa, ais, tree, datas[asm_output].lhs, Space.none);983 try renderExpression(r, datas[asm_output].lhs, Space.none);
963 return renderToken(ais, tree, datas[asm_output].rhs, space); // rparen984 return renderToken(r, datas[asm_output].rhs, space); // rparen
964 } else {985 } else {
965 try renderIdentifier(ais, tree, symbolic_name + 4, .none, .eagerly_unquote); // ident986 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
966 return renderToken(ais, tree, symbolic_name + 5, space); // rparen987 return renderToken(r, symbolic_name + 5, space); // rparen
967 }988 }
968}989}
969990
970fn renderAsmInput(991fn renderAsmInput(
971 gpa: Allocator,992 r: Render,
972 ais: *Ais,
973 tree: Ast,
974 asm_input: Ast.Node.Index,993 asm_input: Ast.Node.Index,
975 space: Space,994 space: Space,
976) Error!void {995) Error!void {
996 const tree = r.tree;
977 const node_tags = tree.nodes.items(.tag);997 const node_tags = tree.nodes.items(.tag);
978 const main_tokens = tree.nodes.items(.main_token);998 const main_tokens = tree.nodes.items(.main_token);
979 const datas = tree.nodes.items(.data);999 const datas = tree.nodes.items(.data);
980 assert(node_tags[asm_input] == .asm_input);1000 assert(node_tags[asm_input] == .asm_input);
981 const symbolic_name = main_tokens[asm_input];1001 const symbolic_name = main_tokens[asm_input];
9821002
983 try renderToken(ais, tree, symbolic_name - 1, .none); // lbracket1003 try renderToken(r, symbolic_name - 1, .none); // lbracket
984 try renderIdentifier(ais, tree, symbolic_name, .none, .eagerly_unquote); // ident1004 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
985 try renderToken(ais, tree, symbolic_name + 1, .space); // rbracket1005 try renderToken(r, symbolic_name + 1, .space); // rbracket
986 try renderToken(ais, tree, symbolic_name + 2, .space); // "constraint"1006 try renderToken(r, symbolic_name + 2, .space); // "constraint"
987 try renderToken(ais, tree, symbolic_name + 3, .none); // lparen1007 try renderToken(r, symbolic_name + 3, .none); // lparen
988 try renderExpression(gpa, ais, tree, datas[asm_input].lhs, Space.none);1008 try renderExpression(r, datas[asm_input].lhs, Space.none);
989 return renderToken(ais, tree, datas[asm_input].rhs, space); // rparen1009 return renderToken(r, datas[asm_input].rhs, space); // rparen
990}1010}
9911011
992fn renderVarDecl(1012fn renderVarDecl(
993 gpa: Allocator,1013 r: Render,
994 ais: *Ais,
995 tree: Ast,
996 var_decl: Ast.full.VarDecl,1014 var_decl: Ast.full.VarDecl,
997 /// Destructures intentionally ignore leading `comptime` tokens.1015 /// Destructures intentionally ignore leading `comptime` tokens.
998 ignore_comptime_token: bool,1016 ignore_comptime_token: bool,
999 /// `comma_space` and `space` are used for destructure LHS decls.1017 /// `comma_space` and `space` are used for destructure LHS decls.
1000 space: Space,1018 space: Space,
1001) Error!void {1019) Error!void {
1020 const tree = r.tree;
1021 const ais = r.ais;
1022
1002 if (var_decl.visib_token) |visib_token| {1023 if (var_decl.visib_token) |visib_token| {
1003 try renderToken(ais, tree, visib_token, Space.space); // pub1024 try renderToken(r, visib_token, Space.space); // pub
1004 }1025 }
10051026
1006 if (var_decl.extern_export_token) |extern_export_token| {1027 if (var_decl.extern_export_token) |extern_export_token| {
1007 try renderToken(ais, tree, extern_export_token, Space.space); // extern1028 try renderToken(r, extern_export_token, Space.space); // extern
10081029
1009 if (var_decl.lib_name) |lib_name| {1030 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"
1011 }1032 }
1012 }1033 }
10131034
1014 if (var_decl.threadlocal_token) |thread_local_token| {1035 if (var_decl.threadlocal_token) |thread_local_token| {
1015 try renderToken(ais, tree, thread_local_token, Space.space); // threadlocal1036 try renderToken(r, thread_local_token, Space.space); // threadlocal
1016 }1037 }
10171038
1018 if (!ignore_comptime_token) {1039 if (!ignore_comptime_token) {
1019 if (var_decl.comptime_token) |comptime_token| {1040 if (var_decl.comptime_token) |comptime_token| {
1020 try renderToken(ais, tree, comptime_token, Space.space); // comptime1041 try renderToken(r, comptime_token, Space.space); // comptime
1021 }1042 }
1022 }1043 }
10231044
1024 try renderToken(ais, tree, var_decl.ast.mut_token, .space); // var1045 try renderToken(r, var_decl.ast.mut_token, .space); // var
10251046
1026 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or1047 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or
1027 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1048 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
...@@ -1036,19 +1057,19 @@ fn renderVarDecl(...@@ -1036,19 +1057,19 @@ fn renderVarDecl(
1036 else1057 else
1037 Space.none;1058 Space.none;
10381059
1039 try renderIdentifier(ais, tree, var_decl.ast.mut_token + 1, name_space, .preserve_when_shadowing); // name1060 try renderIdentifier(r, var_decl.ast.mut_token + 1, name_space, .preserve_when_shadowing); // name
1040 } else {1061 } else {
1041 return renderIdentifier(ais, tree, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name1062 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
1042 }1063 }
10431064
1044 if (var_decl.ast.type_node != 0) {1065 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); // :
1046 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or1067 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or
1047 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)1068 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)
1048 {1069 {
1049 try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space);1070 try renderExpression(r, var_decl.ast.type_node, .space);
1050 } else {1071 } else {
1051 return renderExpression(gpa, ais, tree, var_decl.ast.type_node, space);1072 return renderExpression(r, var_decl.ast.type_node, space);
1052 }1073 }
1053 }1074 }
10541075
...@@ -1056,15 +1077,15 @@ fn renderVarDecl(...@@ -1056,15 +1077,15 @@ fn renderVarDecl(
1056 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;1077 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;
1057 const align_kw = lparen - 1;1078 const align_kw = lparen - 1;
1058 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;1079 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;
1059 try renderToken(ais, tree, align_kw, Space.none); // align1080 try renderToken(r, align_kw, Space.none); // align
1060 try renderToken(ais, tree, lparen, Space.none); // (1081 try renderToken(r, lparen, Space.none); // (
1061 try renderExpression(gpa, ais, tree, var_decl.ast.align_node, Space.none);1082 try renderExpression(r, var_decl.ast.align_node, Space.none);
1062 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1083 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
1063 var_decl.ast.init_node != 0)1084 var_decl.ast.init_node != 0)
1064 {1085 {
1065 try renderToken(ais, tree, rparen, .space); // )1086 try renderToken(r, rparen, .space); // )
1066 } else {1087 } else {
1067 return renderToken(ais, tree, rparen, space); // )1088 return renderToken(r, rparen, space); // )
1068 }1089 }
1069 }1090 }
10701091
...@@ -1072,14 +1093,14 @@ fn renderVarDecl(...@@ -1072,14 +1093,14 @@ fn renderVarDecl(
1072 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;1093 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;
1073 const addrspace_kw = lparen - 1;1094 const addrspace_kw = lparen - 1;
1074 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;1095 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;
1075 try renderToken(ais, tree, addrspace_kw, Space.none); // addrspace1096 try renderToken(r, addrspace_kw, Space.none); // addrspace
1076 try renderToken(ais, tree, lparen, Space.none); // (1097 try renderToken(r, lparen, Space.none); // (
1077 try renderExpression(gpa, ais, tree, var_decl.ast.addrspace_node, Space.none);1098 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);
1078 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {1099 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); // )
1080 } else {1101 } else {
1081 try renderToken(ais, tree, rparen, .none); // )1102 try renderToken(r, rparen, .none); // )
1082 return renderToken(ais, tree, rparen + 1, Space.newline); // ;1103 return renderToken(r, rparen + 1, Space.newline); // ;
1083 }1104 }
1084 }1105 }
10851106
...@@ -1087,13 +1108,13 @@ fn renderVarDecl(...@@ -1087,13 +1108,13 @@ fn renderVarDecl(
1087 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;1108 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;
1088 const section_kw = lparen - 1;1109 const section_kw = lparen - 1;
1089 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;1110 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;
1090 try renderToken(ais, tree, section_kw, Space.none); // linksection1111 try renderToken(r, section_kw, Space.none); // linksection
1091 try renderToken(ais, tree, lparen, Space.none); // (1112 try renderToken(r, lparen, Space.none); // (
1092 try renderExpression(gpa, ais, tree, var_decl.ast.section_node, Space.none);1113 try renderExpression(r, var_decl.ast.section_node, Space.none);
1093 if (var_decl.ast.init_node != 0) {1114 if (var_decl.ast.init_node != 0) {
1094 try renderToken(ais, tree, rparen, .space); // )1115 try renderToken(r, rparen, .space); // )
1095 } else {1116 } else {
1096 return renderToken(ais, tree, rparen, space); // )1117 return renderToken(r, rparen, space); // )
1097 }1118 }
1098 }1119 }
10991120
...@@ -1103,15 +1124,15 @@ fn renderVarDecl(...@@ -1103,15 +1124,15 @@ fn renderVarDecl(
1103 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1124 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
1104 {1125 {
1105 ais.pushIndent();1126 ais.pushIndent();
1106 try renderToken(ais, tree, eq_token, eq_space); // =1127 try renderToken(r, eq_token, eq_space); // =
1107 ais.popIndent();1128 ais.popIndent();
1108 }1129 }
1109 ais.pushIndentOneShot();1130 ais.pushIndentOneShot();
1110 return renderExpression(gpa, ais, tree, var_decl.ast.init_node, space); // ;1131 return renderExpression(r, var_decl.ast.init_node, space); // ;
1111}1132}
11121133
1113fn renderIf(gpa: Allocator, ais: *Ais, tree: Ast, if_node: Ast.full.If, space: Space) Error!void {1134fn renderIf(r: Render, if_node: Ast.full.If, space: Space) Error!void {
1114 return renderWhile(gpa, ais, tree, .{1135 return renderWhile(r, .{
1115 .ast = .{1136 .ast = .{
1116 .while_token = if_node.ast.if_token,1137 .while_token = if_node.ast.if_token,
1117 .cond_expr = if_node.ast.cond_expr,1138 .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...@@ -1129,40 +1150,41 @@ fn renderIf(gpa: Allocator, ais: *Ais, tree: Ast, if_node: Ast.full.If, space: S
11291150
1130/// Note that this function is additionally used to render if expressions, with1151/// Note that this function is additionally used to render if expressions, with
1131/// respective values set to null.1152/// 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;
1133 const token_tags = tree.tokens.items(.tag);1155 const token_tags = tree.tokens.items(.tag);
11341156
1135 if (while_node.label_token) |label| {1157 if (while_node.label_token) |label| {
1136 try renderIdentifier(ais, tree, label, .none, .eagerly_unquote); // label1158 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
1137 try renderToken(ais, tree, label + 1, .space); // :1159 try renderToken(r, label + 1, .space); // :
1138 }1160 }
11391161
1140 if (while_node.inline_token) |inline_token| {1162 if (while_node.inline_token) |inline_token| {
1141 try renderToken(ais, tree, inline_token, .space); // inline1163 try renderToken(r, inline_token, .space); // inline
1142 }1164 }
11431165
1144 try renderToken(ais, tree, while_node.ast.while_token, .space); // if/for/while1166 try renderToken(r, while_node.ast.while_token, .space); // if/for/while
1145 try renderToken(ais, tree, while_node.ast.while_token + 1, .none); // lparen1167 try renderToken(r, while_node.ast.while_token + 1, .none); // lparen
1146 try renderExpression(gpa, ais, tree, while_node.ast.cond_expr, .none); // condition1168 try renderExpression(r, while_node.ast.cond_expr, .none); // condition
11471169
1148 var last_prefix_token = tree.lastToken(while_node.ast.cond_expr) + 1; // rparen1170 var last_prefix_token = tree.lastToken(while_node.ast.cond_expr) + 1; // rparen
11491171
1150 if (while_node.payload_token) |payload_token| {1172 if (while_node.payload_token) |payload_token| {
1151 try renderToken(ais, tree, last_prefix_token, .space);1173 try renderToken(r, last_prefix_token, .space);
1152 try renderToken(ais, tree, payload_token - 1, .none); // |1174 try renderToken(r, payload_token - 1, .none); // |
1153 const ident = blk: {1175 const ident = blk: {
1154 if (token_tags[payload_token] == .asterisk) {1176 if (token_tags[payload_token] == .asterisk) {
1155 try renderToken(ais, tree, payload_token, .none); // *1177 try renderToken(r, payload_token, .none); // *
1156 break :blk payload_token + 1;1178 break :blk payload_token + 1;
1157 } else {1179 } else {
1158 break :blk payload_token;1180 break :blk payload_token;
1159 }1181 }
1160 };1182 };
1161 try renderIdentifier(ais, tree, ident, .none, .preserve_when_shadowing); // identifier1183 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1162 const pipe = blk: {1184 const pipe = blk: {
1163 if (token_tags[ident + 1] == .comma) {1185 if (token_tags[ident + 1] == .comma) {
1164 try renderToken(ais, tree, ident + 1, .space); // ,1186 try renderToken(r, ident + 1, .space); // ,
1165 try renderIdentifier(ais, tree, ident + 2, .none, .preserve_when_shadowing); // index1187 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
1166 break :blk ident + 3;1188 break :blk ident + 3;
1167 } else {1189 } else {
1168 break :blk ident + 1;1190 break :blk ident + 1;
...@@ -1172,18 +1194,16 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,...@@ -1172,18 +1194,16 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,
1172 }1194 }
11731195
1174 if (while_node.ast.cont_expr != 0) {1196 if (while_node.ast.cont_expr != 0) {
1175 try renderToken(ais, tree, last_prefix_token, .space);1197 try renderToken(r, last_prefix_token, .space);
1176 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1198 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1177 try renderToken(ais, tree, lparen - 1, .space); // :1199 try renderToken(r, lparen - 1, .space); // :
1178 try renderToken(ais, tree, lparen, .none); // lparen1200 try renderToken(r, lparen, .none); // lparen
1179 try renderExpression(gpa, ais, tree, while_node.ast.cont_expr, .none);1201 try renderExpression(r, while_node.ast.cont_expr, .none);
1180 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen1202 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen
1181 }1203 }
11821204
1183 try renderThenElse(1205 try renderThenElse(
1184 gpa,1206 r,
1185 ais,
1186 tree,
1187 last_prefix_token,1207 last_prefix_token,
1188 while_node.ast.then_expr,1208 while_node.ast.then_expr,
1189 while_node.else_token,1209 while_node.else_token,
...@@ -1194,9 +1214,7 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,...@@ -1194,9 +1214,7 @@ fn renderWhile(gpa: Allocator, ais: *Ais, tree: Ast, while_node: Ast.full.While,
1194}1214}
11951215
1196fn renderThenElse(1216fn renderThenElse(
1197 gpa: Allocator,1217 r: Render,
1198 ais: *Ais,
1199 tree: Ast,
1200 last_prefix_token: Ast.TokenIndex,1218 last_prefix_token: Ast.TokenIndex,
1201 then_expr: Ast.Node.Index,1219 then_expr: Ast.Node.Index,
1202 else_token: Ast.TokenIndex,1220 else_token: Ast.TokenIndex,
...@@ -1204,33 +1222,35 @@ fn renderThenElse(...@@ -1204,33 +1222,35 @@ fn renderThenElse(
1204 else_expr: Ast.Node.Index,1222 else_expr: Ast.Node.Index,
1205 space: Space,1223 space: Space,
1206) Error!void {1224) Error!void {
1225 const tree = r.tree;
1226 const ais = r.ais;
1207 const node_tags = tree.nodes.items(.tag);1227 const node_tags = tree.nodes.items(.tag);
1208 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);1228 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
1209 const indent_then_expr = !then_expr_is_block and1229 const indent_then_expr = !then_expr_is_block and
1210 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));1230 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
1211 if (indent_then_expr or (then_expr_is_block and ais.isLineOverIndented())) {1231 if (indent_then_expr or (then_expr_is_block and ais.isLineOverIndented())) {
1212 ais.pushIndentNextLine();1232 ais.pushIndentNextLine();
1213 try renderToken(ais, tree, last_prefix_token, .newline);1233 try renderToken(r, last_prefix_token, .newline);
1214 ais.popIndent();1234 ais.popIndent();
1215 } else {1235 } else {
1216 try renderToken(ais, tree, last_prefix_token, .space);1236 try renderToken(r, last_prefix_token, .space);
1217 }1237 }
12181238
1219 if (else_expr != 0) {1239 if (else_expr != 0) {
1220 if (indent_then_expr) {1240 if (indent_then_expr) {
1221 ais.pushIndent();1241 ais.pushIndent();
1222 try renderExpression(gpa, ais, tree, then_expr, .newline);1242 try renderExpression(r, then_expr, .newline);
1223 ais.popIndent();1243 ais.popIndent();
1224 } else {1244 } else {
1225 try renderExpression(gpa, ais, tree, then_expr, .space);1245 try renderExpression(r, then_expr, .space);
1226 }1246 }
12271247
1228 var last_else_token = else_token;1248 var last_else_token = else_token;
12291249
1230 if (maybe_error_token) |error_token| {1250 if (maybe_error_token) |error_token| {
1231 try renderToken(ais, tree, else_token, .space); // else1251 try renderToken(r, else_token, .space); // else
1232 try renderToken(ais, tree, error_token - 1, .none); // |1252 try renderToken(r, error_token - 1, .none); // |
1233 try renderIdentifier(ais, tree, error_token, .none, .preserve_when_shadowing); // identifier1253 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
1234 last_else_token = error_token + 1; // |1254 last_else_token = error_token + 1; // |
1235 }1255 }
12361256
...@@ -1239,53 +1259,55 @@ fn renderThenElse(...@@ -1239,53 +1259,55 @@ fn renderThenElse(
1239 !nodeIsIfForWhileSwitch(node_tags[else_expr]);1259 !nodeIsIfForWhileSwitch(node_tags[else_expr]);
1240 if (indent_else_expr) {1260 if (indent_else_expr) {
1241 ais.pushIndentNextLine();1261 ais.pushIndentNextLine();
1242 try renderToken(ais, tree, last_else_token, .newline);1262 try renderToken(r, last_else_token, .newline);
1243 ais.popIndent();1263 ais.popIndent();
1244 try renderExpressionIndented(gpa, ais, tree, else_expr, space);1264 try renderExpressionIndented(r, else_expr, space);
1245 } else {1265 } else {
1246 try renderToken(ais, tree, last_else_token, .space);1266 try renderToken(r, last_else_token, .space);
1247 try renderExpression(gpa, ais, tree, else_expr, space);1267 try renderExpression(r, else_expr, space);
1248 }1268 }
1249 } else {1269 } else {
1250 if (indent_then_expr) {1270 if (indent_then_expr) {
1251 try renderExpressionIndented(gpa, ais, tree, then_expr, space);1271 try renderExpressionIndented(r, then_expr, space);
1252 } else {1272 } else {
1253 try renderExpression(gpa, ais, tree, then_expr, space);1273 try renderExpression(r, then_expr, space);
1254 }1274 }
1255 }1275 }
1256}1276}
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;
1259 const token_tags = tree.tokens.items(.tag);1281 const token_tags = tree.tokens.items(.tag);
12601282
1261 if (for_node.label_token) |label| {1283 if (for_node.label_token) |label| {
1262 try renderIdentifier(ais, tree, label, .none, .eagerly_unquote); // label1284 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
1263 try renderToken(ais, tree, label + 1, .space); // :1285 try renderToken(r, label + 1, .space); // :
1264 }1286 }
12651287
1266 if (for_node.inline_token) |inline_token| {1288 if (for_node.inline_token) |inline_token| {
1267 try renderToken(ais, tree, inline_token, .space); // inline1289 try renderToken(r, inline_token, .space); // inline
1268 }1290 }
12691291
1270 try renderToken(ais, tree, for_node.ast.for_token, .space); // if/for/while1292 try renderToken(r, for_node.ast.for_token, .space); // if/for/while
12711293
1272 const lparen = for_node.ast.for_token + 1;1294 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
1275 var cur = for_node.payload_token;1297 var cur = for_node.payload_token;
1276 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;1298 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
1277 if (token_tags[pipe - 1] == .comma) {1299 if (token_tags[pipe - 1] == .comma) {
1278 ais.pushIndentNextLine();1300 ais.pushIndentNextLine();
1279 try renderToken(ais, tree, cur - 1, .newline); // |1301 try renderToken(r, cur - 1, .newline); // |
1280 while (true) {1302 while (true) {
1281 if (token_tags[cur] == .asterisk) {1303 if (token_tags[cur] == .asterisk) {
1282 try renderToken(ais, tree, cur, .none); // *1304 try renderToken(r, cur, .none); // *
1283 cur += 1;1305 cur += 1;
1284 }1306 }
1285 try renderIdentifier(ais, tree, cur, .none, .preserve_when_shadowing); // identifier1307 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1286 cur += 1;1308 cur += 1;
1287 if (token_tags[cur] == .comma) {1309 if (token_tags[cur] == .comma) {
1288 try renderToken(ais, tree, cur, .newline); // ,1310 try renderToken(r, cur, .newline); // ,
1289 cur += 1;1311 cur += 1;
1290 }1312 }
1291 if (token_tags[cur] == .pipe) {1313 if (token_tags[cur] == .pipe) {
...@@ -1294,16 +1316,16 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space...@@ -1294,16 +1316,16 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
1294 }1316 }
1295 ais.popIndent();1317 ais.popIndent();
1296 } else {1318 } else {
1297 try renderToken(ais, tree, cur - 1, .none); // |1319 try renderToken(r, cur - 1, .none); // |
1298 while (true) {1320 while (true) {
1299 if (token_tags[cur] == .asterisk) {1321 if (token_tags[cur] == .asterisk) {
1300 try renderToken(ais, tree, cur, .none); // *1322 try renderToken(r, cur, .none); // *
1301 cur += 1;1323 cur += 1;
1302 }1324 }
1303 try renderIdentifier(ais, tree, cur, .none, .preserve_when_shadowing); // identifier1325 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1304 cur += 1;1326 cur += 1;
1305 if (token_tags[cur] == .comma) {1327 if (token_tags[cur] == .comma) {
1306 try renderToken(ais, tree, cur, .space); // ,1328 try renderToken(r, cur, .space); // ,
1307 cur += 1;1329 cur += 1;
1308 }1330 }
1309 if (token_tags[cur] == .pipe) {1331 if (token_tags[cur] == .pipe) {
...@@ -1313,9 +1335,7 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space...@@ -1313,9 +1335,7 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
1313 }1335 }
13141336
1315 try renderThenElse(1337 try renderThenElse(
1316 gpa,1338 r,
1317 ais,
1318 tree,
1319 cur,1339 cur,
1320 for_node.ast.then_expr,1340 for_node.ast.then_expr,
1321 for_node.else_token,1341 for_node.else_token,
...@@ -1326,13 +1346,13 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space...@@ -1326,13 +1346,13 @@ fn renderFor(gpa: Allocator, ais: *Ais, tree: Ast, for_node: Ast.full.For, space
1326}1346}
13271347
1328fn renderContainerField(1348fn renderContainerField(
1329 gpa: Allocator,1349 r: Render,
1330 ais: *Ais,
1331 tree: Ast,
1332 container: Container,1350 container: Container,
1333 field_param: Ast.full.ContainerField,1351 field_param: Ast.full.ContainerField,
1334 space: Space,1352 space: Space,
1335) Error!void {1353) Error!void {
1354 const tree = r.tree;
1355 const ais = r.ais;
1336 var field = field_param;1356 var field = field_param;
1337 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);1357 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);
1338 const quote: QuoteBehavior = switch (container) {1358 const quote: QuoteBehavior = switch (container) {
...@@ -1341,102 +1361,102 @@ fn renderContainerField(...@@ -1341,102 +1361,102 @@ fn renderContainerField(
1341 };1361 };
13421362
1343 if (field.comptime_token) |t| {1363 if (field.comptime_token) |t| {
1344 try renderToken(ais, tree, t, .space); // comptime1364 try renderToken(r, t, .space); // comptime
1345 }1365 }
1346 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {1366 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {
1347 if (field.ast.align_expr != 0) {1367 if (field.ast.align_expr != 0) {
1348 try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name1368 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1349 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1369 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1350 const align_kw = lparen_token - 1;1370 const align_kw = lparen_token - 1;
1351 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1371 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1352 try renderToken(ais, tree, align_kw, .none); // align1372 try renderToken(r, align_kw, .none); // align
1353 try renderToken(ais, tree, lparen_token, .none); // (1373 try renderToken(r, lparen_token, .none); // (
1354 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment1374 try renderExpression(r, field.ast.align_expr, .none); // alignment
1355 return renderToken(ais, tree, rparen_token, .space); // )1375 return renderToken(r, rparen_token, .space); // )
1356 }1376 }
1357 return renderIdentifierComma(ais, tree, field.ast.main_token, space, quote); // name1377 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
1358 }1378 }
1359 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {1379 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {
1360 if (!field.ast.tuple_like) {1380 if (!field.ast.tuple_like) {
1361 try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name1381 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1362 try renderToken(ais, tree, field.ast.main_token + 1, .space); // :1382 try renderToken(r, field.ast.main_token + 1, .space); // :
1363 }1383 }
13641384
1365 if (field.ast.align_expr != 0) {1385 if (field.ast.align_expr != 0) {
1366 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type1386 try renderExpression(r, field.ast.type_expr, .space); // type
1367 const align_token = tree.firstToken(field.ast.align_expr) - 2;1387 const align_token = tree.firstToken(field.ast.align_expr) - 2;
1368 try renderToken(ais, tree, align_token, .none); // align1388 try renderToken(r, align_token, .none); // align
1369 try renderToken(ais, tree, align_token + 1, .none); // (1389 try renderToken(r, align_token + 1, .none); // (
1370 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment1390 try renderExpression(r, field.ast.align_expr, .none); // alignment
1371 const rparen = tree.lastToken(field.ast.align_expr) + 1;1391 const rparen = tree.lastToken(field.ast.align_expr) + 1;
1372 return renderTokenComma(ais, tree, rparen, space); // )1392 return renderTokenComma(r, rparen, space); // )
1373 } else {1393 } else {
1374 return renderExpressionComma(gpa, ais, tree, field.ast.type_expr, space); // type1394 return renderExpressionComma(r, field.ast.type_expr, space); // type
1375 }1395 }
1376 }1396 }
1377 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {1397 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
1378 try renderIdentifier(ais, tree, field.ast.main_token, .space, quote); // name1398 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1379 if (field.ast.align_expr != 0) {1399 if (field.ast.align_expr != 0) {
1380 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1400 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1381 const align_kw = lparen_token - 1;1401 const align_kw = lparen_token - 1;
1382 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1402 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1383 try renderToken(ais, tree, align_kw, .none); // align1403 try renderToken(r, align_kw, .none); // align
1384 try renderToken(ais, tree, lparen_token, .none); // (1404 try renderToken(r, lparen_token, .none); // (
1385 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment1405 try renderExpression(r, field.ast.align_expr, .none); // alignment
1386 try renderToken(ais, tree, rparen_token, .space); // )1406 try renderToken(r, rparen_token, .space); // )
1387 }1407 }
1388 try renderToken(ais, tree, field.ast.main_token + 1, .space); // =1408 try renderToken(r, field.ast.main_token + 1, .space); // =
1389 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value1409 return renderExpressionComma(r, field.ast.value_expr, space); // value
1390 }1410 }
1391 if (!field.ast.tuple_like) {1411 if (!field.ast.tuple_like) {
1392 try renderIdentifier(ais, tree, field.ast.main_token, .none, quote); // name1412 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1393 try renderToken(ais, tree, field.ast.main_token + 1, .space); // :1413 try renderToken(r, field.ast.main_token + 1, .space); // :
1394 }1414 }
1395 try renderExpression(gpa, ais, tree, field.ast.type_expr, .space); // type1415 try renderExpression(r, field.ast.type_expr, .space); // type
13961416
1397 if (field.ast.align_expr != 0) {1417 if (field.ast.align_expr != 0) {
1398 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1418 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1399 const align_kw = lparen_token - 1;1419 const align_kw = lparen_token - 1;
1400 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1420 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1401 try renderToken(ais, tree, align_kw, .none); // align1421 try renderToken(r, align_kw, .none); // align
1402 try renderToken(ais, tree, lparen_token, .none); // (1422 try renderToken(r, lparen_token, .none); // (
1403 try renderExpression(gpa, ais, tree, field.ast.align_expr, .none); // alignment1423 try renderExpression(r, field.ast.align_expr, .none); // alignment
1404 try renderToken(ais, tree, rparen_token, .space); // )1424 try renderToken(r, rparen_token, .space); // )
1405 }1425 }
1406 const eq_token = tree.firstToken(field.ast.value_expr) - 1;1426 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
1407 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1427 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
1408 {1428 {
1409 ais.pushIndent();1429 ais.pushIndent();
1410 try renderToken(ais, tree, eq_token, eq_space); // =1430 try renderToken(r, eq_token, eq_space); // =
1411 ais.popIndent();1431 ais.popIndent();
1412 }1432 }
14131433
1414 if (eq_space == .space)1434 if (eq_space == .space)
1415 return renderExpressionComma(gpa, ais, tree, field.ast.value_expr, space); // value1435 return renderExpressionComma(r, field.ast.value_expr, space); // value
14161436
1417 const token_tags = tree.tokens.items(.tag);1437 const token_tags = tree.tokens.items(.tag);
1418 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;1438 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
14191439
1420 if (token_tags[maybe_comma] == .comma) {1440 if (token_tags[maybe_comma] == .comma) {
1421 ais.pushIndent();1441 ais.pushIndent();
1422 try renderExpression(gpa, ais, tree, field.ast.value_expr, .none); // value1442 try renderExpression(r, field.ast.value_expr, .none); // value
1423 ais.popIndent();1443 ais.popIndent();
1424 try renderToken(ais, tree, maybe_comma, .newline);1444 try renderToken(r, maybe_comma, .newline);
1425 } else {1445 } else {
1426 ais.pushIndent();1446 ais.pushIndent();
1427 try renderExpression(gpa, ais, tree, field.ast.value_expr, space); // value1447 try renderExpression(r, field.ast.value_expr, space); // value
1428 ais.popIndent();1448 ais.popIndent();
1429 }1449 }
1430}1450}
14311451
1432fn renderBuiltinCall(1452fn renderBuiltinCall(
1433 gpa: Allocator,1453 r: Render,
1434 ais: *Ais,
1435 tree: Ast,
1436 builtin_token: Ast.TokenIndex,1454 builtin_token: Ast.TokenIndex,
1437 params: []const Ast.Node.Index,1455 params: []const Ast.Node.Index,
1438 space: Space,1456 space: Space,
1439) Error!void {1457) Error!void {
1458 const tree = r.tree;
1459 const ais = r.ais;
1440 const token_tags = tree.tokens.items(.tag);1460 const token_tags = tree.tokens.items(.tag);
14411461
1442 // TODO remove before release of 0.12.01462 // TODO remove before release of 0.12.0
...@@ -1465,14 +1485,14 @@ fn renderBuiltinCall(...@@ -1465,14 +1485,14 @@ fn renderBuiltinCall(
1465 if (token_tags[after_last_param_token] != .comma) {1485 if (token_tags[after_last_param_token] != .comma) {
1466 // Render all on one line, no trailing comma.1486 // Render all on one line, no trailing comma.
1467 try ais.writer().writeAll("@as");1487 try ais.writer().writeAll("@as");
1468 try renderToken(ais, tree, builtin_token + 1, .none); // (1488 try renderToken(r, builtin_token + 1, .none); // (
1469 try renderExpression(gpa, ais, tree, params[0], .comma_space);1489 try renderExpression(r, params[0], .comma_space);
1470 } else {1490 } else {
1471 // Render one param per line.1491 // Render one param per line.
1472 try ais.writer().writeAll("@as");1492 try ais.writer().writeAll("@as");
1473 ais.pushIndent();1493 ais.pushIndent();
1474 try renderToken(ais, tree, builtin_token + 1, .newline); // (1494 try renderToken(r, builtin_token + 1, .newline); // (
1475 try renderExpression(gpa, ais, tree, params[0], .comma);1495 try renderExpression(r, params[0], .comma);
1476 }1496 }
1477 }1497 }
1478 // Corresponding logic below builtin name rewrite below1498 // Corresponding logic below builtin name rewrite below
...@@ -1507,29 +1527,29 @@ fn renderBuiltinCall(...@@ -1507,29 +1527,29 @@ fn renderBuiltinCall(
1507 } else if (mem.eql(u8, slice, "@errSetCast")) {1527 } else if (mem.eql(u8, slice, "@errSetCast")) {
1508 try ais.writer().writeAll("@errorCast");1528 try ais.writer().writeAll("@errorCast");
1509 } else {1529 } else {
1510 try renderToken(ais, tree, builtin_token, .none); // @name1530 try renderToken(r, builtin_token, .none); // @name
1511 }1531 }
15121532
1513 if (rewrite_two_param_cast) {1533 if (rewrite_two_param_cast) {
1514 // Matches with corresponding logic above builtin name rewrite1534 // Matches with corresponding logic above builtin name rewrite
1515 const after_last_param_token = tree.lastToken(params[1]) + 1;1535 const after_last_param_token = tree.lastToken(params[1]) + 1;
1516 try ais.writer().writeAll("(");1536 try ais.writer().writeAll("(");
1517 try renderExpression(gpa, ais, tree, params[1], .none);1537 try renderExpression(r, params[1], .none);
1518 try ais.writer().writeAll(")");1538 try ais.writer().writeAll(")");
1519 if (token_tags[after_last_param_token] != .comma) {1539 if (token_tags[after_last_param_token] != .comma) {
1520 // Render all on one line, no trailing comma.1540 // 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); // )
1522 } else {1542 } else {
1523 // Render one param per line.1543 // Render one param per line.
1524 ais.popIndent();1544 ais.popIndent();
1525 try renderToken(ais, tree, after_last_param_token, .newline); // ,1545 try renderToken(r, after_last_param_token, .newline); // ,
1526 return renderToken(ais, tree, after_last_param_token + 1, space); // )1546 return renderToken(r, after_last_param_token + 1, space); // )
1527 }1547 }
1528 }1548 }
15291549
1530 if (params.len == 0) {1550 if (params.len == 0) {
1531 try renderToken(ais, tree, builtin_token + 1, .none); // (1551 try renderToken(r, builtin_token + 1, .none); // (
1532 return renderToken(ais, tree, builtin_token + 2, space); // )1552 return renderToken(r, builtin_token + 2, space); // )
1533 }1553 }
15341554
1535 const last_param = params[params.len - 1];1555 const last_param = params[params.len - 1];
...@@ -1537,7 +1557,7 @@ fn renderBuiltinCall(...@@ -1537,7 +1557,7 @@ fn renderBuiltinCall(
15371557
1538 if (token_tags[after_last_param_token] != .comma) {1558 if (token_tags[after_last_param_token] != .comma) {
1539 // Render all on one line, no trailing comma.1559 // 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
1542 for (params, 0..) |param_node, i| {1562 for (params, 0..) |param_node, i| {
1543 const first_param_token = tree.firstToken(param_node);1563 const first_param_token = tree.firstToken(param_node);
...@@ -1546,39 +1566,41 @@ fn renderBuiltinCall(...@@ -1546,39 +1566,41 @@ fn renderBuiltinCall(
1546 {1566 {
1547 ais.pushIndentOneShot();1567 ais.pushIndentOneShot();
1548 }1568 }
1549 try renderExpression(gpa, ais, tree, param_node, .none);1569 try renderExpression(r, param_node, .none);
15501570
1551 if (i + 1 < params.len) {1571 if (i + 1 < params.len) {
1552 const comma_token = tree.lastToken(param_node) + 1;1572 const comma_token = tree.lastToken(param_node) + 1;
1553 try renderToken(ais, tree, comma_token, .space); // ,1573 try renderToken(r, comma_token, .space); // ,
1554 }1574 }
1555 }1575 }
1556 return renderToken(ais, tree, after_last_param_token, space); // )1576 return renderToken(r, after_last_param_token, space); // )
1557 } else {1577 } else {
1558 // Render one param per line.1578 // Render one param per line.
1559 ais.pushIndent();1579 ais.pushIndent();
1560 try renderToken(ais, tree, builtin_token + 1, Space.newline); // (1580 try renderToken(r, builtin_token + 1, Space.newline); // (
15611581
1562 for (params) |param_node| {1582 for (params) |param_node| {
1563 try renderExpression(gpa, ais, tree, param_node, .comma);1583 try renderExpression(r, param_node, .comma);
1564 }1584 }
1565 ais.popIndent();1585 ais.popIndent();
15661586
1567 return renderToken(ais, tree, after_last_param_token + 1, space); // )1587 return renderToken(r, after_last_param_token + 1, space); // )
1568 }1588 }
1569}1589}
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;
1572 const token_tags = tree.tokens.items(.tag);1594 const token_tags = tree.tokens.items(.tag);
1573 const token_starts = tree.tokens.items(.start);1595 const token_starts = tree.tokens.items(.start);
15741596
1575 const after_fn_token = fn_proto.ast.fn_token + 1;1597 const after_fn_token = fn_proto.ast.fn_token + 1;
1576 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {1598 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {
1577 try renderToken(ais, tree, fn_proto.ast.fn_token, .space); // fn1599 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1578 try renderIdentifier(ais, tree, after_fn_token, .none, .preserve_when_shadowing); // name1600 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
1579 break :blk after_fn_token + 1;1601 break :blk after_fn_token + 1;
1580 } else blk: {1602 } else blk: {
1581 try renderToken(ais, tree, fn_proto.ast.fn_token, .space); // fn1603 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1582 break :blk fn_proto.ast.fn_token + 1;1604 break :blk fn_proto.ast.fn_token + 1;
1583 };1605 };
1584 assert(token_tags[lparen] == .l_paren);1606 assert(token_tags[lparen] == .l_paren);
...@@ -1630,7 +1652,7 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt...@@ -1630,7 +1652,7 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1630 const trailing_comma = token_tags[rparen - 1] == .comma;1652 const trailing_comma = token_tags[rparen - 1] == .comma;
1631 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {1653 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
1632 // Render all on one line, no trailing comma.1654 // Render all on one line, no trailing comma.
1633 try renderToken(ais, tree, lparen, .none); // (1655 try renderToken(r, lparen, .none); // (
16341656
1635 var param_i: usize = 0;1657 var param_i: usize = 0;
1636 var last_param_token = lparen;1658 var last_param_token = lparen;
...@@ -1638,25 +1660,25 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt...@@ -1638,25 +1660,25 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1638 last_param_token += 1;1660 last_param_token += 1;
1639 switch (token_tags[last_param_token]) {1661 switch (token_tags[last_param_token]) {
1640 .doc_comment => {1662 .doc_comment => {
1641 try renderToken(ais, tree, last_param_token, .newline);1663 try renderToken(r, last_param_token, .newline);
1642 continue;1664 continue;
1643 },1665 },
1644 .ellipsis3 => {1666 .ellipsis3 => {
1645 try renderToken(ais, tree, last_param_token, .none); // ...1667 try renderToken(r, last_param_token, .none); // ...
1646 break;1668 break;
1647 },1669 },
1648 .keyword_noalias, .keyword_comptime => {1670 .keyword_noalias, .keyword_comptime => {
1649 try renderToken(ais, tree, last_param_token, .space);1671 try renderToken(r, last_param_token, .space);
1650 last_param_token += 1;1672 last_param_token += 1;
1651 },1673 },
1652 .identifier => {},1674 .identifier => {},
1653 .keyword_anytype => {1675 .keyword_anytype => {
1654 try renderToken(ais, tree, last_param_token, .none); // anytype1676 try renderToken(r, last_param_token, .none); // anytype
1655 continue;1677 continue;
1656 },1678 },
1657 .r_paren => break,1679 .r_paren => break,
1658 .comma => {1680 .comma => {
1659 try renderToken(ais, tree, last_param_token, .space); // ,1681 try renderToken(r, last_param_token, .space); // ,
1660 continue;1682 continue;
1661 },1683 },
1662 else => {}, // Parameter type without a name.1684 else => {}, // Parameter type without a name.
...@@ -1664,24 +1686,24 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt...@@ -1664,24 +1686,24 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1664 if (token_tags[last_param_token] == .identifier and1686 if (token_tags[last_param_token] == .identifier and
1665 token_tags[last_param_token + 1] == .colon)1687 token_tags[last_param_token + 1] == .colon)
1666 {1688 {
1667 try renderIdentifier(ais, tree, last_param_token, .none, .preserve_when_shadowing); // name1689 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1668 last_param_token += 1;1690 last_param_token += 1;
1669 try renderToken(ais, tree, last_param_token, .space); // :1691 try renderToken(r, last_param_token, .space); // :
1670 last_param_token += 1;1692 last_param_token += 1;
1671 }1693 }
1672 if (token_tags[last_param_token] == .keyword_anytype) {1694 if (token_tags[last_param_token] == .keyword_anytype) {
1673 try renderToken(ais, tree, last_param_token, .none); // anytype1695 try renderToken(r, last_param_token, .none); // anytype
1674 continue;1696 continue;
1675 }1697 }
1676 const param = fn_proto.ast.params[param_i];1698 const param = fn_proto.ast.params[param_i];
1677 param_i += 1;1699 param_i += 1;
1678 try renderExpression(gpa, ais, tree, param, .none);1700 try renderExpression(r, param, .none);
1679 last_param_token = tree.lastToken(param);1701 last_param_token = tree.lastToken(param);
1680 }1702 }
1681 } else {1703 } else {
1682 // One param per line.1704 // One param per line.
1683 ais.pushIndent();1705 ais.pushIndent();
1684 try renderToken(ais, tree, lparen, .newline); // (1706 try renderToken(r, lparen, .newline); // (
16851707
1686 var param_i: usize = 0;1708 var param_i: usize = 0;
1687 var last_param_token = lparen;1709 var last_param_token = lparen;
...@@ -1689,20 +1711,20 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt...@@ -1689,20 +1711,20 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1689 last_param_token += 1;1711 last_param_token += 1;
1690 switch (token_tags[last_param_token]) {1712 switch (token_tags[last_param_token]) {
1691 .doc_comment => {1713 .doc_comment => {
1692 try renderToken(ais, tree, last_param_token, .newline);1714 try renderToken(r, last_param_token, .newline);
1693 continue;1715 continue;
1694 },1716 },
1695 .ellipsis3 => {1717 .ellipsis3 => {
1696 try renderToken(ais, tree, last_param_token, .comma); // ...1718 try renderToken(r, last_param_token, .comma); // ...
1697 break;1719 break;
1698 },1720 },
1699 .keyword_noalias, .keyword_comptime => {1721 .keyword_noalias, .keyword_comptime => {
1700 try renderToken(ais, tree, last_param_token, .space);1722 try renderToken(r, last_param_token, .space);
1701 last_param_token += 1;1723 last_param_token += 1;
1702 },1724 },
1703 .identifier => {},1725 .identifier => {},
1704 .keyword_anytype => {1726 .keyword_anytype => {
1705 try renderToken(ais, tree, last_param_token, .comma); // anytype1727 try renderToken(r, last_param_token, .comma); // anytype
1706 if (token_tags[last_param_token + 1] == .comma)1728 if (token_tags[last_param_token + 1] == .comma)
1707 last_param_token += 1;1729 last_param_token += 1;
1708 continue;1730 continue;
...@@ -1713,56 +1735,56 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt...@@ -1713,56 +1735,56 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1713 if (token_tags[last_param_token] == .identifier and1735 if (token_tags[last_param_token] == .identifier and
1714 token_tags[last_param_token + 1] == .colon)1736 token_tags[last_param_token + 1] == .colon)
1715 {1737 {
1716 try renderIdentifier(ais, tree, last_param_token, .none, .preserve_when_shadowing); // name1738 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1717 last_param_token += 1;1739 last_param_token += 1;
1718 try renderToken(ais, tree, last_param_token, .space); // :1740 try renderToken(r, last_param_token, .space); // :
1719 last_param_token += 1;1741 last_param_token += 1;
1720 }1742 }
1721 if (token_tags[last_param_token] == .keyword_anytype) {1743 if (token_tags[last_param_token] == .keyword_anytype) {
1722 try renderToken(ais, tree, last_param_token, .comma); // anytype1744 try renderToken(r, last_param_token, .comma); // anytype
1723 if (token_tags[last_param_token + 1] == .comma)1745 if (token_tags[last_param_token + 1] == .comma)
1724 last_param_token += 1;1746 last_param_token += 1;
1725 continue;1747 continue;
1726 }1748 }
1727 const param = fn_proto.ast.params[param_i];1749 const param = fn_proto.ast.params[param_i];
1728 param_i += 1;1750 param_i += 1;
1729 try renderExpression(gpa, ais, tree, param, .comma);1751 try renderExpression(r, param, .comma);
1730 last_param_token = tree.lastToken(param);1752 last_param_token = tree.lastToken(param);
1731 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;1753 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;
1732 }1754 }
1733 ais.popIndent();1755 ais.popIndent();
1734 }1756 }
17351757
1736 try renderToken(ais, tree, rparen, .space); // )1758 try renderToken(r, rparen, .space); // )
17371759
1738 if (fn_proto.ast.align_expr != 0) {1760 if (fn_proto.ast.align_expr != 0) {
1739 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;1761 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;
1740 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;1762 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;
17411763
1742 try renderToken(ais, tree, align_lparen - 1, .none); // align1764 try renderToken(r, align_lparen - 1, .none); // align
1743 try renderToken(ais, tree, align_lparen, .none); // (1765 try renderToken(r, align_lparen, .none); // (
1744 try renderExpression(gpa, ais, tree, fn_proto.ast.align_expr, .none);1766 try renderExpression(r, fn_proto.ast.align_expr, .none);
1745 try renderToken(ais, tree, align_rparen, .space); // )1767 try renderToken(r, align_rparen, .space); // )
1746 }1768 }
17471769
1748 if (fn_proto.ast.addrspace_expr != 0) {1770 if (fn_proto.ast.addrspace_expr != 0) {
1749 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;1771 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;
1750 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;1772 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;
17511773
1752 try renderToken(ais, tree, align_lparen - 1, .none); // addrspace1774 try renderToken(r, align_lparen - 1, .none); // addrspace
1753 try renderToken(ais, tree, align_lparen, .none); // (1775 try renderToken(r, align_lparen, .none); // (
1754 try renderExpression(gpa, ais, tree, fn_proto.ast.addrspace_expr, .none);1776 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);
1755 try renderToken(ais, tree, align_rparen, .space); // )1777 try renderToken(r, align_rparen, .space); // )
1756 }1778 }
17571779
1758 if (fn_proto.ast.section_expr != 0) {1780 if (fn_proto.ast.section_expr != 0) {
1759 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;1781 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;
1760 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;1782 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;
17611783
1762 try renderToken(ais, tree, section_lparen - 1, .none); // section1784 try renderToken(r, section_lparen - 1, .none); // section
1763 try renderToken(ais, tree, section_lparen, .none); // (1785 try renderToken(r, section_lparen, .none); // (
1764 try renderExpression(gpa, ais, tree, fn_proto.ast.section_expr, .none);1786 try renderExpression(r, fn_proto.ast.section_expr, .none);
1765 try renderToken(ais, tree, section_rparen, .space); // )1787 try renderToken(r, section_rparen, .space); // )
1766 }1788 }
17671789
1768 const is_callconv_inline = mem.eql(u8, "Inline", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));1790 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...@@ -1771,25 +1793,24 @@ fn renderFnProto(gpa: Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnProt
1771 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;1793 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;
1772 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;1794 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;
17731795
1774 try renderToken(ais, tree, callconv_lparen - 1, .none); // callconv1796 try renderToken(r, callconv_lparen - 1, .none); // callconv
1775 try renderToken(ais, tree, callconv_lparen, .none); // (1797 try renderToken(r, callconv_lparen, .none); // (
1776 try renderExpression(gpa, ais, tree, fn_proto.ast.callconv_expr, .none);1798 try renderExpression(r, fn_proto.ast.callconv_expr, .none);
1777 try renderToken(ais, tree, callconv_rparen, .space); // )1799 try renderToken(r, callconv_rparen, .space); // )
1778 }1800 }
17791801
1780 if (token_tags[maybe_bang] == .bang) {1802 if (token_tags[maybe_bang] == .bang) {
1781 try renderToken(ais, tree, maybe_bang, .none); // !1803 try renderToken(r, maybe_bang, .none); // !
1782 }1804 }
1783 return renderExpression(gpa, ais, tree, fn_proto.ast.return_type, space);1805 return renderExpression(r, fn_proto.ast.return_type, space);
1784}1806}
17851807
1786fn renderSwitchCase(1808fn renderSwitchCase(
1787 gpa: Allocator,1809 r: Render,
1788 ais: *Ais,
1789 tree: Ast,
1790 switch_case: Ast.full.SwitchCase,1810 switch_case: Ast.full.SwitchCase,
1791 space: Space,1811 space: Space,
1792) Error!void {1812) Error!void {
1813 const tree = r.tree;
1793 const node_tags = tree.nodes.items(.tag);1814 const node_tags = tree.nodes.items(.tag);
1794 const token_tags = tree.tokens.items(.tag);1815 const token_tags = tree.tokens.items(.tag);
1795 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;1816 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
...@@ -1800,22 +1821,22 @@ fn renderSwitchCase(...@@ -1800,22 +1821,22 @@ fn renderSwitchCase(
18001821
1801 // render inline keyword1822 // render inline keyword
1802 if (switch_case.inline_token) |some| {1823 if (switch_case.inline_token) |some| {
1803 try renderToken(ais, tree, some, .space);1824 try renderToken(r, some, .space);
1804 }1825 }
18051826
1806 // Render everything before the arrow1827 // Render everything before the arrow
1807 if (switch_case.ast.values.len == 0) {1828 if (switch_case.ast.values.len == 0) {
1808 try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .space); // else keyword1829 try renderToken(r, switch_case.ast.arrow_token - 1, .space); // else keyword
1809 } else if (switch_case.ast.values.len == 1 and !has_comment_before_arrow) {1830 } else if (switch_case.ast.values.len == 1 and !has_comment_before_arrow) {
1810 // render on one line and drop the trailing comma if any1831 // 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);
1812 } else if (trailing_comma or has_comment_before_arrow) {1833 } else if (trailing_comma or has_comment_before_arrow) {
1813 // Render each value on a new line1834 // 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);
1815 } else {1836 } else {
1816 // Render on one line1837 // Render on one line
1817 for (switch_case.ast.values) |value_expr| {1838 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);
1819 }1840 }
1820 }1841 }
18211842
...@@ -1826,35 +1847,35 @@ fn renderSwitchCase(...@@ -1826,35 +1847,35 @@ fn renderSwitchCase(
1826 else1847 else
1827 Space.space;1848 Space.space;
1828 const after_arrow_space: Space = if (switch_case.payload_token == null) pre_target_space else .space;1849 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
1831 if (switch_case.payload_token) |payload_token| {1852 if (switch_case.payload_token) |payload_token| {
1832 try renderToken(ais, tree, payload_token - 1, .none); // pipe1853 try renderToken(r, payload_token - 1, .none); // pipe
1833 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);1854 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);
1834 if (token_tags[payload_token] == .asterisk) {1855 if (token_tags[payload_token] == .asterisk) {
1835 try renderToken(ais, tree, payload_token, .none); // asterisk1856 try renderToken(r, payload_token, .none); // asterisk
1836 }1857 }
1837 try renderIdentifier(ais, tree, ident, .none, .preserve_when_shadowing); // identifier1858 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1838 if (token_tags[ident + 1] == .comma) {1859 if (token_tags[ident + 1] == .comma) {
1839 try renderToken(ais, tree, ident + 1, .space); // ,1860 try renderToken(r, ident + 1, .space); // ,
1840 try renderIdentifier(ais, tree, ident + 2, .none, .preserve_when_shadowing); // identifier1861 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
1841 try renderToken(ais, tree, ident + 3, pre_target_space); // pipe1862 try renderToken(r, ident + 3, pre_target_space); // pipe
1842 } else {1863 } else {
1843 try renderToken(ais, tree, ident + 1, pre_target_space); // pipe1864 try renderToken(r, ident + 1, pre_target_space); // pipe
1844 }1865 }
1845 }1866 }
18461867
1847 try renderExpression(gpa, ais, tree, switch_case.ast.target_expr, space);1868 try renderExpression(r, switch_case.ast.target_expr, space);
1848}1869}
18491870
1850fn renderBlock(1871fn renderBlock(
1851 gpa: Allocator,1872 r: Render,
1852 ais: *Ais,
1853 tree: Ast,
1854 block_node: Ast.Node.Index,1873 block_node: Ast.Node.Index,
1855 statements: []const Ast.Node.Index,1874 statements: []const Ast.Node.Index,
1856 space: Space,1875 space: Space,
1857) Error!void {1876) Error!void {
1877 const tree = r.tree;
1878 const ais = r.ais;
1858 const token_tags = tree.tokens.items(.tag);1879 const token_tags = tree.tokens.items(.tag);
1859 const node_tags = tree.nodes.items(.tag);1880 const node_tags = tree.nodes.items(.tag);
1860 const lbrace = tree.nodes.items(.main_token)[block_node];1881 const lbrace = tree.nodes.items(.main_token)[block_node];
...@@ -1862,51 +1883,51 @@ fn renderBlock(...@@ -1862,51 +1883,51 @@ fn renderBlock(
1862 if (token_tags[lbrace - 1] == .colon and1883 if (token_tags[lbrace - 1] == .colon and
1863 token_tags[lbrace - 2] == .identifier)1884 token_tags[lbrace - 2] == .identifier)
1864 {1885 {
1865 try renderIdentifier(ais, tree, lbrace - 2, .none, .eagerly_unquote); // identifier1886 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
1866 try renderToken(ais, tree, lbrace - 1, .space); // :1887 try renderToken(r, lbrace - 1, .space); // :
1867 }1888 }
18681889
1869 ais.pushIndentNextLine();1890 ais.pushIndentNextLine();
1870 if (statements.len == 0) {1891 if (statements.len == 0) {
1871 try renderToken(ais, tree, lbrace, .none);1892 try renderToken(r, lbrace, .none);
1872 } else {1893 } else {
1873 try renderToken(ais, tree, lbrace, .newline);1894 try renderToken(r, lbrace, .newline);
1874 for (statements, 0..) |stmt, i| {1895 for (statements, 0..) |stmt, i| {
1875 if (i != 0) try renderExtraNewline(ais, tree, stmt);1896 if (i != 0) try renderExtraNewline(r, stmt);
1876 switch (node_tags[stmt]) {1897 switch (node_tags[stmt]) {
1877 .global_var_decl,1898 .global_var_decl,
1878 .local_var_decl,1899 .local_var_decl,
1879 .simple_var_decl,1900 .simple_var_decl,
1880 .aligned_var_decl,1901 .aligned_var_decl,
1881 => try renderVarDecl(gpa, ais, tree, tree.fullVarDecl(stmt).?, false, .semicolon),1902 => try renderVarDecl(r, tree.fullVarDecl(stmt).?, false, .semicolon),
1882 else => try renderExpression(gpa, ais, tree, stmt, .semicolon),1903 else => try renderExpression(r, stmt, .semicolon),
1883 }1904 }
1884 }1905 }
1885 }1906 }
1886 ais.popIndent();1907 ais.popIndent();
18871908
1888 try renderToken(ais, tree, tree.lastToken(block_node), space); // rbrace1909 try renderToken(r, tree.lastToken(block_node), space); // rbrace
1889}1910}
18901911
1891fn renderStructInit(1912fn renderStructInit(
1892 gpa: Allocator,1913 r: Render,
1893 ais: *Ais,
1894 tree: Ast,
1895 struct_node: Ast.Node.Index,1914 struct_node: Ast.Node.Index,
1896 struct_init: Ast.full.StructInit,1915 struct_init: Ast.full.StructInit,
1897 space: Space,1916 space: Space,
1898) Error!void {1917) Error!void {
1918 const tree = r.tree;
1919 const ais = r.ais;
1899 const token_tags = tree.tokens.items(.tag);1920 const token_tags = tree.tokens.items(.tag);
1900 if (struct_init.ast.type_expr == 0) {1921 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); // .
1902 } else {1923 } else {
1903 try renderExpression(gpa, ais, tree, struct_init.ast.type_expr, .none); // T1924 try renderExpression(r, struct_init.ast.type_expr, .none); // T
1904 }1925 }
1905 if (struct_init.ast.fields.len == 0) {1926 if (struct_init.ast.fields.len == 0) {
1906 ais.pushIndentNextLine();1927 ais.pushIndentNextLine();
1907 try renderToken(ais, tree, struct_init.ast.lbrace, .none); // lbrace1928 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
1908 ais.popIndent();1929 ais.popIndent();
1909 return renderToken(ais, tree, struct_init.ast.lbrace + 1, space); // rbrace1930 return renderToken(r, struct_init.ast.lbrace + 1, space); // rbrace
1910 }1931 }
19111932
1912 const rbrace = tree.lastToken(struct_node);1933 const rbrace = tree.lastToken(struct_node);
...@@ -1914,65 +1935,66 @@ fn renderStructInit(...@@ -1914,65 +1935,66 @@ fn renderStructInit(
1914 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {1935 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
1915 // Render one field init per line.1936 // Render one field init per line.
1916 ais.pushIndentNextLine();1937 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); // .1940 try renderToken(r, struct_init.ast.lbrace + 1, .none); // .
1920 try renderIdentifier(ais, tree, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name1941 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
1921 // Don't output a space after the = if expression is a multiline string,1942 // Don't output a space after the = if expression is a multiline string,
1922 // since then it will start on the next line.1943 // since then it will start on the next line.
1923 const nodes = tree.nodes.items(.tag);1944 const nodes = tree.nodes.items(.tag);
1924 const expr = nodes[struct_init.ast.fields[0]];1945 const expr = nodes[struct_init.ast.fields[0]];
1925 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;1946 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); // =1947 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
1927 try renderExpression(gpa, ais, tree, struct_init.ast.fields[0], .comma);1948 try renderExpression(r, struct_init.ast.fields[0], .comma);
19281949
1929 for (struct_init.ast.fields[1..]) |field_init| {1950 for (struct_init.ast.fields[1..]) |field_init| {
1930 const init_token = tree.firstToken(field_init);1951 const init_token = tree.firstToken(field_init);
1931 try renderExtraNewlineToken(ais, tree, init_token - 3);1952 try renderExtraNewlineToken(r, init_token - 3);
1932 try renderToken(ais, tree, init_token - 3, .none); // .1953 try renderToken(r, init_token - 3, .none); // .
1933 try renderIdentifier(ais, tree, init_token - 2, .space, .eagerly_unquote); // name1954 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
1934 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;1955 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;
1935 try renderToken(ais, tree, init_token - 1, space_after_equal); // =1956 try renderToken(r, init_token - 1, space_after_equal); // =
1936 try renderExpression(gpa, ais, tree, field_init, .comma);1957 try renderExpression(r, field_init, .comma);
1937 }1958 }
19381959
1939 ais.popIndent();1960 ais.popIndent();
1940 } else {1961 } else {
1941 // Render all on one line, no trailing comma.1962 // 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
1944 for (struct_init.ast.fields) |field_init| {1965 for (struct_init.ast.fields) |field_init| {
1945 const init_token = tree.firstToken(field_init);1966 const init_token = tree.firstToken(field_init);
1946 try renderToken(ais, tree, init_token - 3, .none); // .1967 try renderToken(r, init_token - 3, .none); // .
1947 try renderIdentifier(ais, tree, init_token - 2, .space, .eagerly_unquote); // name1968 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
1948 try renderToken(ais, tree, init_token - 1, .space); // =1969 try renderToken(r, init_token - 1, .space); // =
1949 try renderExpression(gpa, ais, tree, field_init, .comma_space);1970 try renderExpression(r, field_init, .comma_space);
1950 }1971 }
1951 }1972 }
19521973
1953 return renderToken(ais, tree, rbrace, space);1974 return renderToken(r, rbrace, space);
1954}1975}
19551976
1956fn renderArrayInit(1977fn renderArrayInit(
1957 gpa: Allocator,1978 r: Render,
1958 ais: *Ais,
1959 tree: Ast,
1960 array_init: Ast.full.ArrayInit,1979 array_init: Ast.full.ArrayInit,
1961 space: Space,1980 space: Space,
1962) Error!void {1981) Error!void {
1982 const tree = r.tree;
1983 const ais = r.ais;
1984 const gpa = r.gpa;
1963 const token_tags = tree.tokens.items(.tag);1985 const token_tags = tree.tokens.items(.tag);
19641986
1965 if (array_init.ast.type_expr == 0) {1987 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); // .
1967 } else {1989 } else {
1968 try renderExpression(gpa, ais, tree, array_init.ast.type_expr, .none); // T1990 try renderExpression(r, array_init.ast.type_expr, .none); // T
1969 }1991 }
19701992
1971 if (array_init.ast.elements.len == 0) {1993 if (array_init.ast.elements.len == 0) {
1972 ais.pushIndentNextLine();1994 ais.pushIndentNextLine();
1973 try renderToken(ais, tree, array_init.ast.lbrace, .none); // lbrace1995 try renderToken(r, array_init.ast.lbrace, .none); // lbrace
1974 ais.popIndent();1996 ais.popIndent();
1975 return renderToken(ais, tree, array_init.ast.lbrace + 1, space); // rbrace1997 return renderToken(r, array_init.ast.lbrace + 1, space); // rbrace
1976 }1998 }
19771999
1978 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];2000 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
...@@ -1987,9 +2009,9 @@ fn renderArrayInit(...@@ -1987,9 +2009,9 @@ fn renderArrayInit(
1987 if (token_tags[first_token] != .multiline_string_literal_line and2009 if (token_tags[first_token] != .multiline_string_literal_line and
1988 !anythingBetween(tree, last_elem_token, rbrace))2010 !anythingBetween(tree, last_elem_token, rbrace))
1989 {2011 {
1990 try renderToken(ais, tree, array_init.ast.lbrace, .none);2012 try renderToken(r, array_init.ast.lbrace, .none);
1991 try renderExpression(gpa, ais, tree, only_elem, .none);2013 try renderExpression(r, only_elem, .none);
1992 return renderToken(ais, tree, rbrace, space);2014 return renderToken(r, rbrace, space);
1993 }2015 }
1994 }2016 }
19952017
...@@ -2000,19 +2022,19 @@ fn renderArrayInit(...@@ -2000,19 +2022,19 @@ fn renderArrayInit(
2000 // Render all on one line, no trailing comma.2022 // Render all on one line, no trailing comma.
2001 if (array_init.ast.elements.len == 1) {2023 if (array_init.ast.elements.len == 1) {
2002 // If there is only one element, we don't use spaces2024 // If there is only one element, we don't use spaces
2003 try renderToken(ais, tree, array_init.ast.lbrace, .none);2025 try renderToken(r, array_init.ast.lbrace, .none);
2004 try renderExpression(gpa, ais, tree, array_init.ast.elements[0], .none);2026 try renderExpression(r, array_init.ast.elements[0], .none);
2005 } else {2027 } else {
2006 try renderToken(ais, tree, array_init.ast.lbrace, .space);2028 try renderToken(r, array_init.ast.lbrace, .space);
2007 for (array_init.ast.elements) |elem| {2029 for (array_init.ast.elements) |elem| {
2008 try renderExpression(gpa, ais, tree, elem, .comma_space);2030 try renderExpression(r, elem, .comma_space);
2009 }2031 }
2010 }2032 }
2011 return renderToken(ais, tree, last_elem_token + 1, space); // rbrace2033 return renderToken(r, last_elem_token + 1, space); // rbrace
2012 }2034 }
20132035
2014 ais.pushIndentNextLine();2036 ais.pushIndentNextLine();
2015 try renderToken(ais, tree, array_init.ast.lbrace, .newline);2037 try renderToken(r, array_init.ast.lbrace, .newline);
20162038
2017 var expr_index: usize = 0;2039 var expr_index: usize = 0;
2018 while (true) {2040 while (true) {
...@@ -2068,6 +2090,12 @@ fn renderArrayInit(...@@ -2068,6 +2090,12 @@ fn renderArrayInit(
2068 .indent_delta = indent_delta,2090 .indent_delta = indent_delta,
2069 .underlying_writer = sub_expr_buffer.writer(),2091 .underlying_writer = sub_expr_buffer.writer(),
2070 };2092 };
2093 var sub_render: Render = .{
2094 .gpa = r.gpa,
2095 .ais = &auto_indenting_stream,
2096 .tree = r.tree,
2097 .fixups = r.fixups,
2098 };
20712099
2072 // Calculate size of columns in current section2100 // Calculate size of columns in current section
2073 var column_counter: usize = 0;2101 var column_counter: usize = 0;
...@@ -2078,7 +2106,7 @@ fn renderArrayInit(...@@ -2078,7 +2106,7 @@ fn renderArrayInit(
2078 sub_expr_buffer_starts[i] = start;2106 sub_expr_buffer_starts[i] = start;
20792107
2080 if (i + 1 < section_exprs.len) {2108 if (i + 1 < section_exprs.len) {
2081 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .none);2109 try renderExpression(sub_render, expr, .none);
2082 const width = sub_expr_buffer.items.len - start;2110 const width = sub_expr_buffer.items.len - start;
2083 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;2111 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;
2084 contains_newline = contains_newline or this_contains_newline;2112 contains_newline = contains_newline or this_contains_newline;
...@@ -2098,7 +2126,7 @@ fn renderArrayInit(...@@ -2098,7 +2126,7 @@ fn renderArrayInit(
2098 column_counter = 0;2126 column_counter = 0;
2099 }2127 }
2100 } else {2128 } else {
2101 try renderExpression(gpa, &auto_indenting_stream, tree, expr, .comma);2129 try renderExpression(sub_render, expr, .comma);
2102 const width = sub_expr_buffer.items.len - start - 2;2130 const width = sub_expr_buffer.items.len - start - 2;
2103 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;2131 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;
2104 contains_newline = contains_newline or this_contains_newline;2132 contains_newline = contains_newline or this_contains_newline;
...@@ -2143,7 +2171,7 @@ fn renderArrayInit(...@@ -2143,7 +2171,7 @@ fn renderArrayInit(
2143 if (column_counter != row_size - 1) {2171 if (column_counter != row_size - 1) {
2144 if (!expr_newlines[i] and !expr_newlines[i + 1]) {2172 if (!expr_newlines[i] and !expr_newlines[i + 1]) {
2145 // Neither the current or next expression is multiline2173 // Neither the current or next expression is multiline
2146 try renderToken(ais, tree, comma, .space); // ,2174 try renderToken(r, comma, .space); // ,
2147 assert(column_widths[column_counter % row_size] >= expr_widths[i]);2175 assert(column_widths[column_counter % row_size] >= expr_widths[i]);
2148 const padding = column_widths[column_counter % row_size] - expr_widths[i];2176 const padding = column_widths[column_counter % row_size] - expr_widths[i];
2149 try ais.writer().writeByteNTimes(' ', padding);2177 try ais.writer().writeByteNTimes(' ', padding);
...@@ -2154,13 +2182,13 @@ fn renderArrayInit(...@@ -2154,13 +2182,13 @@ fn renderArrayInit(
2154 }2182 }
21552183
2156 if (single_line and row_size != 1) {2184 if (single_line and row_size != 1) {
2157 try renderToken(ais, tree, comma, .space); // ,2185 try renderToken(r, comma, .space); // ,
2158 continue;2186 continue;
2159 }2187 }
21602188
2161 column_counter = 0;2189 column_counter = 0;
2162 try renderToken(ais, tree, comma, .newline); // ,2190 try renderToken(r, comma, .newline); // ,
2163 try renderExtraNewline(ais, tree, next_expr);2191 try renderExtraNewline(r, next_expr);
2164 }2192 }
2165 }2193 }
21662194
...@@ -2169,21 +2197,21 @@ fn renderArrayInit(...@@ -2169,21 +2197,21 @@ fn renderArrayInit(
2169 }2197 }
21702198
2171 ais.popIndent();2199 ais.popIndent();
2172 return renderToken(ais, tree, rbrace, space); // rbrace2200 return renderToken(r, rbrace, space); // rbrace
2173}2201}
21742202
2175fn renderContainerDecl(2203fn renderContainerDecl(
2176 gpa: Allocator,2204 r: Render,
2177 ais: *Ais,
2178 tree: Ast,
2179 container_decl_node: Ast.Node.Index,2205 container_decl_node: Ast.Node.Index,
2180 container_decl: Ast.full.ContainerDecl,2206 container_decl: Ast.full.ContainerDecl,
2181 space: Space,2207 space: Space,
2182) Error!void {2208) Error!void {
2209 const tree = r.tree;
2210 const ais = r.ais;
2183 const token_tags = tree.tokens.items(.tag);2211 const token_tags = tree.tokens.items(.tag);
21842212
2185 if (container_decl.layout_token) |layout_token| {2213 if (container_decl.layout_token) |layout_token| {
2186 try renderToken(ais, tree, layout_token, .space);2214 try renderToken(r, layout_token, .space);
2187 }2215 }
21882216
2189 const container: Container = switch (token_tags[container_decl.ast.main_token]) {2217 const container: Container = switch (token_tags[container_decl.ast.main_token]) {
...@@ -2196,29 +2224,29 @@ fn renderContainerDecl(...@@ -2196,29 +2224,29 @@ fn renderContainerDecl(
21962224
2197 var lbrace: Ast.TokenIndex = undefined;2225 var lbrace: Ast.TokenIndex = undefined;
2198 if (container_decl.ast.enum_token) |enum_token| {2226 if (container_decl.ast.enum_token) |enum_token| {
2199 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union2227 try renderToken(r, container_decl.ast.main_token, .none); // union
2200 try renderToken(ais, tree, enum_token - 1, .none); // lparen2228 try renderToken(r, enum_token - 1, .none); // lparen
2201 try renderToken(ais, tree, enum_token, .none); // enum2229 try renderToken(r, enum_token, .none); // enum
2202 if (container_decl.ast.arg != 0) {2230 if (container_decl.ast.arg != 0) {
2203 try renderToken(ais, tree, enum_token + 1, .none); // lparen2231 try renderToken(r, enum_token + 1, .none); // lparen
2204 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);2232 try renderExpression(r, container_decl.ast.arg, .none);
2205 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2233 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2206 try renderToken(ais, tree, rparen, .none); // rparen2234 try renderToken(r, rparen, .none); // rparen
2207 try renderToken(ais, tree, rparen + 1, .space); // rparen2235 try renderToken(r, rparen + 1, .space); // rparen
2208 lbrace = rparen + 2;2236 lbrace = rparen + 2;
2209 } else {2237 } else {
2210 try renderToken(ais, tree, enum_token + 1, .space); // rparen2238 try renderToken(r, enum_token + 1, .space); // rparen
2211 lbrace = enum_token + 2;2239 lbrace = enum_token + 2;
2212 }2240 }
2213 } else if (container_decl.ast.arg != 0) {2241 } else if (container_decl.ast.arg != 0) {
2214 try renderToken(ais, tree, container_decl.ast.main_token, .none); // union2242 try renderToken(r, container_decl.ast.main_token, .none); // union
2215 try renderToken(ais, tree, container_decl.ast.main_token + 1, .none); // lparen2243 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2216 try renderExpression(gpa, ais, tree, container_decl.ast.arg, .none);2244 try renderExpression(r, container_decl.ast.arg, .none);
2217 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2245 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2218 try renderToken(ais, tree, rparen, .space); // rparen2246 try renderToken(r, rparen, .space); // rparen
2219 lbrace = rparen + 1;2247 lbrace = rparen + 1;
2220 } else {2248 } else {
2221 try renderToken(ais, tree, container_decl.ast.main_token, .space); // union2249 try renderToken(r, container_decl.ast.main_token, .space); // union
2222 lbrace = container_decl.ast.main_token + 1;2250 lbrace = container_decl.ast.main_token + 1;
2223 }2251 }
22242252
...@@ -2226,13 +2254,13 @@ fn renderContainerDecl(...@@ -2226,13 +2254,13 @@ fn renderContainerDecl(
2226 if (container_decl.ast.members.len == 0) {2254 if (container_decl.ast.members.len == 0) {
2227 ais.pushIndentNextLine();2255 ais.pushIndentNextLine();
2228 if (token_tags[lbrace + 1] == .container_doc_comment) {2256 if (token_tags[lbrace + 1] == .container_doc_comment) {
2229 try renderToken(ais, tree, lbrace, .newline); // lbrace2257 try renderToken(r, lbrace, .newline); // lbrace
2230 try renderContainerDocComments(ais, tree, lbrace + 1);2258 try renderContainerDocComments(r, lbrace + 1);
2231 } else {2259 } else {
2232 try renderToken(ais, tree, lbrace, .none); // lbrace2260 try renderToken(r, lbrace, .none); // lbrace
2233 }2261 }
2234 ais.popIndent();2262 ais.popIndent();
2235 return renderToken(ais, tree, rbrace, space); // rbrace2263 return renderToken(r, rbrace, space); // rbrace
2236 }2264 }
22372265
2238 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;2266 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;
...@@ -2258,52 +2286,52 @@ fn renderContainerDecl(...@@ -2258,52 +2286,52 @@ fn renderContainerDecl(
2258 }2286 }
22592287
2260 // Print all the declarations on the same line.2288 // Print all the declarations on the same line.
2261 try renderToken(ais, tree, lbrace, .space); // lbrace2289 try renderToken(r, lbrace, .space); // lbrace
2262 for (container_decl.ast.members) |member| {2290 for (container_decl.ast.members) |member| {
2263 try renderMember(gpa, ais, tree, container, member, .space);2291 try renderMember(r, container, member, .space);
2264 }2292 }
2265 return renderToken(ais, tree, rbrace, space); // rbrace2293 return renderToken(r, rbrace, space); // rbrace
2266 }2294 }
22672295
2268 // One member per line.2296 // One member per line.
2269 ais.pushIndentNextLine();2297 ais.pushIndentNextLine();
2270 try renderToken(ais, tree, lbrace, .newline); // lbrace2298 try renderToken(r, lbrace, .newline); // lbrace
2271 if (token_tags[lbrace + 1] == .container_doc_comment) {2299 if (token_tags[lbrace + 1] == .container_doc_comment) {
2272 try renderContainerDocComments(ais, tree, lbrace + 1);2300 try renderContainerDocComments(r, lbrace + 1);
2273 }2301 }
2274 for (container_decl.ast.members, 0..) |member, i| {2302 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);
2276 switch (tree.nodes.items(.tag)[member]) {2304 switch (tree.nodes.items(.tag)[member]) {
2277 // For container fields, ensure a trailing comma is added if necessary.2305 // For container fields, ensure a trailing comma is added if necessary.
2278 .container_field_init,2306 .container_field_init,
2279 .container_field_align,2307 .container_field_align,
2280 .container_field,2308 .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),
2284 }2312 }
2285 }2313 }
2286 ais.popIndent();2314 ais.popIndent();
22872315
2288 return renderToken(ais, tree, rbrace, space); // rbrace2316 return renderToken(r, rbrace, space); // rbrace
2289}2317}
22902318
2291fn renderAsm(2319fn renderAsm(
2292 gpa: Allocator,2320 r: Render,
2293 ais: *Ais,
2294 tree: Ast,
2295 asm_node: Ast.full.Asm,2321 asm_node: Ast.full.Asm,
2296 space: Space,2322 space: Space,
2297) Error!void {2323) Error!void {
2324 const tree = r.tree;
2325 const ais = r.ais;
2298 const token_tags = tree.tokens.items(.tag);2326 const token_tags = tree.tokens.items(.tag);
22992327
2300 try renderToken(ais, tree, asm_node.ast.asm_token, .space); // asm2328 try renderToken(r, asm_node.ast.asm_token, .space); // asm
23012329
2302 if (asm_node.volatile_token) |volatile_token| {2330 if (asm_node.volatile_token) |volatile_token| {
2303 try renderToken(ais, tree, volatile_token, .space); // volatile2331 try renderToken(r, volatile_token, .space); // volatile
2304 try renderToken(ais, tree, volatile_token + 1, .none); // lparen2332 try renderToken(r, volatile_token + 1, .none); // lparen
2305 } else {2333 } else {
2306 try renderToken(ais, tree, asm_node.ast.asm_token + 1, .none); // lparen2334 try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen
2307 }2335 }
23082336
2309 if (asm_node.ast.items.len == 0) {2337 if (asm_node.ast.items.len == 0) {
...@@ -2311,27 +2339,27 @@ fn renderAsm(...@@ -2311,27 +2339,27 @@ fn renderAsm(
2311 if (asm_node.first_clobber) |first_clobber| {2339 if (asm_node.first_clobber) |first_clobber| {
2312 // asm ("foo" ::: "a", "b")2340 // asm ("foo" ::: "a", "b")
2313 // asm ("foo" ::: "a", "b",)2341 // asm ("foo" ::: "a", "b",)
2314 try renderExpression(gpa, ais, tree, asm_node.ast.template, .space);2342 try renderExpression(r, asm_node.ast.template, .space);
2315 // Render the three colons.2343 // Render the three colons.
2316 try renderToken(ais, tree, first_clobber - 3, .none);2344 try renderToken(r, first_clobber - 3, .none);
2317 try renderToken(ais, tree, first_clobber - 2, .none);2345 try renderToken(r, first_clobber - 2, .none);
2318 try renderToken(ais, tree, first_clobber - 1, .space);2346 try renderToken(r, first_clobber - 1, .space);
23192347
2320 var tok_i = first_clobber;2348 var tok_i = first_clobber;
2321 while (true) : (tok_i += 1) {2349 while (true) : (tok_i += 1) {
2322 try renderToken(ais, tree, tok_i, .none);2350 try renderToken(r, tok_i, .none);
2323 tok_i += 1;2351 tok_i += 1;
2324 switch (token_tags[tok_i]) {2352 switch (token_tags[tok_i]) {
2325 .r_paren => {2353 .r_paren => {
2326 ais.popIndent();2354 ais.popIndent();
2327 return renderToken(ais, tree, tok_i, space);2355 return renderToken(r, tok_i, space);
2328 },2356 },
2329 .comma => {2357 .comma => {
2330 if (token_tags[tok_i + 1] == .r_paren) {2358 if (token_tags[tok_i + 1] == .r_paren) {
2331 ais.popIndent();2359 ais.popIndent();
2332 return renderToken(ais, tree, tok_i + 1, space);2360 return renderToken(r, tok_i + 1, space);
2333 } else {2361 } else {
2334 try renderToken(ais, tree, tok_i, .space);2362 try renderToken(r, tok_i, .space);
2335 }2363 }
2336 },2364 },
2337 else => unreachable,2365 else => unreachable,
...@@ -2339,40 +2367,40 @@ fn renderAsm(...@@ -2339,40 +2367,40 @@ fn renderAsm(
2339 }2367 }
2340 } else {2368 } else {
2341 // asm ("foo")2369 // asm ("foo")
2342 try renderExpression(gpa, ais, tree, asm_node.ast.template, .none);2370 try renderExpression(r, asm_node.ast.template, .none);
2343 ais.popIndent();2371 ais.popIndent();
2344 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen2372 return renderToken(r, asm_node.ast.rparen, space); // rparen
2345 }2373 }
2346 }2374 }
23472375
2348 ais.pushIndent();2376 ais.pushIndent();
2349 try renderExpression(gpa, ais, tree, asm_node.ast.template, .newline);2377 try renderExpression(r, asm_node.ast.template, .newline);
2350 ais.setIndentDelta(asm_indent_delta);2378 ais.setIndentDelta(asm_indent_delta);
2351 const colon1 = tree.lastToken(asm_node.ast.template) + 1;2379 const colon1 = tree.lastToken(asm_node.ast.template) + 1;
23522380
2353 const colon2 = if (asm_node.outputs.len == 0) colon2: {2381 const colon2 = if (asm_node.outputs.len == 0) colon2: {
2354 try renderToken(ais, tree, colon1, .newline); // :2382 try renderToken(r, colon1, .newline); // :
2355 break :colon2 colon1 + 1;2383 break :colon2 colon1 + 1;
2356 } else colon2: {2384 } else colon2: {
2357 try renderToken(ais, tree, colon1, .space); // :2385 try renderToken(r, colon1, .space); // :
23582386
2359 ais.pushIndent();2387 ais.pushIndent();
2360 for (asm_node.outputs, 0..) |asm_output, i| {2388 for (asm_node.outputs, 0..) |asm_output, i| {
2361 if (i + 1 < asm_node.outputs.len) {2389 if (i + 1 < asm_node.outputs.len) {
2362 const next_asm_output = asm_node.outputs[i + 1];2390 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
2365 const comma = tree.firstToken(next_asm_output) - 1;2393 const comma = tree.firstToken(next_asm_output) - 1;
2366 try renderToken(ais, tree, comma, .newline); // ,2394 try renderToken(r, comma, .newline); // ,
2367 try renderExtraNewlineToken(ais, tree, tree.firstToken(next_asm_output));2395 try renderExtraNewlineToken(r, tree.firstToken(next_asm_output));
2368 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {2396 } 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);
2370 ais.popIndent();2398 ais.popIndent();
2371 ais.setIndentDelta(indent_delta);2399 ais.setIndentDelta(indent_delta);
2372 ais.popIndent();2400 ais.popIndent();
2373 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen2401 return renderToken(r, asm_node.ast.rparen, space); // rparen
2374 } else {2402 } else {
2375 try renderAsmOutput(gpa, ais, tree, asm_output, .comma);2403 try renderAsmOutput(r, asm_output, .comma);
2376 const comma_or_colon = tree.lastToken(asm_output) + 1;2404 const comma_or_colon = tree.lastToken(asm_output) + 1;
2377 ais.popIndent();2405 ais.popIndent();
2378 break :colon2 switch (token_tags[comma_or_colon]) {2406 break :colon2 switch (token_tags[comma_or_colon]) {
...@@ -2384,27 +2412,27 @@ fn renderAsm(...@@ -2384,27 +2412,27 @@ fn renderAsm(
2384 };2412 };
23852413
2386 const colon3 = if (asm_node.inputs.len == 0) colon3: {2414 const colon3 = if (asm_node.inputs.len == 0) colon3: {
2387 try renderToken(ais, tree, colon2, .newline); // :2415 try renderToken(r, colon2, .newline); // :
2388 break :colon3 colon2 + 1;2416 break :colon3 colon2 + 1;
2389 } else colon3: {2417 } else colon3: {
2390 try renderToken(ais, tree, colon2, .space); // :2418 try renderToken(r, colon2, .space); // :
2391 ais.pushIndent();2419 ais.pushIndent();
2392 for (asm_node.inputs, 0..) |asm_input, i| {2420 for (asm_node.inputs, 0..) |asm_input, i| {
2393 if (i + 1 < asm_node.inputs.len) {2421 if (i + 1 < asm_node.inputs.len) {
2394 const next_asm_input = asm_node.inputs[i + 1];2422 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
2397 const first_token = tree.firstToken(next_asm_input);2425 const first_token = tree.firstToken(next_asm_input);
2398 try renderToken(ais, tree, first_token - 1, .newline); // ,2426 try renderToken(r, first_token - 1, .newline); // ,
2399 try renderExtraNewlineToken(ais, tree, first_token);2427 try renderExtraNewlineToken(r, first_token);
2400 } else if (asm_node.first_clobber == null) {2428 } else if (asm_node.first_clobber == null) {
2401 try renderAsmInput(gpa, ais, tree, asm_input, .comma);2429 try renderAsmInput(r, asm_input, .comma);
2402 ais.popIndent();2430 ais.popIndent();
2403 ais.setIndentDelta(indent_delta);2431 ais.setIndentDelta(indent_delta);
2404 ais.popIndent();2432 ais.popIndent();
2405 return renderToken(ais, tree, asm_node.ast.rparen, space); // rparen2433 return renderToken(r, asm_node.ast.rparen, space); // rparen
2406 } else {2434 } else {
2407 try renderAsmInput(gpa, ais, tree, asm_input, .comma);2435 try renderAsmInput(r, asm_input, .comma);
2408 const comma_or_colon = tree.lastToken(asm_input) + 1;2436 const comma_or_colon = tree.lastToken(asm_input) + 1;
2409 ais.popIndent();2437 ais.popIndent();
2410 break :colon3 switch (token_tags[comma_or_colon]) {2438 break :colon3 switch (token_tags[comma_or_colon]) {
...@@ -2416,7 +2444,7 @@ fn renderAsm(...@@ -2416,7 +2444,7 @@ fn renderAsm(
2416 unreachable;2444 unreachable;
2417 };2445 };
24182446
2419 try renderToken(ais, tree, colon3, .space); // :2447 try renderToken(r, colon3, .space); // :
2420 const first_clobber = asm_node.first_clobber.?;2448 const first_clobber = asm_node.first_clobber.?;
2421 var tok_i = first_clobber;2449 var tok_i = first_clobber;
2422 while (true) {2450 while (true) {
...@@ -2424,20 +2452,20 @@ fn renderAsm(...@@ -2424,20 +2452,20 @@ fn renderAsm(
2424 .r_paren => {2452 .r_paren => {
2425 ais.setIndentDelta(indent_delta);2453 ais.setIndentDelta(indent_delta);
2426 ais.popIndent();2454 ais.popIndent();
2427 try renderToken(ais, tree, tok_i, .newline);2455 try renderToken(r, tok_i, .newline);
2428 return renderToken(ais, tree, tok_i + 1, space);2456 return renderToken(r, tok_i + 1, space);
2429 },2457 },
2430 .comma => {2458 .comma => {
2431 switch (token_tags[tok_i + 2]) {2459 switch (token_tags[tok_i + 2]) {
2432 .r_paren => {2460 .r_paren => {
2433 ais.setIndentDelta(indent_delta);2461 ais.setIndentDelta(indent_delta);
2434 ais.popIndent();2462 ais.popIndent();
2435 try renderToken(ais, tree, tok_i, .newline);2463 try renderToken(r, tok_i, .newline);
2436 return renderToken(ais, tree, tok_i + 2, space);2464 return renderToken(r, tok_i + 2, space);
2437 },2465 },
2438 else => {2466 else => {
2439 try renderToken(ais, tree, tok_i, .none);2467 try renderToken(r, tok_i, .none);
2440 try renderToken(ais, tree, tok_i + 1, .space);2468 try renderToken(r, tok_i + 1, .space);
2441 tok_i += 2;2469 tok_i += 2;
2442 },2470 },
2443 }2471 }
...@@ -2448,44 +2476,42 @@ fn renderAsm(...@@ -2448,44 +2476,42 @@ fn renderAsm(
2448}2476}
24492477
2450fn renderCall(2478fn renderCall(
2451 gpa: Allocator,2479 r: Render,
2452 ais: *Ais,
2453 tree: Ast,
2454 call: Ast.full.Call,2480 call: Ast.full.Call,
2455 space: Space,2481 space: Space,
2456) Error!void {2482) Error!void {
2457 if (call.async_token) |async_token| {2483 if (call.async_token) |async_token| {
2458 try renderToken(ais, tree, async_token, .space);2484 try renderToken(r, async_token, .space);
2459 }2485 }
2460 try renderExpression(gpa, ais, tree, call.ast.fn_expr, .none);2486 try renderExpression(r, call.ast.fn_expr, .none);
2461 try renderParamList(gpa, ais, tree, call.ast.lparen, call.ast.params, space);2487 try renderParamList(r, call.ast.lparen, call.ast.params, space);
2462}2488}
24632489
2464fn renderParamList(2490fn renderParamList(
2465 gpa: Allocator,2491 r: Render,
2466 ais: *Ais,
2467 tree: Ast,
2468 lparen: Ast.TokenIndex,2492 lparen: Ast.TokenIndex,
2469 params: []const Ast.Node.Index,2493 params: []const Ast.Node.Index,
2470 space: Space,2494 space: Space,
2471) Error!void {2495) Error!void {
2496 const tree = r.tree;
2497 const ais = r.ais;
2472 const token_tags = tree.tokens.items(.tag);2498 const token_tags = tree.tokens.items(.tag);
24732499
2474 if (params.len == 0) {2500 if (params.len == 0) {
2475 ais.pushIndentNextLine();2501 ais.pushIndentNextLine();
2476 try renderToken(ais, tree, lparen, .none);2502 try renderToken(r, lparen, .none);
2477 ais.popIndent();2503 ais.popIndent();
2478 return renderToken(ais, tree, lparen + 1, space); // )2504 return renderToken(r, lparen + 1, space); // )
2479 }2505 }
24802506
2481 const last_param = params[params.len - 1];2507 const last_param = params[params.len - 1];
2482 const after_last_param_tok = tree.lastToken(last_param) + 1;2508 const after_last_param_tok = tree.lastToken(last_param) + 1;
2483 if (token_tags[after_last_param_tok] == .comma) {2509 if (token_tags[after_last_param_tok] == .comma) {
2484 ais.pushIndentNextLine();2510 ais.pushIndentNextLine();
2485 try renderToken(ais, tree, lparen, .newline); // (2511 try renderToken(r, lparen, .newline); // (
2486 for (params, 0..) |param_node, i| {2512 for (params, 0..) |param_node, i| {
2487 if (i + 1 < params.len) {2513 if (i + 1 < params.len) {
2488 try renderExpression(gpa, ais, tree, param_node, .none);2514 try renderExpression(r, param_node, .none);
24892515
2490 // Unindent the comma for multiline string literals.2516 // Unindent the comma for multiline string literals.
2491 const is_multiline_string =2517 const is_multiline_string =
...@@ -2493,20 +2519,20 @@ fn renderParamList(...@@ -2493,20 +2519,20 @@ fn renderParamList(
2493 if (is_multiline_string) ais.popIndent();2519 if (is_multiline_string) ais.popIndent();
24942520
2495 const comma = tree.lastToken(param_node) + 1;2521 const comma = tree.lastToken(param_node) + 1;
2496 try renderToken(ais, tree, comma, .newline); // ,2522 try renderToken(r, comma, .newline); // ,
24972523
2498 if (is_multiline_string) ais.pushIndent();2524 if (is_multiline_string) ais.pushIndent();
24992525
2500 try renderExtraNewline(ais, tree, params[i + 1]);2526 try renderExtraNewline(r, params[i + 1]);
2501 } else {2527 } else {
2502 try renderExpression(gpa, ais, tree, param_node, .comma);2528 try renderExpression(r, param_node, .comma);
2503 }2529 }
2504 }2530 }
2505 ais.popIndent();2531 ais.popIndent();
2506 return renderToken(ais, tree, after_last_param_tok + 1, space); // )2532 return renderToken(r, after_last_param_tok + 1, space); // )
2507 }2533 }
25082534
2509 try renderToken(ais, tree, lparen, .none); // (2535 try renderToken(r, lparen, .none); // (
25102536
2511 for (params, 0..) |param_node, i| {2537 for (params, 0..) |param_node, i| {
2512 const first_param_token = tree.firstToken(param_node);2538 const first_param_token = tree.firstToken(param_node);
...@@ -2515,23 +2541,25 @@ fn renderParamList(...@@ -2515,23 +2541,25 @@ fn renderParamList(
2515 {2541 {
2516 ais.pushIndentOneShot();2542 ais.pushIndentOneShot();
2517 }2543 }
2518 try renderExpression(gpa, ais, tree, param_node, .none);2544 try renderExpression(r, param_node, .none);
25192545
2520 if (i + 1 < params.len) {2546 if (i + 1 < params.len) {
2521 const comma = tree.lastToken(param_node) + 1;2547 const comma = tree.lastToken(param_node) + 1;
2522 const next_multiline_string =2548 const next_multiline_string =
2523 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;2549 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;
2524 const comma_space: Space = if (next_multiline_string) .none else .space;2550 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);
2526 }2552 }
2527 }2553 }
25282554
2529 return renderToken(ais, tree, after_last_param_tok, space); // )2555 return renderToken(r, after_last_param_tok, space); // )
2530}2556}
25312557
2532/// Renders the given expression indented, popping the indent before rendering2558/// Renders the given expression indented, popping the indent before rendering
2533/// any following line comments2559/// 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;
2535 const token_starts = tree.tokens.items(.start);2563 const token_starts = tree.tokens.items(.start);
2536 const token_tags = tree.tokens.items(.tag);2564 const token_tags = tree.tokens.items(.tag);
25372565
...@@ -2545,24 +2573,24 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node...@@ -2545,24 +2573,24 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
2545 .semicolon => token_tags[last_token + 1] == .semicolon,2573 .semicolon => token_tags[last_token + 1] == .semicolon,
2546 };2574 };
25472575
2548 try renderExpression(gpa, ais, tree, node, if (punctuation) .none else .skip);2576 try renderExpression(r, node, if (punctuation) .none else .skip);
25492577
2550 switch (space) {2578 switch (space) {
2551 .none, .space, .newline, .skip => {},2579 .none, .space, .newline, .skip => {},
2552 .comma => {2580 .comma => {
2553 if (token_tags[last_token + 1] == .comma) {2581 if (token_tags[last_token + 1] == .comma) {
2554 try renderToken(ais, tree, last_token + 1, .skip);2582 try renderToken(r, last_token + 1, .skip);
2555 last_token += 1;2583 last_token += 1;
2556 } else {2584 } else {
2557 try ais.writer().writeByte(',');2585 try ais.writer().writeByte(',');
2558 }2586 }
2559 },2587 },
2560 .comma_space => if (token_tags[last_token + 1] == .comma) {2588 .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);
2562 last_token += 1;2590 last_token += 1;
2563 },2591 },
2564 .semicolon => if (token_tags[last_token + 1] == .semicolon) {2592 .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);
2566 last_token += 1;2594 last_token += 1;
2567 },2595 },
2568 }2596 }
...@@ -2572,7 +2600,7 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node...@@ -2572,7 +2600,7 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
2572 if (space == .skip) return;2600 if (space == .skip) return;
25732601
2574 const comment_start = token_starts[last_token] + tokenSliceForRender(tree, last_token).len;2602 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
2577 if (!comment) switch (space) {2605 if (!comment) switch (space) {
2578 .none => {},2606 .none => {},
...@@ -2589,40 +2617,43 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node...@@ -2589,40 +2617,43 @@ fn renderExpressionIndented(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node
25892617
2590/// Render an expression, and the comma that follows it, if it is present in the source.2618/// Render an expression, and the comma that follows it, if it is present in the source.
2591/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2619/// 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;
2593 const token_tags = tree.tokens.items(.tag);2622 const token_tags = tree.tokens.items(.tag);
2594 const maybe_comma = tree.lastToken(node) + 1;2623 const maybe_comma = tree.lastToken(node) + 1;
2595 if (token_tags[maybe_comma] == .comma and space != .comma) {2624 if (token_tags[maybe_comma] == .comma and space != .comma) {
2596 try renderExpression(gpa, ais, tree, node, .none);2625 try renderExpression(r, node, .none);
2597 return renderToken(ais, tree, maybe_comma, space);2626 return renderToken(r, maybe_comma, space);
2598 } else {2627 } else {
2599 return renderExpression(gpa, ais, tree, node, space);2628 return renderExpression(r, node, space);
2600 }2629 }
2601}2630}
26022631
2603/// Render a token, and the comma that follows it, if it is present in the source.2632/// Render a token, and the comma that follows it, if it is present in the source.
2604/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2633/// 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;
2606 const token_tags = tree.tokens.items(.tag);2636 const token_tags = tree.tokens.items(.tag);
2607 const maybe_comma = token + 1;2637 const maybe_comma = token + 1;
2608 if (token_tags[maybe_comma] == .comma and space != .comma) {2638 if (token_tags[maybe_comma] == .comma and space != .comma) {
2609 try renderToken(ais, tree, token, .none);2639 try renderToken(r, token, .none);
2610 return renderToken(ais, tree, maybe_comma, space);2640 return renderToken(r, maybe_comma, space);
2611 } else {2641 } else {
2612 return renderToken(ais, tree, token, space);2642 return renderToken(r, token, space);
2613 }2643 }
2614}2644}
26152645
2616/// Render an identifier, and the comma that follows it, if it is present in the source.2646/// Render an identifier, and the comma that follows it, if it is present in the source.
2617/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2647/// 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;
2619 const token_tags = tree.tokens.items(.tag);2650 const token_tags = tree.tokens.items(.tag);
2620 const maybe_comma = token + 1;2651 const maybe_comma = token + 1;
2621 if (token_tags[maybe_comma] == .comma and space != .comma) {2652 if (token_tags[maybe_comma] == .comma and space != .comma) {
2622 try renderIdentifier(ais, tree, token, .none, quote);2653 try renderIdentifier(r, token, .none, quote);
2623 return renderToken(ais, tree, maybe_comma, space);2654 return renderToken(r, maybe_comma, space);
2624 } else {2655 } else {
2625 return renderIdentifier(ais, tree, token, space, quote);2656 return renderIdentifier(r, token, space, quote);
2626 }2657 }
2627}2658}
26282659
...@@ -2647,13 +2678,17 @@ const Space = enum {...@@ -2647,13 +2678,17 @@ const Space = enum {
2647 skip,2678 skip,
2648};2679};
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;
2651 const lexeme = tokenSliceForRender(tree, token_index);2684 const lexeme = tokenSliceForRender(tree, token_index);
2652 try ais.writer().writeAll(lexeme);2685 try ais.writer().writeAll(lexeme);
2653 try renderSpace(ais, tree, token_index, lexeme.len, space);2686 try renderSpace(r, token_index, lexeme.len, space);
2654}2687}
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;
2657 const token_tags = tree.tokens.items(.tag);2692 const token_tags = tree.tokens.items(.tag);
2658 const token_starts = tree.tokens.items(.start);2693 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...@@ -2665,26 +2700,26 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us
2665 try ais.writer().writeByte(',');2700 try ais.writer().writeByte(',');
2666 }2701 }
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]);
2669 switch (space) {2704 switch (space) {
2670 .none => {},2705 .none => {},
2671 .space => if (!comment) try ais.writer().writeByte(' '),2706 .space => if (!comment) try ais.writer().writeByte(' '),
2672 .newline => if (!comment) try ais.insertNewline(),2707 .newline => if (!comment) try ais.insertNewline(),
26732708
2674 .comma => if (token_tags[token_index + 1] == .comma) {2709 .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);
2676 } else if (!comment) {2711 } else if (!comment) {
2677 try ais.insertNewline();2712 try ais.insertNewline();
2678 },2713 },
26792714
2680 .comma_space => if (token_tags[token_index + 1] == .comma) {2715 .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);
2682 } else if (!comment) {2717 } else if (!comment) {
2683 try ais.writer().writeByte(' ');2718 try ais.writer().writeByte(' ');
2684 },2719 },
26852720
2686 .semicolon => if (token_tags[token_index + 1] == .semicolon) {2721 .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);
2688 } else if (!comment) {2723 } else if (!comment) {
2689 try ais.insertNewline();2724 try ais.insertNewline();
2690 },2725 },
...@@ -2699,12 +2734,13 @@ const QuoteBehavior = enum {...@@ -2699,12 +2734,13 @@ const QuoteBehavior = enum {
2699 eagerly_unquote_except_underscore,2734 eagerly_unquote_except_underscore,
2700};2735};
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;
2703 const token_tags = tree.tokens.items(.tag);2739 const token_tags = tree.tokens.items(.tag);
2704 assert(token_tags[token_index] == .identifier);2740 assert(token_tags[token_index] == .identifier);
2705 const lexeme = tokenSliceForRender(tree, token_index);2741 const lexeme = tokenSliceForRender(tree, token_index);
2706 if (lexeme[0] != '@') {2742 if (lexeme[0] != '@') {
2707 return renderToken(ais, tree, token_index, space);2743 return renderToken(r, token_index, space);
2708 }2744 }
27092745
2710 assert(lexeme.len >= 3);2746 assert(lexeme.len >= 3);
...@@ -2715,15 +2751,15 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp...@@ -2715,15 +2751,15 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
27152751
2716 // Empty name can't be unquoted.2752 // Empty name can't be unquoted.
2717 if (contents.len == 0) {2753 if (contents.len == 0) {
2718 return renderQuotedIdentifier(ais, tree, token_index, space, false);2754 return renderQuotedIdentifier(r, token_index, space, false);
2719 }2755 }
27202756
2721 // Special case for _ which would incorrectly be rejected by isValidId below.2757 // Special case for _ which would incorrectly be rejected by isValidId below.
2722 if (contents.len == 1 and contents[0] == '_') switch (quote) {2758 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),
2724 .eagerly_unquote_except_underscore,2760 .eagerly_unquote_except_underscore,
2725 .preserve_when_shadowing,2761 .preserve_when_shadowing,
2726 => return renderQuotedIdentifier(ais, tree, token_index, space, false),2762 => return renderQuotedIdentifier(r, token_index, space, false),
2727 };2763 };
27282764
2729 // Scan the entire name for characters that would (after un-escaping) be illegal in a symbol,2765 // 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...@@ -2731,23 +2767,23 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
2731 var contents_i: usize = 0;2767 var contents_i: usize = 0;
2732 while (contents_i < contents.len) {2768 while (contents_i < contents.len) {
2733 switch (contents[contents_i]) {2769 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),
2735 'A'...'Z', 'a'...'z', '_' => {},2771 'A'...'Z', 'a'...'z', '_' => {},
2736 '\\' => {2772 '\\' => {
2737 var esc_offset = contents_i;2773 var esc_offset = contents_i;
2738 const res = std.zig.string_literal.parseEscapeSequence(contents, &esc_offset);2774 const res = std.zig.string_literal.parseEscapeSequence(contents, &esc_offset);
2739 switch (res) {2775 switch (res) {
2740 .success => |char| switch (char) {2776 .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),
2742 'A'...'Z', 'a'...'z', '_' => {},2778 'A'...'Z', 'a'...'z', '_' => {},
2743 else => return renderQuotedIdentifier(ais, tree, token_index, space, false),2779 else => return renderQuotedIdentifier(r, token_index, space, false),
2744 },2780 },
2745 .failure => return renderQuotedIdentifier(ais, tree, token_index, space, false),2781 .failure => return renderQuotedIdentifier(r, token_index, space, false),
2746 }2782 }
2747 contents_i += esc_offset;2783 contents_i += esc_offset;
2748 continue;2784 continue;
2749 },2785 },
2750 else => return renderQuotedIdentifier(ais, tree, token_index, space, false),2786 else => return renderQuotedIdentifier(r, token_index, space, false),
2751 }2787 }
2752 contents_i += 1;2788 contents_i += 1;
2753 }2789 }
...@@ -2784,23 +2820,25 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp...@@ -2784,23 +2820,25 @@ fn renderIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, space: Sp
2784 // We read the whole thing, so it could be a keyword or primitive.2820 // We read the whole thing, so it could be a keyword or primitive.
2785 if (contents_i == contents.len) {2821 if (contents_i == contents.len) {
2786 if (!std.zig.isValidId(buf[0..buf_i])) {2822 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);
2788 }2824 }
2789 if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) {2825 if (primitives.isPrimitive(buf[0..buf_i])) switch (quote) {
2790 .eagerly_unquote,2826 .eagerly_unquote,
2791 .eagerly_unquote_except_underscore,2827 .eagerly_unquote_except_underscore,
2792 => return renderQuotedIdentifier(ais, tree, token_index, space, true),2828 => return renderQuotedIdentifier(r, token_index, space, true),
2793 .preserve_when_shadowing => return renderQuotedIdentifier(ais, tree, token_index, space, false),2829 .preserve_when_shadowing => return renderQuotedIdentifier(r, token_index, space, false),
2794 };2830 };
2795 }2831 }
27962832
2797 try renderQuotedIdentifier(ais, tree, token_index, space, true);2833 try renderQuotedIdentifier(r, token_index, space, true);
2798}2834}
27992835
2800// Renders a @"" quoted identifier, normalizing escapes.2836// Renders a @"" quoted identifier, normalizing escapes.
2801// Unnecessary escapes are un-escaped, and \u escapes are normalized to \x when they fit.2837// Unnecessary escapes are un-escaped, and \u escapes are normalized to \x when they fit.
2802// If unquote is true, the @"" is removed and the result is a bare symbol whose validity is asserted.2838// 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;
2804 const token_tags = tree.tokens.items(.tag);2842 const token_tags = tree.tokens.items(.tag);
2805 assert(token_tags[token_index] == .identifier);2843 assert(token_tags[token_index] == .identifier);
2806 const lexeme = tokenSliceForRender(tree, token_index);2844 const lexeme = tokenSliceForRender(tree, token_index);
...@@ -2811,7 +2849,7 @@ fn renderQuotedIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, spa...@@ -2811,7 +2849,7 @@ fn renderQuotedIdentifier(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, spa
2811 try renderIdentifierContents(ais.writer(), contents);2849 try renderIdentifierContents(ais.writer(), contents);
2812 if (!unquote) try ais.writer().writeByte('\"');2850 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);
2815}2853}
28162854
2817fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {2855fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
...@@ -2884,7 +2922,10 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok...@@ -2884,7 +2922,10 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
28842922
2885/// Assumes that start is the first byte past the previous token and2923/// Assumes that start is the first byte past the previous token and
2886/// that end is the last byte before the next token.2924/// 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
2888 var index: usize = start;2929 var index: usize = start;
2889 while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| {2930 while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| {
2890 const comment_start = index + offset;2931 const comment_start = index + offset;
...@@ -2944,12 +2985,14 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {...@@ -2944,12 +2985,14 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {
2944 return index != start;2985 return index != start;
2945}2986}
29462987
2947fn renderExtraNewline(ais: *Ais, tree: Ast, node: Ast.Node.Index) Error!void {2988fn renderExtraNewline(r: Render, node: Ast.Node.Index) Error!void {
2948 return renderExtraNewlineToken(ais, tree, tree.firstToken(node));2989 return renderExtraNewlineToken(r, r.tree.firstToken(node));
2949}2990}
29502991
2951/// Check if there is an empty line immediately before the given token. If so, render it.2992/// 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;
2953 const token_starts = tree.tokens.items(.start);2996 const token_starts = tree.tokens.items(.start);
2954 const token_start = token_starts[token_index];2997 const token_start = token_starts[token_index];
2955 if (token_start == 0) return;2998 if (token_start == 0) return;
...@@ -2974,7 +3017,8 @@ fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Er...@@ -2974,7 +3017,8 @@ fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Er
29743017
2975/// end_token is the token one past the last doc comment token. This function3018/// end_token is the token one past the last doc comment token. This function
2976/// searches backwards from there.3019/// 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;
2978 // Search backwards for the first doc comment.3022 // Search backwards for the first doc comment.
2979 const token_tags = tree.tokens.items(.tag);3023 const token_tags = tree.tokens.items(.tag);
2980 if (end_token == 0) return;3024 if (end_token == 0) return;
...@@ -2995,27 +3039,28 @@ fn renderDocComments(ais: *Ais, tree: Ast, end_token: Ast.TokenIndex) Error!void...@@ -2995,27 +3039,28 @@ fn renderDocComments(ais: *Ais, tree: Ast, end_token: Ast.TokenIndex) Error!void
2995 assert(prev_token_tag != .l_paren);3039 assert(prev_token_tag != .l_paren);
29963040
2997 if (prev_token_tag != .l_brace) {3041 if (prev_token_tag != .l_brace) {
2998 try renderExtraNewlineToken(ais, tree, first_tok);3042 try renderExtraNewlineToken(r, first_tok);
2999 }3043 }
3000 }3044 }
30013045
3002 while (token_tags[tok] == .doc_comment) : (tok += 1) {3046 while (token_tags[tok] == .doc_comment) : (tok += 1) {
3003 try renderToken(ais, tree, tok, .newline);3047 try renderToken(r, tok, .newline);
3004 }3048 }
3005}3049}
30063050
3007/// start_token is first container doc comment token.3051/// 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;
3009 const token_tags = tree.tokens.items(.tag);3054 const token_tags = tree.tokens.items(.tag);
3010 var tok = start_token;3055 var tok = start_token;
3011 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {3056 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {
3012 try renderToken(ais, tree, tok, .newline);3057 try renderToken(r, tok, .newline);
3013 }3058 }
3014 // Render extra newline if there is one between final container doc comment and3059 // Render extra newline if there is one between final container doc comment and
3015 // the next token. If the next token is a doc comment, that code path3060 // the next token. If the next token is a doc comment, that code path
3016 // will have its own logic to insert a newline.3061 // will have its own logic to insert a newline.
3017 if (token_tags[tok] != .doc_comment) {3062 if (token_tags[tok] != .doc_comment) {
3018 try renderExtraNewlineToken(ais, tree, tok);3063 try renderExtraNewlineToken(r, tok);
3019 }3064 }
3020}3065}
30213066