authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-09 22:25:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-09 22:26:21-07:00
log36eee7bc6cbe6fcc388ebdc38fd3c5f06c9e9043
treef52add396d55777d2f2cb510e5f2cc22c61efc31
parent25bcf4eb99d367965b0f699faff5d3fd1d991941

zig fmt: anytype, fn calls with one param, trailing commas

and extra newlines between top level declarations

4 files changed, 404 insertions(+), 161 deletions(-)

lib/std/zig/ast.zig+100-24
......@@ -196,6 +196,7 @@ pub const Tree = struct {
196196 const datas = tree.nodes.items(.data);
197197 const main_tokens = tree.nodes.items(.main_token);
198198 const token_tags = tree.tokens.items(.tag);
199 var end_offset: TokenIndex = 0;
199200 var n = node;
200201 while (true) switch (tags[n]) {
201202 .Root => return 0,
......@@ -251,7 +252,7 @@ pub const Tree = struct {
251252 .ArrayType,
252253 .ArrayTypeSentinel,
253254 .ErrorValue,
254 => return main_tokens[n],
255 => return main_tokens[n] - end_offset,
255256
256257 .ArrayInitDot,
257258 .ArrayInitDotTwo,
......@@ -260,7 +261,7 @@ pub const Tree = struct {
260261 .StructInitDotTwo,
261262 .StructInitDotTwoComma,
262263 .EnumLiteral,
263 => return main_tokens[n] - 1,
264 => return main_tokens[n] - 1 - end_offset,
264265
265266 .Catch,
266267 .FieldAccess,
......@@ -314,24 +315,32 @@ pub const Tree = struct {
314315 .StructInitOne,
315316 .StructInit,
316317 .CallOne,
318 .CallOneComma,
317319 .Call,
320 .CallComma,
318321 .SwitchRange,
319322 .FnDecl,
320323 .ErrorUnion,
321324 => n = datas[n].lhs,
322325
326 .AsyncCallOne,
327 .AsyncCallOneComma,
328 .AsyncCall,
329 .AsyncCallComma,
330 => {
331 end_offset += 1; // async token
332 n = datas[n].lhs;
333 },
334
323335 .ContainerFieldInit,
324336 .ContainerFieldAlign,
325337 .ContainerField,
326338 => {
327339 const name_token = main_tokens[n];
328 if (name_token > 0 and
329 token_tags[name_token - 1] == .Keyword_comptime)
330 {
331 return name_token - 1;
332 } else {
333 return name_token;
340 if (name_token > 0 and token_tags[name_token - 1] == .Keyword_comptime) {
341 end_offset += 1;
334342 }
343 return name_token - end_offset;
335344 },
336345
337346 .GlobalVarDecl,
......@@ -351,10 +360,10 @@ pub const Tree = struct {
351360 .StringLiteral,
352361 => continue,
353362
354 else => return i + 1,
363 else => return i + 1 - end_offset,
355364 }
356365 }
357 return i;
366 return i - end_offset;
358367 },
359368
360369 .Block,
......@@ -365,10 +374,9 @@ pub const Tree = struct {
365374 // Look for a label.
366375 const lbrace = main_tokens[n];
367376 if (token_tags[lbrace - 1] == .Colon) {
368 return lbrace - 2;
369 } else {
370 return lbrace;
377 end_offset += 2;
371378 }
379 return lbrace - end_offset;
372380 },
373381
374382 .ContainerDecl,
......@@ -386,9 +394,10 @@ pub const Tree = struct {
386394 => {
387395 const main_token = main_tokens[n];
388396 switch (token_tags[main_token - 1]) {
389 .Keyword_packed, .Keyword_extern => return main_token - 1,
390 else => return main_token,
397 .Keyword_packed, .Keyword_extern => end_offset += 1,
398 else => {},
391399 }
400 return main_token - end_offset;
392401 },
393402
394403 .PtrTypeAligned,
......@@ -404,12 +413,12 @@ pub const Tree = struct {
404413 },
405414 .LBrace => main_token,
406415 else => unreachable,
407 };
416 } - end_offset;
408417 },
409418
410419 .SwitchCaseOne => {
411420 if (datas[n].lhs == 0) {
412 return main_tokens[n] - 1; // else token
421 return main_tokens[n] - 1 - end_offset; // else token
413422 } else {
414423 n = datas[n].lhs;
415424 }
......@@ -422,7 +431,7 @@ pub const Tree = struct {
422431
423432 .AsmOutput, .AsmInput => {
424433 assert(token_tags[main_tokens[n] - 1] == .LBracket);
425 return main_tokens[n] - 1;
434 return main_tokens[n] - 1 - end_offset;
426435 },
427436
428437 .WhileSimple,
......@@ -435,7 +444,7 @@ pub const Tree = struct {
435444 return switch (token_tags[main_token - 1]) {
436445 .Keyword_inline => main_token - 1,
437446 else => main_token,
438 };
447 } - end_offset;
439448 },
440449 };
441450 }
......@@ -555,7 +564,7 @@ pub const Tree = struct {
555564 return main_tokens[n] + end_offset;
556565 },
557566
558 .Call => {
567 .Call, .AsyncCall => {
559568 end_offset += 1; // for the rparen
560569 const params = tree.extraData(datas[n].rhs, Node.SubRange);
561570 if (params.end - params.start == 0) {
......@@ -563,6 +572,12 @@ pub const Tree = struct {
563572 }
564573 n = tree.extra_data[params.end - 1]; // last parameter
565574 },
575 .CallComma, .AsyncCallComma => {
576 end_offset += 2; // for the comma+rparen
577 const params = tree.extraData(datas[n].rhs, Node.SubRange);
578 assert(params.end > params.start);
579 n = tree.extra_data[params.end - 1]; // last parameter
580 },
566581 .Switch => {
567582 const cases = tree.extraData(datas[n].rhs, Node.SubRange);
568583 if (cases.end - cases.start == 0) {
......@@ -614,6 +629,7 @@ pub const Tree = struct {
614629 n = tree.extra_data[datas[n].rhs - 1]; // last member
615630 },
616631 .CallOne,
632 .AsyncCallOne,
617633 .ArrayAccess,
618634 => {
619635 end_offset += 1; // for the rparen/rbracket
......@@ -622,7 +638,6 @@ pub const Tree = struct {
622638 }
623639 n = datas[n].rhs;
624640 },
625
626641 .ArrayInitDotTwo,
627642 .BlockTwo,
628643 .StructInitDotTwo,
......@@ -755,9 +770,10 @@ pub const Tree = struct {
755770 }
756771 },
757772
758 .SliceOpen => {
759 end_offset += 2; // ellipsis2 and rbracket
773 .SliceOpen, .CallOneComma, .AsyncCallOneComma => {
774 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
760775 n = datas[n].rhs;
776 assert(n != 0);
761777 },
762778 .Slice => {
763779 const extra = tree.extraData(datas[n].rhs, Node.Slice);
......@@ -1496,6 +1512,27 @@ pub const Tree = struct {
14961512 });
14971513 }
14981514
1515 pub fn callOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.Call {
1516 const data = tree.nodes.items(.data)[node];
1517 buffer.* = .{data.rhs};
1518 const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0];
1519 return tree.fullCall(.{
1520 .lparen = tree.nodes.items(.main_token)[node],
1521 .fn_expr = data.lhs,
1522 .params = params,
1523 });
1524 }
1525
1526 pub fn callFull(tree: Tree, node: Node.Index) full.Call {
1527 const data = tree.nodes.items(.data)[node];
1528 const extra = tree.extraData(data.rhs, Node.SubRange);
1529 return tree.fullCall(.{
1530 .lparen = tree.nodes.items(.main_token)[node],
1531 .fn_expr = data.lhs,
1532 .params = tree.extra_data[extra.start..extra.end],
1533 });
1534 }
1535
14991536 fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl {
15001537 const token_tags = tree.tokens.items(.tag);
15011538 var result: full.VarDecl = .{
......@@ -1750,6 +1787,19 @@ pub const Tree = struct {
17501787 }
17511788 return result;
17521789 }
1790
1791 fn fullCall(tree: Tree, info: full.Call.Ast) full.Call {
1792 const token_tags = tree.tokens.items(.tag);
1793 var result: full.Call = .{
1794 .ast = info,
1795 .async_token = null,
1796 };
1797 const maybe_async_token = tree.firstToken(info.fn_expr) - 1;
1798 if (token_tags[maybe_async_token] == .Keyword_async) {
1799 result.async_token = maybe_async_token;
1800 }
1801 return result;
1802 }
17531803};
17541804
17551805/// Fully assembled AST node information.
......@@ -1942,6 +1992,17 @@ pub const full = struct {
19421992 rparen: TokenIndex,
19431993 };
19441994 };
1995
1996 pub const Call = struct {
1997 ast: Ast,
1998 async_token: ?TokenIndex,
1999
2000 pub const Ast = struct {
2001 lparen: TokenIndex,
2002 fn_expr: Node.Index,
2003 params: []const Node.Index,
2004 };
2005 };
19452006};
19462007
19472008pub const Error = union(enum) {
......@@ -2383,9 +2444,24 @@ pub const Node = struct {
23832444 StructInit,
23842445 /// `lhs(rhs)`. rhs can be omitted.
23852446 CallOne,
2386 /// `lhs(a, b, c)`. `sub_range_list[rhs]`.
2447 /// `lhs(rhs,)`. rhs can be omitted.
2448 CallOneComma,
2449 /// `async lhs(rhs)`. rhs can be omitted.
2450 AsyncCallOne,
2451 /// `async lhs(rhs,)`.
2452 AsyncCallOneComma,
2453 /// `lhs(a, b, c)`. `SubRange[rhs]`.
23872454 /// main_token is the `(`.
23882455 Call,
2456 /// `lhs(a, b, c,)`. `SubRange[rhs]`.
2457 /// main_token is the `(`.
2458 CallComma,
2459 /// `async lhs(a, b, c)`. `SubRange[rhs]`.
2460 /// main_token is the `(`.
2461 AsyncCall,
2462 /// `async lhs(a, b, c,)`. `SubRange[rhs]`.
2463 /// main_token is the `(`.
2464 AsyncCallComma,
23892465 /// `switch(lhs) {}`. `SubRange[rhs]`.
23902466 Switch,
23912467 /// Same as Switch except there is known to be a trailing comma
lib/std/zig/parse.zig+180-30
......@@ -2254,8 +2254,6 @@ const Parser = struct {
22542254 /// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
22552255 /// FnCallArguments <- LPAREN ExprList RPAREN
22562256 /// ExprList <- (Expr COMMA)* Expr?
2257 /// TODO detect when there is 1 or less parameter to the call and emit
2258 /// CallOne instead of Call.
22592257 fn parseSuffixExpr(p: *Parser) !Node.Index {
22602258 if (p.eatToken(.Keyword_async)) |async_token| {
22612259 var res = try p.expectPrimaryTypeExpr();
......@@ -2269,20 +2267,95 @@ const Parser = struct {
22692267 try p.warn(.{ .ExpectedParamList = .{ .token = p.tok_i } });
22702268 return res;
22712269 };
2272 const params = try ListParseFn(parseExpr)(p);
2273 _ = try p.expectToken(.RParen);
2270 if (p.eatToken(.RParen)) |_| {
2271 return p.addNode(.{
2272 .tag = .AsyncCallOne,
2273 .main_token = lparen,
2274 .data = .{
2275 .lhs = res,
2276 .rhs = 0,
2277 },
2278 });
2279 }
2280 const param_one = try p.expectExpr();
2281 const comma_one = p.eatToken(.Comma);
2282 if (p.eatToken(.RParen)) |_| {
2283 return p.addNode(.{
2284 .tag = if (comma_one == null) .AsyncCallOne else .AsyncCallOneComma,
2285 .main_token = lparen,
2286 .data = .{
2287 .lhs = res,
2288 .rhs = param_one,
2289 },
2290 });
2291 }
2292 if (comma_one == null) {
2293 try p.warn(.{
2294 .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
2295 });
2296 }
22742297
2275 return p.addNode(.{
2276 .tag = .Call,
2277 .main_token = lparen,
2278 .data = .{
2279 .lhs = res,
2280 .rhs = try p.addExtra(Node.SubRange{
2281 .start = params.start,
2282 .end = params.end,
2283 }),
2284 },
2285 });
2298 var param_list = std.ArrayList(Node.Index).init(p.gpa);
2299 defer param_list.deinit();
2300
2301 try param_list.append(param_one);
2302
2303 while (true) {
2304 const next = try p.expectExpr();
2305 try param_list.append(next);
2306 switch (p.token_tags[p.nextToken()]) {
2307 .Comma => {
2308 if (p.eatToken(.RParen)) |_| {
2309 const span = try p.listToSpan(param_list.items);
2310 return p.addNode(.{
2311 .tag = .AsyncCallComma,
2312 .main_token = lparen,
2313 .data = .{
2314 .lhs = res,
2315 .rhs = try p.addExtra(Node.SubRange{
2316 .start = span.start,
2317 .end = span.end,
2318 }),
2319 },
2320 });
2321 } else {
2322 continue;
2323 }
2324 },
2325 .RParen => {
2326 const span = try p.listToSpan(param_list.items);
2327 return p.addNode(.{
2328 .tag = .AsyncCall,
2329 .main_token = lparen,
2330 .data = .{
2331 .lhs = res,
2332 .rhs = try p.addExtra(Node.SubRange{
2333 .start = span.start,
2334 .end = span.end,
2335 }),
2336 },
2337 });
2338 },
2339 .Colon, .RBrace, .RBracket => {
2340 p.tok_i -= 1;
2341 return p.fail(.{
2342 .ExpectedToken = .{
2343 .token = p.tok_i,
2344 .expected_id = .RParen,
2345 },
2346 });
2347 },
2348 else => {
2349 p.tok_i -= 1;
2350 try p.warn(.{
2351 .ExpectedToken = .{
2352 .token = p.tok_i,
2353 .expected_id = .Comma,
2354 },
2355 });
2356 },
2357 }
2358 }
22862359 }
22872360 var res = try p.parsePrimaryTypeExpr();
22882361 if (res == 0) return res;
......@@ -2293,21 +2366,98 @@ const Parser = struct {
22932366 res = suffix_op;
22942367 continue;
22952368 }
2296 const lparen = p.eatToken(.LParen) orelse return res;
2297 const params = try ListParseFn(parseExpr)(p);
2298 _ = try p.expectToken(.RParen);
2369 res = res: {
2370 const lparen = p.eatToken(.LParen) orelse return res;
2371 if (p.eatToken(.RParen)) |_| {
2372 break :res try p.addNode(.{
2373 .tag = .CallOne,
2374 .main_token = lparen,
2375 .data = .{
2376 .lhs = res,
2377 .rhs = 0,
2378 },
2379 });
2380 }
2381 const param_one = try p.expectExpr();
2382 const comma_one = p.eatToken(.Comma);
2383 if (p.eatToken(.RParen)) |_| {
2384 break :res try p.addNode(.{
2385 .tag = if (comma_one == null) .CallOne else .CallOneComma,
2386 .main_token = lparen,
2387 .data = .{
2388 .lhs = res,
2389 .rhs = param_one,
2390 },
2391 });
2392 }
2393 if (comma_one == null) {
2394 try p.warn(.{
2395 .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
2396 });
2397 }
22992398
2300 res = try p.addNode(.{
2301 .tag = .Call,
2302 .main_token = lparen,
2303 .data = .{
2304 .lhs = res,
2305 .rhs = try p.addExtra(Node.SubRange{
2306 .start = params.start,
2307 .end = params.end,
2308 }),
2309 },
2310 });
2399 var param_list = std.ArrayList(Node.Index).init(p.gpa);
2400 defer param_list.deinit();
2401
2402 try param_list.append(param_one);
2403
2404 while (true) {
2405 const next = try p.expectExpr();
2406 try param_list.append(next);
2407 switch (p.token_tags[p.nextToken()]) {
2408 .Comma => {
2409 if (p.eatToken(.RParen)) |_| {
2410 const span = try p.listToSpan(param_list.items);
2411 break :res try p.addNode(.{
2412 .tag = .CallComma,
2413 .main_token = lparen,
2414 .data = .{
2415 .lhs = res,
2416 .rhs = try p.addExtra(Node.SubRange{
2417 .start = span.start,
2418 .end = span.end,
2419 }),
2420 },
2421 });
2422 } else {
2423 continue;
2424 }
2425 },
2426 .RParen => {
2427 const span = try p.listToSpan(param_list.items);
2428 break :res try p.addNode(.{
2429 .tag = .Call,
2430 .main_token = lparen,
2431 .data = .{
2432 .lhs = res,
2433 .rhs = try p.addExtra(Node.SubRange{
2434 .start = span.start,
2435 .end = span.end,
2436 }),
2437 },
2438 });
2439 },
2440 .Colon, .RBrace, .RBracket => {
2441 p.tok_i -= 1;
2442 return p.fail(.{
2443 .ExpectedToken = .{
2444 .token = p.tok_i,
2445 .expected_id = .RParen,
2446 },
2447 });
2448 },
2449 else => {
2450 p.tok_i -= 1;
2451 try p.warn(.{
2452 .ExpectedToken = .{
2453 .token = p.tok_i,
2454 .expected_id = .Comma,
2455 },
2456 });
2457 },
2458 }
2459 }
2460 };
23112461 }
23122462 }
23132463
......@@ -2588,7 +2738,7 @@ const Parser = struct {
25882738
25892739 while (true) {
25902740 const next = try p.expectFieldInit();
2591 if (next == 0) break;
2741 assert(next != 0);
25922742 try init_list.append(next);
25932743 switch (p.token_tags[p.nextToken()]) {
25942744 .Comma => {
lib/std/zig/parser_test.zig+29-29
......@@ -3046,35 +3046,35 @@ test "zig fmt: for" {
30463046// \\
30473047// );
30483048//}
3049//
3050//test "zig fmt: async functions" {
3051// try testCanonical(
3052// \\fn simpleAsyncFn() void {
3053// \\ const a = async a.b();
3054// \\ x += 1;
3055// \\ suspend;
3056// \\ x += 1;
3057// \\ suspend;
3058// \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
3059// \\ await p;
3060// \\}
3061// \\
3062// \\test "suspend, resume, await" {
3063// \\ const p: anyframe = async testAsyncSeq();
3064// \\ resume p;
3065// \\ await p;
3066// \\}
3067// \\
3068// );
3069//}
3070//
3071//test "zig fmt: nosuspend" {
3072// try testCanonical(
3073// \\const a = nosuspend foo();
3074// \\
3075// );
3076//}
3077//
3049
3050test "zig fmt: async functions" {
3051 try testCanonical(
3052 \\fn simpleAsyncFn() void {
3053 \\ const a = async a.b();
3054 \\ x += 1;
3055 \\ suspend;
3056 \\ x += 1;
3057 \\ suspend;
3058 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
3059 \\ await p;
3060 \\}
3061 \\
3062 \\test "suspend, resume, await" {
3063 \\ const p: anyframe = async testAsyncSeq();
3064 \\ resume p;
3065 \\ await p;
3066 \\}
3067 \\
3068 );
3069}
3070
3071test "zig fmt: nosuspend" {
3072 try testCanonical(
3073 \\const a = nosuspend foo();
3074 \\
3075 );
3076}
3077
30783078//test "zig fmt: Block after if" {
30793079// try testCanonical(
30803080// \\test "Block after if" {
lib/std/zig/render.zig+95-78
......@@ -73,8 +73,18 @@ fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {
7373 const nodes_data = tree.nodes.items(.data);
7474 const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];
7575
76 for (root_decls) |decl| {
77 try renderMember(ais, tree, decl, .Newline);
76 return renderAllMembers(ais, tree, root_decls);
77}
78
79fn renderAllMembers(ais: *Ais, tree: ast.Tree, members: []const ast.Node.Index) Error!void {
80 if (members.len == 0) return;
81
82 const first_member = members[0];
83 try renderMember(ais, tree, first_member, .Newline);
84
85 for (members[1..]) |member| {
86 try renderExtraNewline(ais, tree, member);
87 try renderMember(ais, tree, member, .Newline);
7888 }
7989}
8090
......@@ -391,65 +401,17 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
391401 .StructInitDot => return renderStructInit(ais, tree, tree.structInitDot(node), space),
392402 .StructInit => return renderStructInit(ais, tree, tree.structInit(node), space),
393403
394 .CallOne => unreachable, // TODO
395 .Call => {
396 const call = datas[node];
397 const params_range = tree.extraData(call.rhs, ast.Node.SubRange);
398 const params = tree.extra_data[params_range.start..params_range.end];
399 const async_token = tree.firstToken(call.lhs) - 1;
400 if (token_tags[async_token] == .Keyword_async) {
401 try renderToken(ais, tree, async_token, .Space);
402 }
403 try renderExpression(ais, tree, call.lhs, .None);
404
405 const lparen = main_tokens[node];
406
407 if (params.len == 0) {
408 try renderToken(ais, tree, lparen, .None);
409 return renderToken(ais, tree, lparen + 1, space); // )
410 }
411
412 const last_param = params[params.len - 1];
413 const after_last_param_tok = tree.lastToken(last_param) + 1;
414 if (token_tags[after_last_param_tok] == .Comma) {
415 ais.pushIndent();
416 try renderToken(ais, tree, lparen, Space.Newline); // (
417 for (params) |param_node, i| {
418 if (i + 1 < params.len) {
419 try renderExpression(ais, tree, param_node, Space.None);
420
421 // Unindent the comma for multiline string literals
422 const is_multiline_string = node_tags[param_node] == .StringLiteral and
423 token_tags[main_tokens[param_node]] == .MultilineStringLiteralLine;
424 if (is_multiline_string) ais.popIndent();
425
426 const comma = tree.lastToken(param_node) + 1;
427 try renderToken(ais, tree, comma, Space.Newline); // ,
428
429 if (is_multiline_string) ais.pushIndent();
430
431 try renderExtraNewline(ais, tree, params[i + 1]);
432 } else {
433 try renderExpression(ais, tree, param_node, Space.Comma);
434 }
435 }
436 ais.popIndent();
437 return renderToken(ais, tree, after_last_param_tok + 1, space); // )
438 }
439
440 try renderToken(ais, tree, lparen, Space.None); // (
441
442 for (params) |param_node, i| {
443 try renderExpression(ais, tree, param_node, Space.None);
444
445 if (i + 1 < params.len) {
446 const comma = tree.lastToken(param_node) + 1;
447 try renderToken(ais, tree, comma, Space.Space);
448 }
449 }
450 return renderToken(ais, tree, after_last_param_tok, space); // )
404 .CallOne, .CallOneComma, .AsyncCallOne, .AsyncCallOneComma => {
405 var params: [1]ast.Node.Index = undefined;
406 return renderCall(ais, tree, tree.callOne(&params, node), space);
451407 },
452408
409 .Call,
410 .CallComma,
411 .AsyncCall,
412 .AsyncCallComma,
413 => return renderCall(ais, tree, tree.callFull(node), space),
414
453415 .ArrayAccess => {
454416 const suffix = datas[node];
455417 const lbracket = tree.firstToken(suffix.rhs) - 1;
......@@ -625,18 +587,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
625587 },
626588 .FnProto => return renderFnProto(ais, tree, tree.fnProto(node), space),
627589
628 .AnyFrameType => unreachable, // TODO
629 //.AnyFrameType => {
630 // const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
631
632 // if (anyframe_type.result) |result| {
633 // try renderToken(ais, tree, anyframe_type.anyframe_token, Space.None); // anyframe
634 // try renderToken(ais, tree, result.arrow_token, Space.None); // ->
635 // return renderExpression(ais, tree, result.return_type, space);
636 // } else {
637 // return renderToken(ais, tree, anyframe_type.anyframe_token, space); // anyframe
638 // }
639 //},
590 .AnyFrameType => {
591 const main_token = main_tokens[node];
592 if (datas[node].rhs != 0) {
593 try renderToken(ais, tree, main_token, .None); // anyframe
594 try renderToken(ais, tree, main_token + 1, .None); // ->
595 return renderExpression(ais, tree, datas[node].rhs, space);
596 } else {
597 return renderToken(ais, tree, main_token, space); // anyframe
598 }
599 },
640600
641601 .Switch,
642602 .SwitchComma,
......@@ -1730,13 +1690,7 @@ fn renderContainerDecl(
17301690 // One member per line.
17311691 ais.pushIndent();
17321692 try renderToken(ais, tree, lbrace, .Newline); // lbrace
1733 for (container_decl.ast.members) |member, i| {
1734 try renderMember(ais, tree, member, .Newline);
1735
1736 if (i + 1 < container_decl.ast.members.len) {
1737 try renderExtraNewline(ais, tree, container_decl.ast.members[i + 1]);
1738 }
1739 }
1693 try renderAllMembers(ais, tree, container_decl.ast.members);
17401694 ais.popIndent();
17411695
17421696 return renderToken(ais, tree, rbrace, space); // rbrace
......@@ -1871,6 +1825,69 @@ fn renderAsm(
18711825 } else unreachable; // TODO shouldn't need this on while(true)
18721826}
18731827
1828fn renderCall(
1829 ais: *Ais,
1830 tree: ast.Tree,
1831 call: ast.full.Call,
1832 space: Space,
1833) Error!void {
1834 const token_tags = tree.tokens.items(.tag);
1835 const node_tags = tree.nodes.items(.tag);
1836 const main_tokens = tree.nodes.items(.main_token);
1837
1838 if (call.async_token) |async_token| {
1839 try renderToken(ais, tree, async_token, .Space);
1840 }
1841 try renderExpression(ais, tree, call.ast.fn_expr, .None);
1842
1843 const lparen = call.ast.lparen;
1844 const params = call.ast.params;
1845 if (params.len == 0) {
1846 try renderToken(ais, tree, lparen, .None);
1847 return renderToken(ais, tree, lparen + 1, space); // )
1848 }
1849
1850 const last_param = params[params.len - 1];
1851 const after_last_param_tok = tree.lastToken(last_param) + 1;
1852 if (token_tags[after_last_param_tok] == .Comma) {
1853 ais.pushIndent();
1854 try renderToken(ais, tree, lparen, Space.Newline); // (
1855 for (params) |param_node, i| {
1856 if (i + 1 < params.len) {
1857 try renderExpression(ais, tree, param_node, Space.None);
1858
1859 // Unindent the comma for multiline string literals
1860 const is_multiline_string = node_tags[param_node] == .StringLiteral and
1861 token_tags[main_tokens[param_node]] == .MultilineStringLiteralLine;
1862 if (is_multiline_string) ais.popIndent();
1863
1864 const comma = tree.lastToken(param_node) + 1;
1865 try renderToken(ais, tree, comma, Space.Newline); // ,
1866
1867 if (is_multiline_string) ais.pushIndent();
1868
1869 try renderExtraNewline(ais, tree, params[i + 1]);
1870 } else {
1871 try renderExpression(ais, tree, param_node, Space.Comma);
1872 }
1873 }
1874 ais.popIndent();
1875 return renderToken(ais, tree, after_last_param_tok + 1, space); // )
1876 }
1877
1878 try renderToken(ais, tree, lparen, Space.None); // (
1879
1880 for (params) |param_node, i| {
1881 try renderExpression(ais, tree, param_node, Space.None);
1882
1883 if (i + 1 < params.len) {
1884 const comma = tree.lastToken(param_node) + 1;
1885 try renderToken(ais, tree, comma, Space.Space);
1886 }
1887 }
1888 return renderToken(ais, tree, after_last_param_tok, space); // )
1889}
1890
18741891/// Render an expression, and the comma that follows it, if it is present in the source.
18751892fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
18761893 const token_tags = tree.tokens.items(.tag);