authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-02 15:27:53-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-02-02 15:27:53-05:00
loga795c36d7b299f8167fbeb8a650e7477b5390be8
treedf67cfa147e0531ad23f15ea4a32a2ed0be37519
parent32291ab70249c874e6941292de8611e619c838e5
parente548195fd5ddedb5b2d87ef4b396666917e6d9b6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4352 from LemonBoy/fix-4349

fmt: Respect trailing commas in field declarations

11 files changed, 157 insertions(+), 75 deletions(-)

lib/std/c/parse.zig-1
...@@ -1428,4 +1428,3 @@ const Parser = struct {...@@ -1428,4 +1428,3 @@ const Parser = struct {
1428 });1428 });
1429 }1429 }
1430};1430};
1431
lib/std/c/tokenizer.zig+1-1
...@@ -631,7 +631,7 @@ pub const Tokenizer = struct {...@@ -631,7 +631,7 @@ pub const Tokenizer = struct {
631 },631 },
632 .BackSlashCr => switch (c) {632 .BackSlashCr => switch (c) {
633 '\n' => {633 '\n' => {
634 state = .Start;634 state = .Start;
635 },635 },
636 else => {636 else => {
637 result.id = .Invalid;637 result.id = .Invalid;
lib/std/hash/benchmark.zig+2-2
...@@ -250,13 +250,13 @@ pub fn main() !void {...@@ -250,13 +250,13 @@ pub fn main() !void {
250 if (H.has_iterative_api) {250 if (H.has_iterative_api) {
251 prng.seed(seed);251 prng.seed(seed);
252 const result = try benchmarkHash(H, count);252 const result = try benchmarkHash(H, count);
253 try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", .{result.throughput / (1 * MiB), result.hash});253 try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });
254 }254 }
255255
256 if (!test_iterative_only) {256 if (!test_iterative_only) {
257 prng.seed(seed);257 prng.seed(seed);
258 const result_small = try benchmarkHashSmallKeys(H, key_size, count);258 const result_small = try benchmarkHashSmallKeys(H, key_size, count);
259 try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", .{result_small.throughput / (1 * MiB), result_small.hash});259 try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", .{ result_small.throughput / (1 * MiB), result_small.hash });
260 }260 }
261 }261 }
262 }262 }
lib/std/os/uefi.zig+2-1
...@@ -40,7 +40,8 @@ pub const Guid = extern struct {...@@ -40,7 +40,8 @@ pub const Guid = extern struct {
40 self.time_mid,40 self.time_mid,
41 self.time_high_and_version,41 self.time_high_and_version,
42 self.clock_seq_high_and_reserved,42 self.clock_seq_high_and_reserved,
43 self.clock_seq_low, self.node,43 self.clock_seq_low,
44 self.node,
44 });45 });
45 } else {46 } else {
46 @compileError("Unknown format character: '" ++ f ++ "'");47 @compileError("Unknown format character: '" ++ f ++ "'");
lib/std/os/windows/bits.zig+7-13
...@@ -928,10 +928,7 @@ pub usingnamespace switch (builtin.arch) {...@@ -928,10 +928,7 @@ pub usingnamespace switch (builtin.arch) {
928 SegSs: DWORD,928 SegSs: DWORD,
929 ExtendedRegisters: [512]BYTE,929 ExtendedRegisters: [512]BYTE,
930930
931 pub fn getRegs(ctx: *const CONTEXT) struct {931 pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } {
932 bp: usize,
933 ip: usize,
934 } {
935 return .{ .bp = ctx.Ebp, .ip = ctx.Eip };932 return .{ .bp = ctx.Ebp, .ip = ctx.Eip };
936 }933 }
937 };934 };
...@@ -1034,10 +1031,7 @@ pub usingnamespace switch (builtin.arch) {...@@ -1034,10 +1031,7 @@ pub usingnamespace switch (builtin.arch) {
1034 LastExceptionToRip: DWORD64,1031 LastExceptionToRip: DWORD64,
1035 LastExceptionFromRip: DWORD64,1032 LastExceptionFromRip: DWORD64,
10361033
1037 pub fn getRegs(ctx: *const CONTEXT) struct {1034 pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } {
1038 bp: usize,
1039 ip: usize,
1040 } {
1041 return .{ .bp = ctx.Rbp, .ip = ctx.Rip };1035 return .{ .bp = ctx.Rbp, .ip = ctx.Rip };
1042 }1036 }
1043 };1037 };
...@@ -1105,11 +1099,11 @@ pub usingnamespace switch (builtin.arch) {...@@ -1105,11 +1099,11 @@ pub usingnamespace switch (builtin.arch) {
1105 Wcr: [2]DWORD,1099 Wcr: [2]DWORD,
1106 Wvr: [2]DWORD64,1100 Wvr: [2]DWORD64,
11071101
1108 pub fn getRegs(ctx: *const CONTEXT) struct {1102 pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize } {
1109 bp: usize,1103 return .{
1110 ip: usize,1104 .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp,
1111 } {1105 .ip = ctx.Pc,
1112 return .{ .bp = ctx.DUMMYUNIONNAME.DUMMYSTRUCTNAME.Fp, .ip = ctx.Pc };1106 };
1113 }1107 }
1114 };1108 };
11151109
lib/std/zig/ast.zig+11
...@@ -10,6 +10,7 @@ pub const TokenIndex = usize;...@@ -10,6 +10,7 @@ pub const TokenIndex = usize;
10pub const Tree = struct {10pub const Tree = struct {
11 source: []const u8,11 source: []const u8,
12 tokens: TokenList,12 tokens: TokenList,
13
13 /// undefined on parse error (errors not empty)14 /// undefined on parse error (errors not empty)
14 root_node: *Node.Root,15 root_node: *Node.Root,
15 arena_allocator: std.heap.ArenaAllocator,16 arena_allocator: std.heap.ArenaAllocator,
...@@ -780,6 +781,11 @@ pub const Node = struct {...@@ -780,6 +781,11 @@ pub const Node = struct {
780 i -= 1;781 i -= 1;
781 }782 }
782783
784 if (self.align_expr) |align_expr| {
785 if (i < 1) return align_expr;
786 i -= 1;
787 }
788
783 if (self.value_expr) |value_expr| {789 if (self.value_expr) |value_expr| {
784 if (i < 1) return value_expr;790 if (i < 1) return value_expr;
785 i -= 1;791 i -= 1;
...@@ -796,6 +802,11 @@ pub const Node = struct {...@@ -796,6 +802,11 @@ pub const Node = struct {
796 if (self.value_expr) |value_expr| {802 if (self.value_expr) |value_expr| {
797 return value_expr.lastToken();803 return value_expr.lastToken();
798 }804 }
805 if (self.align_expr) |align_expr| {
806 // The expression refers to what's inside the parenthesis, the
807 // last token is the closing one
808 return align_expr.lastToken() + 1;
809 }
799 if (self.type_expr) |type_expr| {810 if (self.type_expr) |type_expr| {
800 return type_expr.lastToken();811 return type_expr.lastToken();
801 }812 }
lib/std/zig/parser_test.zig+23-14
...@@ -1,3 +1,23 @@...@@ -1,3 +1,23 @@
1test "zig fmt: trailing comma in container declaration" {
2 try testCanonical(
3 \\const X = struct { foo: i32 };
4 \\const X = struct { foo: i32, bar: i32 };
5 \\const X = struct { foo: i32 = 1, bar: i32 = 2 };
6 \\const X = struct { foo: i32 align(4), bar: i32 align(4) };
7 \\const X = struct { foo: i32 align(4) = 1, bar: i32 align(4) = 2 };
8 \\
9 );
10 try testTransform(
11 \\const X = struct {
12 \\ foo: i32, bar: i8 };
13 ,
14 \\const X = struct {
15 \\ foo: i32, bar: i8
16 \\};
17 \\
18 );
19}
20
1test "zig fmt: trailing comma in fn parameter list" {21test "zig fmt: trailing comma in fn parameter list" {
2 try testCanonical(22 try testCanonical(
3 \\pub fn f(23 \\pub fn f(
...@@ -727,10 +747,7 @@ test "zig fmt: enum decl with no trailing comma" {...@@ -727,10 +747,7 @@ test "zig fmt: enum decl with no trailing comma" {
727 try testTransform(747 try testTransform(
728 \\const StrLitKind = enum {Normal, C};748 \\const StrLitKind = enum {Normal, C};
729 ,749 ,
730 \\const StrLitKind = enum {750 \\const StrLitKind = enum { Normal, C };
731 \\ Normal,
732 \\ C,
733 \\};
734 \\751 \\
735 );752 );
736}753}
...@@ -984,16 +1001,10 @@ test "zig fmt: empty block with only comment" {...@@ -984,16 +1001,10 @@ test "zig fmt: empty block with only comment" {
984}1001}
9851002
986test "zig fmt: no trailing comma on struct decl" {1003test "zig fmt: no trailing comma on struct decl" {
987 try testTransform(1004 try testCanonical(
988 \\const RoundParam = struct {1005 \\const RoundParam = struct {
989 \\ k: usize, s: u32, t: u321006 \\ k: usize, s: u32, t: u32
990 \\};1007 \\};
991 ,
992 \\const RoundParam = struct {
993 \\ k: usize,
994 \\ s: u32,
995 \\ t: u32,
996 \\};
997 \\1008 \\
998 );1009 );
999}1010}
...@@ -2560,10 +2571,8 @@ test "zig fmt: if type expr" {...@@ -2560,10 +2571,8 @@ test "zig fmt: if type expr" {
2560 );2571 );
2561}2572}
2562test "zig fmt: file ends with struct field" {2573test "zig fmt: file ends with struct field" {
2563 try testTransform(2574 try testCanonical(
2564 \\a: bool2575 \\a: bool
2565 ,
2566 \\a: bool,
2567 \\2576 \\
2568 );2577 );
2569}2578}
lib/std/zig/perf_test.zig+1-1
...@@ -25,7 +25,7 @@ pub fn main() !void {...@@ -25,7 +25,7 @@ pub fn main() !void {
2525
26 var stdout_file = std.io.getStdOut();26 var stdout_file = std.io.getStdOut();
27 const stdout = &stdout_file.outStream().stream;27 const stdout = &stdout_file.outStream().stream;
28 try stdout.print("{:.3} MiB/s, {} KiB used \n", .{mb_per_sec, memory_used / 1024});28 try stdout.print("{:.3} MiB/s, {} KiB used \n", .{ mb_per_sec, memory_used / 1024 });
29}29}
3030
31fn testOnce() usize {31fn testOnce() usize {
lib/std/zig/render.zig+108-40
...@@ -206,6 +206,10 @@ fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *as...@@ -206,6 +206,10 @@ fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *as
206}206}
207207
208fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node) (@TypeOf(stream).Child.Error || Error)!void {208fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node) (@TypeOf(stream).Child.Error || Error)!void {
209 try renderContainerDecl(allocator, stream, tree, indent, start_col, decl, .Newline);
210}
211
212fn 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 {
209 switch (decl.id) {213 switch (decl.id) {
210 .FnProto => {214 .FnProto => {
211 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);215 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
...@@ -213,11 +217,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -213,11 +217,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
213 try renderDocComments(tree, stream, fn_proto, indent, start_col);217 try renderDocComments(tree, stream, fn_proto, indent, start_col);
214218
215 if (fn_proto.body_node) |body_node| {219 if (fn_proto.body_node) |body_node| {
216 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space);220 try renderExpression(allocator, stream, tree, indent, start_col, decl, .Space);
217 try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline);221 try renderExpression(allocator, stream, tree, indent, start_col, body_node, space);
218 } else {222 } else {
219 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None);223 try renderExpression(allocator, stream, tree, indent, start_col, decl, .None);
220 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline);224 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, space);
221 }225 }
222 },226 },
223227
...@@ -225,11 +229,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -225,11 +229,11 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
225 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);229 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
226230
227 if (use_decl.visib_token) |visib_token| {231 if (use_decl.visib_token) |visib_token| {
228 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub232 try renderToken(tree, stream, visib_token, indent, start_col, .Space); // pub
229 }233 }
230 try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // usingnamespace234 try renderToken(tree, stream, use_decl.use_token, indent, start_col, .Space); // usingnamespace
231 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);235 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, .None);
232 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;236 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, space); // ;
233 },237 },
234238
235 .VarDecl => {239 .VarDecl => {
...@@ -243,9 +247,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -243,9 +247,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
243 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);247 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
244248
245 try renderDocComments(tree, stream, test_decl, indent, start_col);249 try renderDocComments(tree, stream, test_decl, indent, start_col);
246 try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space);250 try renderToken(tree, stream, test_decl.test_token, indent, start_col, .Space);
247 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space);251 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, .Space);
248 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);252 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, space);
249 },253 },
250254
251 .ContainerField => {255 .ContainerField => {
...@@ -253,62 +257,76 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -253,62 +257,76 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
253257
254 try renderDocComments(tree, stream, field, indent, start_col);258 try renderDocComments(tree, stream, field, indent, start_col);
255 if (field.comptime_token) |t| {259 if (field.comptime_token) |t| {
256 try renderToken(tree, stream, t, indent, start_col, Space.Space); // comptime260 try renderToken(tree, stream, t, indent, start_col, .Space); // comptime
257 }261 }
258262
263 const src_has_trailing_comma = blk: {
264 const maybe_comma = tree.nextToken(field.lastToken());
265 break :blk tree.tokens.at(maybe_comma).id == .Comma;
266 };
267
268 // The trailing comma is emitted at the end, but if it's not present
269 // we still have to respect the specified `space` parameter
270 const last_token_space: Space = if (src_has_trailing_comma) .None else space;
271
259 if (field.type_expr == null and field.value_expr == null) {272 if (field.type_expr == null and field.value_expr == null) {
260 return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name,273 try renderToken(tree, stream, field.name_token, indent, start_col, last_token_space); // name
261 } else if (field.type_expr != null and field.value_expr == null) {274 } else if (field.type_expr != null and field.value_expr == null) {
262 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name275 try renderToken(tree, stream, field.name_token, indent, start_col, .None); // name
263 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :276 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // :
264277
265 if (field.align_expr) |align_value_expr| {278 if (field.align_expr) |align_value_expr| {
266 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type279 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type
267 const lparen_token = tree.prevToken(align_value_expr.firstToken());280 const lparen_token = tree.prevToken(align_value_expr.firstToken());
268 const align_kw = tree.prevToken(lparen_token);281 const align_kw = tree.prevToken(lparen_token);
269 const rparen_token = tree.nextToken(align_value_expr.lastToken());282 const rparen_token = tree.nextToken(align_value_expr.lastToken());
270 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align283 try renderToken(tree, stream, align_kw, indent, start_col, .None); // align
271 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (284 try renderToken(tree, stream, lparen_token, indent, start_col, .None); // (
272 try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment285 try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, .None); // alignment
273 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Comma); // ),286 try renderToken(tree, stream, rparen_token, indent, start_col, last_token_space); // )
274 } else {287 } else {
275 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,288 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, last_token_space); // type
276 }289 }
277 } else if (field.type_expr == null and field.value_expr != null) {290 } else if (field.type_expr == null and field.value_expr != null) {
278 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name291 try renderToken(tree, stream, field.name_token, indent, start_col, .Space); // name
279 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =292 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // =
280 return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value293 try renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, last_token_space); // value
281 } else {294 } else {
282 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name295 try renderToken(tree, stream, field.name_token, indent, start_col, .None); // name
283 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :296 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, .Space); // :
284297
285 if (field.align_expr) |align_value_expr| {298 if (field.align_expr) |align_value_expr| {
286 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type299 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type
287 const lparen_token = tree.prevToken(align_value_expr.firstToken());300 const lparen_token = tree.prevToken(align_value_expr.firstToken());
288 const align_kw = tree.prevToken(lparen_token);301 const align_kw = tree.prevToken(lparen_token);
289 const rparen_token = tree.nextToken(align_value_expr.lastToken());302 const rparen_token = tree.nextToken(align_value_expr.lastToken());
290 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align303 try renderToken(tree, stream, align_kw, indent, start_col, .None); // align
291 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (304 try renderToken(tree, stream, lparen_token, indent, start_col, .None); // (
292 try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment305 try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, .None); // alignment
293 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Space); // )306 try renderToken(tree, stream, rparen_token, indent, start_col, .Space); // )
294 } else {307 } else {
295 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type308 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, .Space); // type
296 }309 }
297 try renderToken(tree, stream, tree.prevToken(field.value_expr.?.firstToken()), indent, start_col, Space.Space); // =310 try renderToken(tree, stream, tree.prevToken(field.value_expr.?.firstToken()), indent, start_col, .Space); // =
298 return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value,311 try renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, last_token_space); // value
312 }
313
314 if (src_has_trailing_comma) {
315 const comma = tree.nextToken(field.lastToken());
316 try renderToken(tree, stream, comma, indent, start_col, space);
299 }317 }
300 },318 },
301319
302 .Comptime => {320 .Comptime => {
303 assert(!decl.requireSemiColon());321 assert(!decl.requireSemiColon());
304 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline);322 try renderExpression(allocator, stream, tree, indent, start_col, decl, space);
305 },323 },
306324
307 .DocComment => {325 .DocComment => {
308 const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);326 const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
309 var it = comment.lines.iterator(0);327 var it = comment.lines.iterator(0);
310 while (it.next()) |line_token_index| {328 while (it.next()) |line_token_index| {
311 try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline);329 try renderToken(tree, stream, line_token_index.*, indent, start_col, .Newline);
312 if (it.peek()) |_| {330 if (it.peek()) |_| {
313 try stream.writeByteNTimes(' ', indent);331 try stream.writeByteNTimes(' ', indent);
314 }332 }
...@@ -1150,14 +1168,42 @@ fn renderExpression(...@@ -1150,14 +1168,42 @@ fn renderExpression(
1150 if (container_decl.fields_and_decls.len == 0) {1168 if (container_decl.fields_and_decls.len == 0) {
1151 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {1169 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {
1152 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }1170 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
1153 } else {1171 }
1172
1173 const src_has_trailing_comma = blk: {
1174 var maybe_comma = tree.prevToken(container_decl.lastToken());
1175 // Doc comments for a field may also appear after the comma, eg.
1176 // field_name: T, // comment attached to field_name
1177 if (tree.tokens.at(maybe_comma).id == .DocComment)
1178 maybe_comma = tree.prevToken(maybe_comma);
1179 break :blk tree.tokens.at(maybe_comma).id == .Comma;
1180 };
1181
1182 // Check if the first declaration and the { are on the same line
1183 const src_has_newline = !tree.tokensOnSameLine(
1184 container_decl.lbrace_token,
1185 container_decl.fields_and_decls.at(0).*.firstToken(),
1186 );
1187
1188 // We can only print all the elements in-line if all the
1189 // declarations inside are fields
1190 const src_has_only_fields = blk: {
1191 var it = container_decl.fields_and_decls.iterator(0);
1192 while (it.next()) |decl| {
1193 if (decl.*.id != .ContainerField) break :blk false;
1194 }
1195 break :blk true;
1196 };
1197
1198 if (src_has_trailing_comma or !src_has_only_fields) {
1199 // One declaration per line
1154 const new_indent = indent + indent_delta;1200 const new_indent = indent + indent_delta;
1155 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, Space.Newline); // {1201 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, start_col, .Newline); // {
11561202
1157 var it = container_decl.fields_and_decls.iterator(0);1203 var it = container_decl.fields_and_decls.iterator(0);
1158 while (it.next()) |decl| {1204 while (it.next()) |decl| {
1159 try stream.writeByteNTimes(' ', new_indent);1205 try stream.writeByteNTimes(' ', new_indent);
1160 try renderTopLevelDecl(allocator, stream, tree, new_indent, start_col, decl.*);1206 try renderContainerDecl(allocator, stream, tree, new_indent, start_col, decl.*, .Newline);
11611207
1162 if (it.peek()) |next_decl| {1208 if (it.peek()) |next_decl| {
1163 try renderExtraNewline(tree, stream, start_col, next_decl.*);1209 try renderExtraNewline(tree, stream, start_col, next_decl.*);
...@@ -1165,8 +1211,30 @@ fn renderExpression(...@@ -1165,8 +1211,30 @@ fn renderExpression(
1165 }1211 }
11661212
1167 try stream.writeByteNTimes(' ', indent);1213 try stream.writeByteNTimes(' ', indent);
1168 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }1214 } else if (src_has_newline) {
1215 // All the declarations on the same line, but place the items on
1216 // their own line
1217 try renderToken(tree, stream, container_decl.lbrace_token, indent, start_col, .Newline); // {
1218
1219 const new_indent = indent + indent_delta;
1220 try stream.writeByteNTimes(' ', new_indent);
1221
1222 var it = container_decl.fields_and_decls.iterator(0);
1223 while (it.next()) |decl| {
1224 const space_after_decl: Space = if (it.peek() == null) .Newline else .Space;
1225 try renderContainerDecl(allocator, stream, tree, new_indent, start_col, decl.*, space_after_decl);
1226 }
1227 } else {
1228 // All the declarations on the same line
1229 try renderToken(tree, stream, container_decl.lbrace_token, indent, start_col, .Space); // {
1230
1231 var it = container_decl.fields_and_decls.iterator(0);
1232 while (it.next()) |decl| {
1233 try renderContainerDecl(allocator, stream, tree, indent, start_col, decl.*, .Space);
1234 }
1169 }1235 }
1236
1237 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
1170 },1238 },
11711239
1172 .ErrorSetDecl => {1240 .ErrorSetDecl => {
src-self-hosted/dep_tokenizer.zig+1-1
...@@ -894,7 +894,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {...@@ -894,7 +894,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
894894
895fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {895fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
896 var buf: [80]u8 = undefined;896 var buf: [80]u8 = undefined;
897 var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{label, bytes.len});897 var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
898 try out.write(text);898 try out.write(text);
899 var i: usize = text.len;899 var i: usize = text.len;
900 const end = 79;900 const end = 79;
src-self-hosted/link.zig+1-1
...@@ -105,7 +105,7 @@ extern fn ZigLLDLink(...@@ -105,7 +105,7 @@ extern fn ZigLLDLink(
105 context: *c_void,105 context: *c_void,
106) bool;106) bool;
107107
108extern fn linkDiagCallback(context: *c_void, ptr: [*]const u8, len: usize) void {108fn linkDiagCallback(context: *c_void, ptr: [*]const u8, len: usize) callconv(.C) void {
109 const ctx = @ptrCast(*Context, @alignCast(@alignOf(Context), context));109 const ctx = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
110 ctx.link_err = linkDiagCallbackErrorable(ctx, ptr[0..len]);110 ctx.link_err = linkDiagCallbackErrorable(ctx, ptr[0..len]);
111}111}