zig fmt: fix comment indent after multiline single statement if/while/for

This commit is contained in:
Isaac Freund 2021-02-24 13:46:11 +01:00
parent 15c7c6ab97
commit 371b21bdfb
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 91 additions and 35 deletions

View File

@ -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(

View File

@ -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,33 +2224,65 @@ 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) {
try ais.insertNewline();
},
.comma_space => if (token_tags[token_index + 1] == .comma) {
try renderToken(ais, tree, token_index + 1, .space);
} else if (!comment) {
.space => if (!try renderComments(ais, tree, token_end, next_token_start)) {
try ais.writer().writeByte(' ');
},
.semicolon => if (token_tags[token_index + 1] == .semicolon) {
try renderToken(ais, tree, token_index + 1, .newline);
} else if (!comment) {
.newline => if (!try renderComments(ais, tree, token_end, next_token_start)) {
try ais.insertNewline();
},
.newline_pop => {
ais.popIndent();
if (!try renderComments(ais, tree, token_end, next_token_start)) {
try ais.insertNewline();
}
},
.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 {
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();
}
}
},
}
}