authorgravatar for 178735591+87flowers@users.noreply.github.com87flowers <178735591+87flowers@users.noreply.github.com> 2024-10-17 01:52:53+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-22 17:09:20-08:00
logc724e157d6da0236dd8e84e3456ccb13c812adaf
tree5ebfffdec6871b8c6a2cce30bce1d11ff482394d
parenta702dc31ccb3443913b8cc30988d366316085767

std/zig/render: implement fixes for unit tests


2 files changed, 78 insertions(+), 67 deletions(-)

lib/std/zig/parser_test.zig+20-20
...@@ -1776,7 +1776,7 @@ test "zig fmt: if nested" {...@@ -1776,7 +1776,7 @@ test "zig fmt: if nested" {
1776 \\ GE_EQUAL1776 \\ GE_EQUAL
1777 \\ else1777 \\ else
1778 \\ GE_GREATER1778 \\ GE_GREATER
1779 \\ // comment1779 \\ // comment
1780 \\ else if (aInt > bInt)1780 \\ else if (aInt > bInt)
1781 \\ GE_LESS1781 \\ GE_LESS
1782 \\ else if (aInt == bInt)1782 \\ else if (aInt == bInt)
...@@ -4670,7 +4670,7 @@ test "zig fmt: test comments in field access chain" {...@@ -4670,7 +4670,7 @@ test "zig fmt: test comments in field access chain" {
4670 \\ .more() //4670 \\ .more() //
4671 \\ .more().more() //4671 \\ .more().more() //
4672 \\ .more() //4672 \\ .more() //
4673 \\ // .more() //4673 \\ // .more() //
4674 \\ .more() //4674 \\ .more() //
4675 \\ .more();4675 \\ .more();
4676 \\ data: Data,4676 \\ data: Data,
...@@ -4679,9 +4679,9 @@ test "zig fmt: test comments in field access chain" {...@@ -4679,9 +4679,9 @@ test "zig fmt: test comments in field access chain" {
4679 \\pub const str = struct {4679 \\pub const str = struct {
4680 \\ pub const Thing = more.more //4680 \\ pub const Thing = more.more //
4681 \\ .more() //4681 \\ .more() //
4682 \\ // .more() //4682 \\ // .more() //
4683 \\ // .more() //4683 \\ // .more() //
4684 \\ // .more() //4684 \\ // .more() //
4685 \\ .more() //4685 \\ .more() //
4686 \\ .more();4686 \\ .more();
4687 \\ data: Data,4687 \\ data: Data,
...@@ -4706,7 +4706,7 @@ test "zig fmt: allow line break before field access" {...@@ -4706,7 +4706,7 @@ test "zig fmt: allow line break before field access" {
4706 \\ const x = foo4706 \\ const x = foo
4707 \\ .bar()4707 \\ .bar()
4708 \\ . // comment4708 \\ . // comment
4709 \\ // comment4709 \\ // comment
4710 \\ swooop().zippy(zag)4710 \\ swooop().zippy(zag)
4711 \\ .iguessthisisok();4711 \\ .iguessthisisok();
4712 \\4712 \\
...@@ -4716,7 +4716,7 @@ test "zig fmt: allow line break before field access" {...@@ -4716,7 +4716,7 @@ test "zig fmt: allow line break before field access" {
4716 \\ .input_manager //4716 \\ .input_manager //
4717 \\ .default_seat4717 \\ .default_seat
4718 \\ . // comment4718 \\ . // comment
4719 \\ // another comment4719 \\ // another comment
4720 \\ wlr_seat.name;4720 \\ wlr_seat.name;
4721 \\}4721 \\}
4722 \\4722 \\
...@@ -4955,19 +4955,19 @@ test "zig fmt: use of comments and multiline string literals may force the param...@@ -4955,19 +4955,19 @@ test "zig fmt: use of comments and multiline string literals may force the param
4955 \\4955 \\
4956 \\// This looks like garbage don't do this4956 \\// This looks like garbage don't do this
4957 \\const rparen = tree.prevToken(4957 \\const rparen = tree.prevToken(
4958 \\// the first token for the annotation expressions is the left4958 \\ // the first token for the annotation expressions is the left
4959 \\// parenthesis, hence the need for two prevToken4959 \\ // parenthesis, hence the need for two prevToken
4960 \\if (fn_proto.getAlignExpr()) |align_expr|4960 \\ if (fn_proto.getAlignExpr()) |align_expr|
4961 \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))4961 \\ tree.prevToken(tree.prevToken(align_expr.firstToken()))
4962 \\else if (fn_proto.getSectionExpr()) |section_expr|4962 \\ else if (fn_proto.getSectionExpr()) |section_expr|
4963 \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))4963 \\ tree.prevToken(tree.prevToken(section_expr.firstToken()))
4964 \\else if (fn_proto.getCallconvExpr()) |callconv_expr|4964 \\ else if (fn_proto.getCallconvExpr()) |callconv_expr|
4965 \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))4965 \\ tree.prevToken(tree.prevToken(callconv_expr.firstToken()))
4966 \\else switch (fn_proto.return_type) {4966 \\ else switch (fn_proto.return_type) {
4967 \\ .Explicit => |node| node.firstToken(),4967 \\ .Explicit => |node| node.firstToken(),
4968 \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),4968 \\ .InferErrorSet => |node| tree.prevToken(node.firstToken()),
4969 \\ .Invalid => unreachable,4969 \\ .Invalid => unreachable,
4970 \\});4970 \\ });
4971 \\4971 \\
4972 );4972 );
4973}4973}
lib/std/zig/render.zig+58-47
...@@ -369,23 +369,19 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -369,23 +369,19 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
369 while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline);369 while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline);
370370
371 // dedent the next thing that comes after a multiline string literal371 // dedent the next thing that comes after a multiline string literal
372 if (!ais.indentStackEmpty()) {372 if (!ais.indentStackEmpty() and
373 token_tags[i] != .colon and
374 ((token_tags[i] != .semicolon and token_tags[i] != .comma) or
375 ais.lastSpaceModeIndent() < ais.currentIndent()))
376 {
373 ais.popIndent();377 ais.popIndent();
374 try ais.pushIndent(.normal);378 try ais.pushIndent(.normal);
375 }379 }
376380
377 switch (space) {381 switch (space) {
378 .none, .space, .newline, .skip => {},382 .none, .space, .newline, .skip => {},
379 .semicolon => if (token_tags[i] == .semicolon) {383 .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon),
380 ais.enableSpaceMode(.semicolon);384 .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma),
381 try renderToken(r, i, .newline);
382 ais.disableSpaceMode();
383 },
384 .comma => if (token_tags[i] == .comma) {
385 ais.enableSpaceMode(.comma);
386 try renderToken(r, i, .newline);
387 ais.disableSpaceMode();
388 },
389 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),385 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),
390 }386 }
391 },387 },
...@@ -476,7 +472,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -476,7 +472,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
476 const main_token = main_tokens[node];472 const main_token = main_tokens[node];
477 const field_access = datas[node];473 const field_access = datas[node];
478474
479 try ais.pushIndent(.normal);475 try ais.pushIndent(.field_access);
480 try renderExpression(r, field_access.lhs, .none);476 try renderExpression(r, field_access.lhs, .none);
481477
482 // Allow a line break between the lhs and the dot if the lhs and rhs478 // Allow a line break between the lhs and the dot if the lhs and rhs
...@@ -740,8 +736,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -740,8 +736,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
740 },736 },
741737
742 .grouped_expression => {738 .grouped_expression => {
743 try renderToken(r, main_tokens[node], .none); // lparen
744 try ais.pushIndent(.normal);739 try ais.pushIndent(.normal);
740 try renderToken(r, main_tokens[node], .none); // lparen
745 try renderExpression(r, datas[node].lhs, .none);741 try renderExpression(r, datas[node].lhs, .none);
746 ais.popIndent();742 ais.popIndent();
747 return renderToken(r, datas[node].rhs, space); // rparen743 return renderToken(r, datas[node].rhs, space); // rparen
...@@ -2444,7 +2440,7 @@ fn renderAsm(...@@ -2444,7 +2440,7 @@ fn renderAsm(
2444 }2440 }
24452441
2446 if (asm_node.ast.items.len == 0) {2442 if (asm_node.ast.items.len == 0) {
2447 try ais.pushIndent(.normal);2443 try ais.forcePushIndent(.normal);
2448 if (asm_node.first_clobber) |first_clobber| {2444 if (asm_node.first_clobber) |first_clobber| {
2449 // asm ("foo" ::: "a", "b")2445 // asm ("foo" ::: "a", "b")
2450 // asm ("foo" ::: "a", "b",)2446 // asm ("foo" ::: "a", "b",)
...@@ -2482,7 +2478,7 @@ fn renderAsm(...@@ -2482,7 +2478,7 @@ fn renderAsm(
2482 }2478 }
2483 }2479 }
24842480
2485 try ais.pushIndent(.normal);2481 try ais.forcePushIndent(.normal);
2486 try renderExpression(r, asm_node.ast.template, .newline);2482 try renderExpression(r, asm_node.ast.template, .newline);
2487 ais.setIndentDelta(asm_indent_delta);2483 ais.setIndentDelta(asm_indent_delta);
2488 const colon1 = tree.lastToken(asm_node.ast.template) + 1;2484 const colon1 = tree.lastToken(asm_node.ast.template) + 1;
...@@ -2493,7 +2489,7 @@ fn renderAsm(...@@ -2493,7 +2489,7 @@ fn renderAsm(
2493 } else colon2: {2489 } else colon2: {
2494 try renderToken(r, colon1, .space); // :2490 try renderToken(r, colon1, .space); // :
24952491
2496 try ais.pushIndent(.normal);2492 try ais.forcePushIndent(.normal);
2497 for (asm_node.outputs, 0..) |asm_output, i| {2493 for (asm_node.outputs, 0..) |asm_output, i| {
2498 if (i + 1 < asm_node.outputs.len) {2494 if (i + 1 < asm_node.outputs.len) {
2499 const next_asm_output = asm_node.outputs[i + 1];2495 const next_asm_output = asm_node.outputs[i + 1];
...@@ -2529,7 +2525,7 @@ fn renderAsm(...@@ -2529,7 +2525,7 @@ fn renderAsm(
2529 break :colon3 colon2 + 1;2525 break :colon3 colon2 + 1;
2530 } else colon3: {2526 } else colon3: {
2531 try renderToken(r, colon2, .space); // :2527 try renderToken(r, colon2, .space); // :
2532 try ais.pushIndent(.normal);2528 try ais.forcePushIndent(.normal);
2533 for (asm_node.inputs, 0..) |asm_input, i| {2529 for (asm_node.inputs, 0..) |asm_input, i| {
2534 if (i + 1 < asm_node.inputs.len) {2530 if (i + 1 < asm_node.inputs.len) {
2535 const next_asm_input = asm_node.inputs[i + 1];2531 const next_asm_input = asm_node.inputs[i + 1];
...@@ -2568,16 +2564,16 @@ fn renderAsm(...@@ -2568,16 +2564,16 @@ fn renderAsm(
2568 switch (token_tags[tok_i + 1]) {2564 switch (token_tags[tok_i + 1]) {
2569 .r_paren => {2565 .r_paren => {
2570 ais.setIndentDelta(indent_delta);2566 ais.setIndentDelta(indent_delta);
2571 ais.popIndent();
2572 try renderToken(r, tok_i, .newline);2567 try renderToken(r, tok_i, .newline);
2568 ais.popIndent();
2573 return renderToken(r, tok_i + 1, space);2569 return renderToken(r, tok_i + 1, space);
2574 },2570 },
2575 .comma => {2571 .comma => {
2576 switch (token_tags[tok_i + 2]) {2572 switch (token_tags[tok_i + 2]) {
2577 .r_paren => {2573 .r_paren => {
2578 ais.setIndentDelta(indent_delta);2574 ais.setIndentDelta(indent_delta);
2579 ais.popIndent();
2580 try renderToken(r, tok_i, .newline);2575 try renderToken(r, tok_i, .newline);
2576 ais.popIndent();
2581 return renderToken(r, tok_i + 2, space);2577 return renderToken(r, tok_i + 2, space);
2582 },2578 },
2583 else => {2579 else => {
...@@ -2644,19 +2640,10 @@ fn renderParamList(...@@ -2644,19 +2640,10 @@ fn renderParamList(
2644 return renderToken(r, after_last_param_tok + 1, space); // )2640 return renderToken(r, after_last_param_tok + 1, space); // )
2645 }2641 }
26462642
2643 try ais.pushIndent(.normal);
2647 try renderToken(r, lparen, .none); // (2644 try renderToken(r, lparen, .none); // (
2648
2649 for (params, 0..) |param_node, i| {2645 for (params, 0..) |param_node, i| {
2650 const first_param_token = tree.firstToken(param_node);2646 try renderExpression(r, param_node, .none);
2651 if (token_tags[first_param_token] == .multiline_string_literal_line or
2652 hasSameLineComment(tree, first_param_token - 1))
2653 {
2654 try ais.pushIndent(.normal);
2655 try renderExpression(r, param_node, .none);
2656 ais.popIndent();
2657 } else {
2658 try renderExpression(r, param_node, .none);
2659 }
26602647
2661 if (i + 1 < params.len) {2648 if (i + 1 < params.len) {
2662 const comma = tree.lastToken(param_node) + 1;2649 const comma = tree.lastToken(param_node) + 1;
...@@ -2666,7 +2653,7 @@ fn renderParamList(...@@ -2666,7 +2653,7 @@ fn renderParamList(
2666 try renderToken(r, comma, comma_space);2653 try renderToken(r, comma, comma_space);
2667 }2654 }
2668 }2655 }
26692656 ais.popIndent();
2670 return renderToken(r, after_last_param_tok, space); // )2657 return renderToken(r, after_last_param_tok, space); // )
2671}2658}
26722659
...@@ -2741,6 +2728,16 @@ fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) Error!void...@@ -2741,6 +2728,16 @@ fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) Error!void
2741 try renderSpace(r, token_index, lexeme.len, space);2728 try renderSpace(r, token_index, lexeme.len, space);
2742}2729}
27432730
2731fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: Space, override_space: Space) Error!void {
2732 const tree = r.tree;
2733 const ais = r.ais;
2734 const lexeme = tokenSliceForRender(tree, token_index);
2735 try ais.writer().writeAll(lexeme);
2736 ais.enableSpaceMode(override_space);
2737 defer ais.disableSpaceMode();
2738 try renderSpace(r, token_index, lexeme.len, space);
2739}
2740
2744fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {2741fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2745 const tree = r.tree;2742 const tree = r.tree;
2746 const ais = r.ais;2743 const ais = r.ais;
...@@ -3315,6 +3312,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3315,6 +3312,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3315 normal,3312 normal,
3316 after_equals,3313 after_equals,
3317 binop,3314 binop,
3315 field_access,
3318 };3316 };
3319 const StackElem = struct {3317 const StackElem = struct {
3320 indent_type: IndentType,3318 indent_type: IndentType,
...@@ -3404,20 +3402,26 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3404,20 +3402,26 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3404 self.current_line_empty = true;3402 self.current_line_empty = true;
3405 if (self.disable_indent_committing > 0) return;3403 if (self.disable_indent_committing > 0) return;
3406 if (self.indent_stack.items.len > 0) {3404 if (self.indent_stack.items.len > 0) {
3407 // Only realize last pushed indent3405 var to_realize = self.indent_stack.items.len - 1;
3408 if (!self.indent_stack.items[self.indent_stack.items.len - 1].realized) {3406
3409 if (self.indent_stack.items.len >= 2 and3407 if (self.indent_stack.items.len >= 2 and
3410 self.indent_stack.items[self.indent_stack.items.len - 2].indent_type == .after_equals and3408 self.indent_stack.items[to_realize - 1].indent_type == .after_equals and
3411 self.indent_stack.items[self.indent_stack.items.len - 2].realized and3409 self.indent_stack.items[to_realize - 1].realized and
3412 self.indent_stack.items[self.indent_stack.items.len - 1].indent_type == .binop)3410 self.indent_stack.items[to_realize].indent_type == .binop)
3413 {3411 {
3414 // collapse one level of indentation in binop after equals sign3412 // collapse one level of indentation in binop after equals sign
3415 return;3413 return;
3416 }3414 }
34173415
3418 self.indent_stack.items[self.indent_stack.items.len - 1].realized = true;3416 if (self.indent_stack.items[to_realize].indent_type == .field_access) {
3419 self.indent_count += 1;3417 // only realize topmost field_access in a chain
3418 while (to_realize > 0 and self.indent_stack.items[to_realize - 1].indent_type == .field_access)
3419 to_realize -= 1;
3420 }3420 }
3421
3422 if (self.indent_stack.items[to_realize].realized) return;
3423 self.indent_stack.items[to_realize].realized = true;
3424 self.indent_count += 1;
3421 }3425 }
3422 }3426 }
34233427
...@@ -3441,10 +3445,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3441,10 +3445,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3441 pub fn enableSpaceMode(self: *Self, space: Space) void {3445 pub fn enableSpaceMode(self: *Self, space: Space) void {
3442 if (self.space_stack.items.len == 0) return;3446 if (self.space_stack.items.len == 0) return;
3443 const curr = self.space_stack.getLast();3447 const curr = self.space_stack.getLast();
3444 if (curr.space != space) {3448 if (curr.space != space) return;
3445 return;
3446 }
3447 assert(curr.space == space);
3448 self.space_mode = curr.indent_count;3449 self.space_mode = curr.indent_count;
3449 }3450 }
34503451
...@@ -3452,6 +3453,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3452,6 +3453,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3452 self.space_mode = null;3453 self.space_mode = null;
3453 }3454 }
34543455
3456 pub fn lastSpaceModeIndent(self: *Self) usize {
3457 if (self.space_stack.items.len == 0) return 0;
3458 return self.space_stack.getLast().indent_count * self.indent_delta;
3459 }
3460
3455 /// Insert a newline unless the current line is blank3461 /// Insert a newline unless the current line is blank
3456 pub fn maybeInsertNewline(self: *Self) WriteError!void {3462 pub fn maybeInsertNewline(self: *Self) WriteError!void {
3457 if (!self.current_line_empty)3463 if (!self.current_line_empty)
...@@ -3465,6 +3471,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {...@@ -3465,6 +3471,11 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
3465 try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false });3471 try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false });
3466 }3472 }
34673473
3474 pub fn forcePushIndent(self: *Self, indent_type: IndentType) !void {
3475 try self.indent_stack.append(.{ .indent_type = indent_type, .realized = true });
3476 self.indent_count += 1;
3477 }
3478
3468 pub fn popIndent(self: *Self) void {3479 pub fn popIndent(self: *Self) void {
3469 if (self.indent_stack.pop().realized) {3480 if (self.indent_stack.pop().realized) {
3470 assert(self.indent_count > 0);3481 assert(self.indent_count > 0);