Skip to content

Commit

Permalink
zig fmt: support array literal row size hint
Browse files Browse the repository at this point in the history
See #1003
  • Loading branch information
andrewrk committed May 27, 2018
1 parent 349365d commit 118d41e
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 8 deletions.
8 changes: 8 additions & 0 deletions std/mem.zig
Expand Up @@ -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);
Expand Down
59 changes: 59 additions & 0 deletions 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 {
Expand Down
108 changes: 100 additions & 8 deletions std/zig/render.zig
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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");
},
}
}

0 comments on commit 118d41e

Please sign in to comment.