diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-02-02 15:27:53 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-02 15:27:53 -0500 |
| commit | a795c36d7b299f8167fbeb8a650e7477b5390be8 (patch) | |
| tree | df67cfa147e0531ad23f15ea4a32a2ed0be37519 /lib/std | |
| parent | 32291ab70249c874e6941292de8611e619c838e5 (diff) | |
| parent | e548195fd5ddedb5b2d87ef4b396666917e6d9b6 (diff) | |
| download | zig-a795c36d7b299f8167fbeb8a650e7477b5390be8.tar.gz zig-a795c36d7b299f8167fbeb8a650e7477b5390be8.zip | |
Merge pull request #4352 from LemonBoy/fix-4349
fmt: Respect trailing commas in field declarations
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/c/parse.zig | 1 | ||||
| -rw-r--r-- | lib/std/c/tokenizer.zig | 2 | ||||
| -rw-r--r-- | lib/std/hash/benchmark.zig | 4 | ||||
| -rw-r--r-- | lib/std/os/uefi.zig | 3 | ||||
| -rw-r--r-- | lib/std/os/windows/bits.zig | 20 | ||||
| -rw-r--r-- | lib/std/zig/ast.zig | 11 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 37 | ||||
| -rw-r--r-- | lib/std/zig/perf_test.zig | 2 | ||||
| -rw-r--r-- | lib/std/zig/render.zig | 148 |
9 files changed, 155 insertions, 73 deletions
diff --git a/lib/std/c/parse.zig b/lib/std/c/parse.zig index dd646e06d6..4c6c2fb462 100644 --- a/lib/std/c/parse.zig +++ b/lib/std/c/parse.zig @@ -1428,4 +1428,3 @@ const Parser = struct { }); } }; - diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig index a641529502..bf8bb2b8c7 100644 --- a/lib/std/c/tokenizer.zig +++ b/lib/std/c/tokenizer.zig @@ -631,7 +631,7 @@ pub const Tokenizer = struct { }, .BackSlashCr => switch (c) { '\n' => { - state = .Start; + state = .Start; }, else => { result.id = .Invalid; diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index c792013e06..ed1bab9d87 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -250,13 +250,13 @@ pub fn main() !void { if (H.has_iterative_api) { prng.seed(seed); const result = try benchmarkHash(H, count); - try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", .{result.throughput / (1 * MiB), result.hash}); + try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash }); } if (!test_iterative_only) { prng.seed(seed); const result_small = try benchmarkHashSmallKeys(H, key_size, count); - try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", .{result_small.throughput / (1 * MiB), result_small.hash}); + try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", .{ result_small.throughput / (1 * MiB), result_small.hash }); } } } diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 1095706c97..81d13ac1c3 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -40,7 +40,8 @@ pub const Guid = extern struct { self.time_mid, self.time_high_and_version, self.clock_seq_high_and_reserved, - self.clock_seq_low, self.node, + self.clock_seq_low, + self.node, }); } else { @compileError("Unknown format character: '" ++ f ++ "'"); diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 2d95ae8416..265d3439e2 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -928,10 +928,7 @@ pub usingnamespace switch (builtin.arch) { SegSs: DWORD, ExtendedRegisters: [512]BYTE, - pub fn getRegs(ctx: *const CONTEXT) struct { - bp: usize, - ip: usize, - } { + pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } { return .{ .bp = ctx.Ebp, .ip = ctx.Eip }; } }; @@ -1034,10 +1031,7 @@ pub usingnamespace switch (builtin.arch) { LastExceptionToRip: DWORD64, LastExceptionFromRip: DWORD64, - pub fn getRegs(ctx: *const CONTEXT) struct { - bp: usize, - ip: usize, - } { + pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } { return .{ .bp = ctx.Rbp, .ip = ctx.Rip }; } }; @@ -1105,11 +1099,11 @@ pub usingnamespace switch (builtin.arch) { Wcr: [2]DWORD, Wvr: [2]DWORD64, - pub fn getRegs(ctx: *const CONTEXT) struct { - bp: usize, - ip: usize, - } { - return .{ .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, .ip = ctx.Pc }; + pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } { + return .{ + .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, + .ip = ctx.Pc, + }; } }; diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index e339343823..f34a6b3626 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -10,6 +10,7 @@ pub const TokenIndex = usize; pub const Tree = struct { source: []const u8, tokens: TokenList, + /// undefined on parse error (errors not empty) root_node: *Node.Root, arena_allocator: std.heap.ArenaAllocator, @@ -780,6 +781,11 @@ pub const Node = struct { i -= 1; } + if (self.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + if (self.value_expr) |value_expr| { if (i < 1) return value_expr; i -= 1; @@ -796,6 +802,11 @@ pub const Node = struct { if (self.value_expr) |value_expr| { return value_expr.lastToken(); } + if (self.align_expr) |align_expr| { + // The expression refers to what's inside the parenthesis, the + // last token is the closing one + return align_expr.lastToken() + 1; + } if (self.type_expr) |type_expr| { return type_expr.lastToken(); } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 4154bb6a7d..7b75aed28e 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,3 +1,23 @@ +test "zig fmt: trailing comma in container declaration" { + try testCanonical( + \\const X = struct { foo: i32 }; + \\const X = struct { foo: i32, bar: i32 }; + \\const X = struct { foo: i32 = 1, bar: i32 = 2 }; + \\const X = struct { foo: i32 align(4), bar: i32 align(4) }; + \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 }; + \\ + ); + try testTransform( + \\const X = struct { + \\ foo: i32, bar: i8 }; + , + \\const X = struct { + \\ foo: i32, bar: i8 + \\}; + \\ + ); +} + test "zig fmt: trailing comma in fn parameter list" { try testCanonical( \\pub fn f( @@ -727,10 +747,7 @@ test "zig fmt: enum decl with no trailing comma" { try testTransform( \\const StrLitKind = enum {Normal, C}; , - \\const StrLitKind = enum { - \\ Normal, - \\ C, - \\}; + \\const StrLitKind = enum { Normal, C }; \\ ); } @@ -984,16 +1001,10 @@ test "zig fmt: empty block with only comment" { } test "zig fmt: no trailing comma on struct decl" { - try testTransform( + try testCanonical( \\const RoundParam = struct { \\ k: usize, s: u32, t: u32 \\}; - , - \\const RoundParam = struct { - \\ k: usize, - \\ s: u32, - \\ t: u32, - \\}; \\ ); } @@ -2560,10 +2571,8 @@ test "zig fmt: if type expr" { ); } test "zig fmt: file ends with struct field" { - try testTransform( + try testCanonical( \\a: bool - , - \\a: bool, \\ ); } diff --git a/lib/std/zig/perf_test.zig b/lib/std/zig/perf_test.zig index fe9d35fa43..070d9c3bc9 100644 --- a/lib/std/zig/perf_test.zig +++ b/lib/std/zig/perf_test.zig @@ -25,7 +25,7 @@ pub fn main() !void { var stdout_file = std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; - try stdout.print("{:.3} MiB/s, {} KiB used \n", .{mb_per_sec, memory_used / 1024}); + try stdout.print("{:.3} MiB/s, {} KiB used \n", .{ mb_per_sec, memory_used / 1024 }); } fn testOnce() usize { diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 6c9e3e01a2..5fda700484 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -206,6 +206,10 @@ fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *as } fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node) (@TypeOf(stream).Child.Error || Error)!void { + try renderContainerDecl(allocator, stream, tree, indent, start_col, decl, .Newline); +} + +fn renderContainerDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node, space: Space) (@TypeOf(stream).Child.Error || Error)!void { switch (decl.id) { .FnProto => { const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); @@ -213,11 +217,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i try renderDocComments(tree, stream, fn_proto, indent, start_col); if (fn_proto.body_node) |body_node| { - try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space); - try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, .Space); + try renderExpression(allocator, stream, tree, indent, start_col, body_node, space); } else { - try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None); - try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, .None); + try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, space); } }, @@ -225,11 +229,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); if (use_decl.visib_token) |visib_token| { - try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub + try renderToken(tree, stream, visib_token, indent, start_col, .Space); // pub } - try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // usingnamespace - try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None); - try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ; + try renderToken(tree, stream, use_decl.use_token, indent, start_col, .Space); // usingnamespace + try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, .None); + try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, space); // ; }, .VarDecl => { @@ -243,9 +247,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); try renderDocComments(tree, stream, test_decl, indent, start_col); - try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space); - try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space); - try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline); + try renderToken(tree, stream, test_decl.test_token, indent, start_col, .Space); + try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, .Space); + try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, space); }, .ContainerField => { @@ -253,62 +257,76 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i try renderDocComments(tree, stream, field, indent, start_col); if (field.comptime_token) |t| { - try renderToken(tree, stream, t, indent, start_col, Space.Space); // comptime + try renderToken(tree, stream, t, indent, start_col, .Space); // comptime } + const src_has_trailing_comma = blk: { + const maybe_comma = tree.nextToken(field.lastToken()); + break :blk tree.tokens.at(maybe_comma).id == .Comma; + }; + + // The trailing comma is emitted at the end, but if it's not present + // we still have to respect the specified `space` parameter + const last_token_space: Space = if (src_has_trailing_comma) .None else space; + if (field.type_expr == null and field.value_expr == null) { - return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name, + try renderToken(tree, stream, field.name_token, indent, start_col, last_token_space); // name } else if (field.type_expr != null and field.value_expr == null) { - try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name - try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // : + try renderToken(tree, stream, field.name_token, indent, start_col, .None); // name + try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // : if (field.align_expr) |align_value_expr| { - try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type + try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type const lparen_token = tree.prevToken(align_value_expr.firstToken()); const align_kw = tree.prevToken(lparen_token); const rparen_token = tree.nextToken(align_value_expr.lastToken()); - try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align - try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment - try renderToken(tree, stream, rparen_token, indent, start_col, Space.Comma); // ), + try renderToken(tree, stream, align_kw, indent, start_col, .None); // align + try renderToken(tree, stream, lparen_token, indent, start_col, .None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, .None); // alignment + try renderToken(tree, stream, rparen_token, indent, start_col, last_token_space); // ) } else { - try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type, + try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, last_token_space); // type } } else if (field.type_expr == null and field.value_expr != null) { - try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name - try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // = - return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value + try renderToken(tree, stream, field.name_token, indent, start_col, .Space); // name + try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // = + try renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, last_token_space); // value } else { - try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name - try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // : + try renderToken(tree, stream, field.name_token, indent, start_col, .None); // name + try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // : if (field.align_expr) |align_value_expr| { - try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type + try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type const lparen_token = tree.prevToken(align_value_expr.firstToken()); const align_kw = tree.prevToken(lparen_token); const rparen_token = tree.nextToken(align_value_expr.lastToken()); - try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align - try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // ( - try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment - try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // ) + try renderToken(tree, stream, align_kw, indent, start_col, .None); // align + try renderToken(tree, stream, lparen_token, indent, start_col, .None); // ( + try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, .None); // alignment + try renderToken(tree, stream, rparen_token, indent, start_col, .Space); // ) } else { - try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type + try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type } - try renderToken(tree, stream, tree.prevToken(field.value_expr.?.firstToken()), indent, start_col, Space.Space); // = - return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value, + try renderToken(tree, stream, tree.prevToken(field.value_expr.?.firstToken()), indent, start_col, .Space); // = + try renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, last_token_space); // value + } + + if (src_has_trailing_comma) { + const comma = tree.nextToken(field.lastToken()); + try renderToken(tree, stream, comma, indent, start_col, space); } }, .Comptime => { assert(!decl.requireSemiColon()); - try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline); + try renderExpression(allocator, stream, tree, indent, start_col, decl, space); }, .DocComment => { const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl); var it = comment.lines.iterator(0); while (it.next()) |line_token_index| { - try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline); + try renderToken(tree, stream, line_token_index.*, indent, start_col, .Newline); if (it.peek()) |_| { try stream.writeByteNTimes(' ', indent); } @@ -1150,14 +1168,42 @@ fn renderExpression( if (container_decl.fields_and_decls.len == 0) { try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // { return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // } - } else { + } + + const src_has_trailing_comma = blk: { + var maybe_comma = tree.prevToken(container_decl.lastToken()); + // Doc comments for a field may also appear after the comma, eg. + // field_name: T, // comment attached to field_name + if (tree.tokens.at(maybe_comma).id == .DocComment) + maybe_comma = tree.prevToken(maybe_comma); + break :blk tree.tokens.at(maybe_comma).id == .Comma; + }; + + // Check if the first declaration and the { are on the same line + const src_has_newline = !tree.tokensOnSameLine( + container_decl.lbrace_token, + container_decl.fields_and_decls.at(0).*.firstToken(), + ); + + // We can only print all the elements in-line if all the + // declarations inside are fields + const src_has_only_fields = blk: { + var it = container_decl.fields_and_decls.iterator(0); + while (it.next()) |decl| { + if (decl.*.id != .ContainerField) break :blk false; + } + break :blk true; + }; + + if (src_has_trailing_comma or !src_has_only_fields) { + // One declaration per line const new_indent = indent + indent_delta; - try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, Space.Newline); // { + try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, .Newline); // { var it = container_decl.fields_and_decls.iterator(0); while (it.next()) |decl| { try stream.writeByteNTimes(' ', new_indent); - try renderTopLevelDecl(allocator, stream, tree, new_indent, start_col, decl.*); + try renderContainerDecl(allocator, stream, tree, new_indent, start_col, decl.*, .Newline); if (it.peek()) |next_decl| { try renderExtraNewline(tree, stream, start_col, next_decl.*); @@ -1165,8 +1211,30 @@ fn renderExpression( } try stream.writeByteNTimes(' ', indent); - return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // } + } else if (src_has_newline) { + // All the declarations on the same line, but place the items on + // their own line + try renderToken(tree, stream, container_decl.lbrace_token, indent, start_col, .Newline); // { + + const new_indent = indent + indent_delta; + try stream.writeByteNTimes(' ', new_indent); + + var it = container_decl.fields_and_decls.iterator(0); + while (it.next()) |decl| { + const space_after_decl: Space = if (it.peek() == null) .Newline else .Space; + try renderContainerDecl(allocator, stream, tree, new_indent, start_col, decl.*, space_after_decl); + } + } else { + // All the declarations on the same line + try renderToken(tree, stream, container_decl.lbrace_token, indent, start_col, .Space); // { + + var it = container_decl.fields_and_decls.iterator(0); + while (it.next()) |decl| { + try renderContainerDecl(allocator, stream, tree, indent, start_col, decl.*, .Space); + } } + + return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // } }, .ErrorSetDecl => { |
