Commit 118d41ef83
Changed files (3)
std/zig/parser_test.zig
@@ -1,3 +1,62 @@
+test "zig fmt: array literal with hint" {
+ try testTransform(
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3,
+ \\ 4,
+ \\ 5,
+ \\ 6,
+ \\ 7 };
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3,
+ \\ 4,
+ \\ 5,
+ \\ 6,
+ \\ 7, 8 };
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3,
+ \\ 4,
+ \\ 5,
+ \\ 6, // blah
+ \\ 7, 8 };
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3, //
+ \\ 4,
+ \\ 5,
+ \\ 6,
+ \\ 7 };
+ ,
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3, 4, //
+ \\ 5, 6, //
+ \\ 7,
+ \\};
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3, 4, //
+ \\ 5, 6, //
+ \\ 7, 8, //
+ \\};
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3, 4, //
+ \\ 5, 6, // blah
+ \\ 7, 8, //
+ \\};
+ \\const a = []u8{
+ \\ 1, 2, //
+ \\ 3, 4, //
+ \\ 5, 6, //
+ \\ 7,
+ \\};
+ \\
+ );
+}
+
test "zig fmt: multiline string with backslash at end of line" {
try testCanonical(
\\comptime {
std/zig/render.zig
@@ -19,7 +19,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
var tok_it = tree.tokens.iterator(0);
while (tok_it.next()) |token| {
if (token.id != Token.Id.LineComment) break;
- try stream.print("{}\n", tree.tokenSlicePtr(token));
+ try stream.print("{}\n", mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
if (tok_it.peek()) |next_token| {
const loc = tree.tokenLocationPtr(token.end, next_token);
if (loc.line >= 2) {
@@ -532,12 +532,73 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
+ // scan to find row size
+ const maybe_row_size: ?usize = blk: {
+ var count: usize = 0;
+ var it = exprs.iterator(0);
+ var prev_token = (??it.peek()).*.lastToken() + 1;
+ while (it.next()) |expr| {
+ const expr_last_token = expr.*.lastToken() + 1;
+ const next_token = tree.tokens.at(expr_last_token + 1);
+ const loc = tree.tokenLocationPtr(tree.tokens.at(prev_token).end, next_token);
+ if (loc.line != 0) break :blk null;
+ if (next_token.id == Token.Id.LineComment) {
+ const trimmed = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ");
+ if (trimmed.len == 2) {
+ break :blk count;
+ } else {
+ break :blk null;
+ }
+ }
+ prev_token = expr_last_token;
+ count += 1;
+ }
+ break :blk null;
+ };
+
+
const new_indent = indent + indent_delta;
try renderToken(tree, stream, lbrace, new_indent, Space.Newline);
+ try stream.writeByteNTimes(' ', new_indent);
+
+ if (maybe_row_size) |row_size| {
+ var it = exprs.iterator(0);
+ var i: usize = 0;
+ while (it.next()) |expr| {
+ if (it.peek()) |next_expr| {
+ try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
+
+ const comma = tree.nextToken(expr.*.lastToken());
+
+ if (i != row_size) {
+ try renderToken(tree, stream, comma, new_indent, Space.IgnoreEmptyComment); // ,
+ i += 1;
+ continue;
+ }
+ i = 0;
+
+ try renderToken(tree, stream, comma, new_indent, Space.NoIndent); // ,
+
+ const next_token = tree.tokens.at(comma + 1);
+ if (next_token.id != Token.Id.LineComment) {
+ try stream.print(" //\n");
+ }
+
+ try renderExtraNewline(tree, stream, next_expr.*);
+ try stream.writeByteNTimes(' ', new_indent);
+ } else if (i == row_size) {
+ try renderTrailingCommaAndEmptyComment(allocator, stream, tree, new_indent, expr.*); // , //
+ } else {
+ try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline); // ,
+ }
+ }
+ try stream.writeByteNTimes(' ', indent);
+ try renderToken(tree, stream, suffix_op.rtoken, indent, space);
+ return;
+ }
var it = exprs.iterator(0);
while (it.next()) |expr| {
- try stream.writeByteNTimes(' ', new_indent);
if (it.peek()) |next_expr| {
try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
@@ -546,6 +607,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
try renderExtraNewline(tree, stream, next_expr.*);
+ try stream.writeByteNTimes(' ', new_indent);
} else {
try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline);
}
@@ -1496,11 +1558,12 @@ const Space = enum {
NoNewline,
NoIndent,
NoComment,
+ IgnoreEmptyComment,
};
fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {
var token = tree.tokens.at(token_index);
- try stream.write(tree.tokenSlicePtr(token));
+ try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(token), " "));
if (space == Space.NoComment) return;
@@ -1515,15 +1578,19 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
return stream.write("\n");
}
},
- Space.Space => return stream.writeByte(' '),
+ Space.Space, Space.IgnoreEmptyComment => return stream.writeByte(' '),
Space.NoComment => unreachable,
}
}
+ if (space == Space.IgnoreEmptyComment and mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2) {
+ return stream.writeByte(' ');
+ }
+
var loc = tree.tokenLocationPtr(token.end, next_token);
var offset: usize = 1;
if (loc.line == 0) {
- try stream.print(" {}", tree.tokenSlicePtr(next_token));
+ try stream.print(" {}", mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
offset = 2;
token = next_token;
next_token = tree.tokens.at(token_index + offset);
@@ -1546,7 +1613,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
}
},
Space.NoNewline => {},
- Space.NoComment => unreachable,
+ Space.NoComment, Space.IgnoreEmptyComment => unreachable,
}
return;
}
@@ -1558,7 +1625,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
const newline_count = if (loc.line == 1) u8(1) else u8(2);
try stream.writeByteNTimes('\n', newline_count);
try stream.writeByteNTimes(' ', indent);
- try stream.write(tree.tokenSlicePtr(next_token));
+ try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
offset += 1;
token = next_token;
@@ -1583,7 +1650,7 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
try stream.writeByteNTimes(' ', next_line_indent);
},
Space.NoNewline => {},
- Space.NoComment => unreachable,
+ Space.NoComment, Space.IgnoreEmptyComment => unreachable,
}
return;
}
@@ -1621,3 +1688,28 @@ fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree,
},
}
}
+
+fn renderTrailingCommaAndEmptyComment(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void
+{
+ const end_token = base.lastToken() + 1;
+ switch (tree.tokens.at(end_token).id) {
+ Token.Id.Comma => {
+ try renderExpression(allocator, stream, tree, indent, base, Space.None);
+ try renderToken(tree, stream, end_token, indent, Space.Space); // ,
+
+ const next_token = tree.tokens.at(end_token + 1);
+ if (next_token.id != Token.Id.LineComment) {
+ try stream.print("//\n");
+ }
+ },
+ Token.Id.LineComment => {
+ try renderExpression(allocator, stream, tree, indent, base, Space.NoComment);
+ try stream.write(", ");
+ try renderToken(tree, stream, end_token, indent, Space.Newline);
+ },
+ else => {
+ try renderExpression(allocator, stream, tree, indent, base, Space.None);
+ try stream.write(", //\n");
+ },
+ }
+}
std/mem.zig
@@ -177,6 +177,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
return true;
}
+/// Returns true if all elements in a slice are equal to the scalar value provided
+pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
+ for (slice) |item| {
+ if (item != scalar) return false;
+ }
+ return true;
+}
+
/// Copies ::m to newly allocated memory. Caller is responsible to free it.
pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T {
const new_buf = try allocator.alloc(T, m.len);