From 371b21bdfbfa8917b44e809fb8a041411ffc6b8a Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 24 Feb 2021 13:46:11 +0100 Subject: zig fmt: fix comment indent after multiline single statement if/while/for --- lib/std/zig/parser_test.zig | 42 ++++++++++++++++-------- lib/std/zig/render.zig | 80 +++++++++++++++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 5ac0d62026..a74a002385 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -4164,19 +4164,35 @@ test "zig fmt: for loop with ptr payload and index" { ); } -// TODO -//test "zig fmt: proper indent line comment after multi-line single expr while loop" { -// try testCanonical( -// \\test { -// \\ while (a) : (b) -// \\ foo(); -// \\ -// \\ // bar -// \\ baz(); -// \\} -// \\ -// ); -//} +test "zig fmt: proper indent line comment after multi-line single expr while loop" { + try testCanonical( + \\test { + \\ while (a) : (b) + \\ foo(); + \\ + \\ // bar + \\ baz(); + \\} + \\ + ); +} + +test "zig fmt: line comment after multiline single expr if statement with multiline string" { + try testCanonical( + \\test { + \\ if (foo) + \\ x = + \\ \\hello + \\ \\hello + \\ \\ + \\ ; + \\ + \\ // bar + \\ baz(); + \\} + \\ + ); +} test "zig fmt: respect extra newline between fn and pub usingnamespace" { try testCanonical( diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 604ee4f312..e93881edc0 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -203,7 +203,9 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I switch (space) { .none, .space, .newline => {}, + .newline_pop => ais.popIndent(), .semicolon => if (token_tags[i] == .semicolon) try renderToken(ais, tree, i, .newline), + .semicolon_pop => if (token_tags[i] == .semicolon) try renderToken(ais, tree, i, .newline_pop), .comma => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .newline), .comma_space => if (token_tags[i] == .comma) try renderToken(ais, tree, i, .space), } @@ -1152,8 +1154,8 @@ fn renderWhile(gpa: *Allocator, ais: *Ais, tree: ast.Tree, while_node: ast.full. } } else { ais.pushIndent(); - try renderExpression(gpa, ais, tree, while_node.ast.then_expr, space); - ais.popIndent(); + assert(space == .semicolon); + try renderExpression(gpa, ais, tree, while_node.ast.then_expr, .semicolon_pop); return; } } @@ -2196,6 +2198,9 @@ const Space = enum { space, /// Output the token lexeme followed by a newline. newline, + /// Same as newline, but pop an indent level before rendering the + /// following comments if any. + newline_pop, /// If the next token is a comma, render it as well. If not, insert one. /// In either case, a newline will be inserted afterwards. comma, @@ -2205,6 +2210,9 @@ const Space = enum { /// Additionally consume the next token if it is a semicolon. /// In either case, a newline will be inserted afterwards. semicolon, + /// Same as semicolon, but pop an indent level before rendering the + /// following comments if any. + semicolon_pop, }; fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Space) Error!void { @@ -2216,32 +2224,64 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp try ais.writer().writeAll(lexeme); - if (space == .comma and token_tags[token_index + 1] != .comma) { - try ais.writer().writeByte(','); - } - - const comment = try renderComments(ais, tree, token_start + lexeme.len, token_starts[token_index + 1]); + const token_end = token_start + lexeme.len; + const next_token_start = token_starts[token_index + 1]; switch (space) { - .none => {}, - .space => if (!comment) try ais.writer().writeByte(' '), - .newline => if (!comment) try ais.insertNewline(), + .none => _ = try renderComments(ais, tree, token_end, next_token_start), - .comma => if (token_tags[token_index + 1] == .comma) { - try renderToken(ais, tree, token_index + 1, .newline); - } else if (!comment) { + .space => if (!try renderComments(ais, tree, token_end, next_token_start)) { + try ais.writer().writeByte(' '); + }, + + .newline => if (!try renderComments(ais, tree, token_end, next_token_start)) { try ais.insertNewline(); }, - .comma_space => if (token_tags[token_index + 1] == .comma) { - try renderToken(ais, tree, token_index + 1, .space); - } else if (!comment) { - try ais.writer().writeByte(' '); + .newline_pop => { + ais.popIndent(); + if (!try renderComments(ais, tree, token_end, next_token_start)) { + try ais.insertNewline(); + } }, - .semicolon => if (token_tags[token_index + 1] == .semicolon) { + .comma => if (token_tags[token_index + 1] == .comma) { + _ = try renderComments(ais, tree, token_end, next_token_start); try renderToken(ais, tree, token_index + 1, .newline); - } else if (!comment) { - try ais.insertNewline(); + } else { + try ais.writer().writeByte(','); + if (!try renderComments(ais, tree, token_end, next_token_start)) { + try ais.insertNewline(); + } + }, + + .comma_space => { + const comment = try renderComments(ais, tree, token_end, next_token_start); + if (token_tags[token_index + 1] == .comma) { + try renderToken(ais, tree, token_index + 1, .space); + } else if (!comment) { + try ais.writer().writeByte(' '); + } + }, + + .semicolon => { + const comment = try renderComments(ais, tree, token_end, next_token_start); + if (token_tags[token_index + 1] == .semicolon) { + try renderToken(ais, tree, token_index + 1, .newline); + } else if (!comment) { + try ais.insertNewline(); + } + }, + + .semicolon_pop => { + if (token_tags[token_index + 1] == .semicolon) { + _ = try renderComments(ais, tree, token_end, next_token_start); + try renderToken(ais, tree, token_index + 1, .newline_pop); + } else { + ais.popIndent(); + if (!try renderComments(ais, tree, token_end, next_token_start)) { + try ais.insertNewline(); + } + } }, } } -- cgit v1.2.3