authorgravatar for 178735591+87flowers@users.noreply.github.com87flowers <178735591+87flowers@users.noreply.github.com> 2024-10-16 20:14:46+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-22 17:09:20-08:00
log9b2677c639da2ea9b54c778bb4543abfc8595de9
tree4f07a8ea0d6da78452bfa378907dffe041872670
parentec3e4cc14b004496d8d2ab0d15d03c0c22c3d95c

std/zig/render: Implement space mode to fix comment indentation


1 files changed, 89 insertions(+), 7 deletions(-)

lib/std/zig/render.zig+89-7
......@@ -295,7 +295,11 @@ fn renderMember(
295295 .local_var_decl,
296296 .simple_var_decl,
297297 .aligned_var_decl,
298 => return renderVarDecl(r, tree.fullVarDecl(decl).?, false, .semicolon),
298 => {
299 try ais.pushSpace(.semicolon);
300 try renderVarDecl(r, tree.fullVarDecl(decl).?, false, .semicolon);
301 ais.popSpace();
302 },
299303
300304 .test_decl => {
301305 const test_token = main_tokens[decl];
......@@ -372,8 +376,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
372376
373377 switch (space) {
374378 .none, .space, .newline, .skip => {},
375 .semicolon => if (token_tags[i] == .semicolon) try renderToken(r, i, .newline),
376 .comma => if (token_tags[i] == .comma) try renderToken(r, i, .newline),
379 .semicolon => if (token_tags[i] == .semicolon) {
380 ais.enableSpaceMode(.semicolon);
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 },
377389 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),
378390 }
379391 },
......@@ -764,7 +776,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
764776 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
765777 switch (token_tags[i]) {
766778 .doc_comment => try renderToken(r, i, .newline),
767 .identifier => try renderIdentifier(r, i, .comma, .eagerly_unquote),
779 .identifier => {
780 try ais.pushSpace(.comma);
781 try renderIdentifier(r, i, .comma, .eagerly_unquote);
782 ais.popSpace();
783 },
768784 .comma => {},
769785 else => unreachable,
770786 }
......@@ -843,7 +859,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
843859 try renderToken(r, rparen + 1, .none); // {
844860 } else {
845861 try renderToken(r, rparen + 1, .newline); // {
862 try ais.pushSpace(.comma);
846863 try renderExpressions(r, full.ast.cases, .comma);
864 ais.popSpace();
847865 }
848866 ais.popIndent();
849867 return renderToken(r, tree.lastToken(node), space); // }
......@@ -1625,7 +1643,9 @@ fn renderBuiltinCall(
16251643 try renderToken(r, builtin_token + 1, Space.newline); // (
16261644
16271645 for (params) |param_node| {
1646 try ais.pushSpace(.comma);
16281647 try renderExpression(r, param_node, .comma);
1648 ais.popSpace();
16291649 }
16301650 ais.popIndent();
16311651
......@@ -1793,7 +1813,9 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17931813 }
17941814 const param = fn_proto.ast.params[param_i];
17951815 param_i += 1;
1816 try ais.pushSpace(.comma);
17961817 try renderExpression(r, param, .comma);
1818 ais.popSpace();
17971819 last_param_token = tree.lastToken(param);
17981820 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;
17991821 }
......@@ -1856,6 +1878,7 @@ fn renderSwitchCase(
18561878 switch_case: Ast.full.SwitchCase,
18571879 space: Space,
18581880) Error!void {
1881 const ais = r.ais;
18591882 const tree = r.tree;
18601883 const node_tags = tree.nodes.items(.tag);
18611884 const token_tags = tree.tokens.items(.tag);
......@@ -1875,7 +1898,9 @@ fn renderSwitchCase(
18751898 try renderToken(r, switch_case.ast.arrow_token - 1, .space); // else keyword
18761899 } else if (trailing_comma or has_comment_before_arrow) {
18771900 // Render each value on a new line
1901 try ais.pushSpace(.comma);
18781902 try renderExpressions(r, switch_case.ast.values, .comma);
1903 ais.popSpace();
18791904 } else {
18801905 // Render on one line
18811906 for (switch_case.ast.values) |value_expr| {
......@@ -1951,6 +1976,7 @@ fn finishRenderBlock(
19511976 for (statements, 0..) |stmt, i| {
19521977 if (i != 0) try renderExtraNewline(r, stmt);
19531978 if (r.fixups.omit_nodes.contains(stmt)) continue;
1979 try ais.pushSpace(.semicolon);
19541980 switch (node_tags[stmt]) {
19551981 .global_var_decl,
19561982 .local_var_decl,
......@@ -1960,6 +1986,7 @@ fn finishRenderBlock(
19601986
19611987 else => try renderExpression(r, stmt, .semicolon),
19621988 }
1989 ais.popSpace();
19631990 }
19641991 ais.popIndent();
19651992
......@@ -2003,7 +2030,10 @@ fn renderStructInit(
20032030 const expr = nodes[field_node];
20042031 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
20052032 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
2033
2034 try ais.pushSpace(.comma);
20062035 try renderExpressionFixup(r, field_node, .comma);
2036 ais.popSpace();
20072037
20082038 for (struct_init.ast.fields[1..]) |field_init| {
20092039 const init_token = tree.firstToken(field_init);
......@@ -2012,7 +2042,10 @@ fn renderStructInit(
20122042 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
20132043 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;
20142044 try renderToken(r, init_token - 1, space_after_equal); // =
2045
2046 try ais.pushSpace(.comma);
20152047 try renderExpressionFixup(r, field_init, .comma);
2048 ais.popSpace();
20162049 }
20172050
20182051 ais.popIndent();
......@@ -2182,7 +2215,10 @@ fn renderArrayInit(
21822215 column_counter = 0;
21832216 }
21842217 } else {
2218 try ais.pushSpace(.comma);
21852219 try renderExpression(&sub_render, expr, .comma);
2220 ais.popSpace();
2221
21862222 const width = sub_expr_buffer.items.len - start - 2;
21872223 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;
21882224 contains_newline = contains_newline or this_contains_newline;
......@@ -2362,7 +2398,11 @@ fn renderContainerDecl(
23622398 .container_field_init,
23632399 .container_field_align,
23642400 .container_field,
2365 => try renderMember(r, container, member, .comma),
2401 => {
2402 try ais.pushSpace(.comma);
2403 try renderMember(r, container, member, .comma);
2404 ais.popSpace();
2405 },
23662406
23672407 else => try renderMember(r, container, member, .newline),
23682408 }
......@@ -2450,13 +2490,17 @@ fn renderAsm(
24502490 try renderToken(r, comma, .newline); // ,
24512491 try renderExtraNewlineToken(r, tree.firstToken(next_asm_output));
24522492 } else if (asm_node.inputs.len == 0 and asm_node.first_clobber == null) {
2493 try ais.pushSpace(.comma);
24532494 try renderAsmOutput(r, asm_output, .comma);
2495 ais.popSpace();
24542496 ais.popIndent();
24552497 ais.setIndentDelta(indent_delta);
24562498 ais.popIndent();
24572499 return renderToken(r, asm_node.ast.rparen, space); // rparen
24582500 } else {
2501 try ais.pushSpace(.comma);
24592502 try renderAsmOutput(r, asm_output, .comma);
2503 ais.popSpace();
24602504 const comma_or_colon = tree.lastToken(asm_output) + 1;
24612505 ais.popIndent();
24622506 break :colon2 switch (token_tags[comma_or_colon]) {
......@@ -2482,13 +2526,17 @@ fn renderAsm(
24822526 try renderToken(r, first_token - 1, .newline); // ,
24832527 try renderExtraNewlineToken(r, first_token);
24842528 } else if (asm_node.first_clobber == null) {
2529 try ais.pushSpace(.comma);
24852530 try renderAsmInput(r, asm_input, .comma);
2531 ais.popSpace();
24862532 ais.popIndent();
24872533 ais.setIndentDelta(indent_delta);
24882534 ais.popIndent();
24892535 return renderToken(r, asm_node.ast.rparen, space); // rparen
24902536 } else {
2537 try ais.pushSpace(.comma);
24912538 try renderAsmInput(r, asm_input, .comma);
2539 ais.popSpace();
24922540 const comma_or_colon = tree.lastToken(asm_input) + 1;
24932541 ais.popIndent();
24942542 break :colon3 switch (token_tags[comma_or_colon]) {
......@@ -2574,7 +2622,9 @@ fn renderParamList(
25742622
25752623 try renderExtraNewline(r, params[i + 1]);
25762624 } else {
2625 try ais.pushSpace(.comma);
25772626 try renderExpression(r, param_node, .comma);
2627 ais.popSpace();
25782628 }
25792629 }
25802630 ais.popIndent();
......@@ -2691,7 +2741,8 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
26912741 if (space == .comma and token_tags[token_index + 1] != .comma) {
26922742 try ais.writer().writeByte(',');
26932743 }
2694
2744 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
2745 defer ais.disableSpaceMode();
26952746 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);
26962747 switch (space) {
26972748 .none => {},
......@@ -3254,6 +3305,10 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
32543305 indent_type: IndentType,
32553306 realized: bool,
32563307 };
3308 const SpaceElem = struct {
3309 space: Space,
3310 indent_count: usize,
3311 };
32573312
32583313 underlying_writer: UnderlyingWriter,
32593314
......@@ -3268,6 +3323,8 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
32683323 indent_count: usize = 0,
32693324 indent_delta: usize,
32703325 indent_stack: std.ArrayList(StackElem),
3326 space_stack: std.ArrayList(SpaceElem),
3327 space_mode: ?usize = null,
32713328 disable_indent_committing: usize = 0,
32723329 current_line_empty: bool = true,
32733330 /// the most recently applied indent
......@@ -3278,11 +3335,13 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
32783335 .underlying_writer = buffer.writer(),
32793336 .indent_delta = indent_delta_,
32803337 .indent_stack = std.ArrayList(StackElem).init(buffer.allocator),
3338 .space_stack = std.ArrayList(SpaceElem).init(buffer.allocator),
32813339 };
32823340 }
32833341
32843342 pub fn deinit(self: *Self) void {
32853343 self.indent_stack.deinit();
3344 self.space_stack.deinit();
32863345 }
32873346
32883347 pub fn writer(self: *Self) Writer {
......@@ -3347,6 +3406,28 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
33473406 self.disable_indent_committing -= 1;
33483407 }
33493408
3409 pub fn pushSpace(self: *Self, space: Space) !void {
3410 try self.space_stack.append(.{ .space = space, .indent_count = self.indent_count });
3411 }
3412
3413 pub fn popSpace(self: *Self) void {
3414 _ = self.space_stack.pop();
3415 }
3416
3417 pub fn enableSpaceMode(self: *Self, space: Space) void {
3418 if (self.space_stack.items.len == 0) return;
3419 const curr = self.space_stack.getLast();
3420 if (curr.space != space) {
3421 return;
3422 }
3423 assert(curr.space == space);
3424 self.space_mode = curr.indent_count;
3425 }
3426
3427 pub fn disableSpaceMode(self: *Self) void {
3428 self.space_mode = null;
3429 }
3430
33503431 /// Insert a newline unless the current line is blank
33513432 pub fn maybeInsertNewline(self: *Self) WriteError!void {
33523433 if (!self.current_line_empty)
......@@ -3390,7 +3471,8 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
33903471 }
33913472
33923473 fn currentIndent(self: *Self) usize {
3393 return self.indent_count * self.indent_delta;
3474 const indent_count = self.space_mode orelse self.indent_count;
3475 return indent_count * self.indent_delta;
33943476 }
33953477 };
33963478}