authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-29 15:48:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-29 15:48:53-04:00
logb7095912c77900eab6ad667a6eeb1add18ac8071
tree5b18212a0caf93462eae9862e9f8c326815561ab
parentf37e79e720215a3a41c603fe41d05d6910c79de2

zig fmt: respect comments before statements


3 files changed, 180 insertions(+), 133 deletions(-)

std/mem.zig+16-2
......@@ -37,6 +37,20 @@ pub const Allocator = struct {
3737 return &slice[0];
3838 }
3939
40 // TODO once #733 is solved, this will replace create
41 fn construct(self: &Allocator, init: var) t: {
42 // TODO this is a workaround for type getting parsed as Error!&const T
43 const T = @typeOf(init).Child;
44 break :t Error!&T;
45 } {
46 const T = @typeOf(init).Child;
47 if (@sizeOf(T) == 0) return &{};
48 const slice = try self.alloc(T, 1);
49 const ptr = &slice[0];
50 *ptr = *init;
51 return ptr;
52 }
53
4054 fn destroy(self: &Allocator, ptr: var) void {
4155 self.free(ptr[0..1]);
4256 }
......@@ -54,7 +68,7 @@ pub const Allocator = struct {
5468 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
5569 const byte_slice = try self.allocFn(self, byte_count, alignment);
5670 assert(byte_slice.len == byte_count);
57 // This loop should get optimized out in ReleaseFast mode
71 // This loop gets optimized out in ReleaseFast mode
5872 for (byte_slice) |*byte| {
5973 *byte = undefined;
6074 }
......@@ -81,7 +95,7 @@ pub const Allocator = struct {
8195 const byte_slice = try self.reallocFn(self, old_byte_slice, byte_count, alignment);
8296 assert(byte_slice.len == byte_count);
8397 if (n > old_mem.len) {
84 // This loop should get optimized out in ReleaseFast mode
98 // This loop gets optimized out in ReleaseFast mode
8599 for (byte_slice[old_byte_slice.len..]) |*byte| {
86100 *byte = undefined;
87101 }
std/zig/ast.zig+1-3
......@@ -6,6 +6,7 @@ const mem = std.mem;
66
77pub const Node = struct {
88 id: Id,
9 comments: ?&LineComment,
910
1011 pub const Id = enum {
1112 // Top level
......@@ -139,7 +140,6 @@ pub const Node = struct {
139140
140141 pub const VarDecl = struct {
141142 base: Node,
142 comments: ?&LineComment,
143143 visib_token: ?Token,
144144 name_token: Token,
145145 eq_token: Token,
......@@ -421,7 +421,6 @@ pub const Node = struct {
421421
422422 pub const FnProto = struct {
423423 base: Node,
424 comments: ?&LineComment,
425424 visib_token: ?Token,
426425 fn_token: Token,
427426 name_token: ?Token,
......@@ -1732,7 +1731,6 @@ pub const Node = struct {
17321731
17331732 pub const TestDecl = struct {
17341733 base: Node,
1735 comments: ?&LineComment,
17361734 test_token: Token,
17371735 name: &Node,
17381736 body_node: &Node,
std/zig/parser.zig+163-128
......@@ -182,6 +182,11 @@ pub const Parser = struct {
182182 }
183183 };
184184
185 const AddCommentsCtx = struct {
186 node_ptr: &&ast.Node,
187 comments: ?&ast.Node.LineComment,
188 };
189
185190 const State = union(enum) {
186191 TopLevel,
187192 TopLevelExtern: TopLevelDeclCtx,
......@@ -221,6 +226,7 @@ pub const Parser = struct {
221226 Statement: &ast.Node.Block,
222227 ComptimeStatement: ComptimeStatementCtx,
223228 Semicolon: &&ast.Node,
229 AddComments: AddCommentsCtx,
224230
225231 AsmOutputItems: &ArrayList(&ast.Node.AsmOutput),
226232 AsmOutputReturnOrType: &ast.Node.AsmOutput,
......@@ -345,24 +351,26 @@ pub const Parser = struct {
345351 Token.Id.Keyword_test => {
346352 stack.append(State.TopLevel) catch unreachable;
347353
348 const block = try self.createNode(arena, ast.Node.Block,
349 ast.Node.Block {
350 .base = undefined,
351 .label = null,
352 .lbrace = undefined,
353 .statements = ArrayList(&ast.Node).init(arena),
354 .rbrace = undefined,
355 }
356 );
357 const test_node = try self.createAttachNode(arena, &root_node.decls, ast.Node.TestDecl,
358 ast.Node.TestDecl {
359 .base = undefined,
354 const block = try arena.construct(ast.Node.Block {
355 .base = ast.Node {
356 .id = ast.Node.Id.Block,
357 .comments = null,
358 },
359 .label = null,
360 .lbrace = undefined,
361 .statements = ArrayList(&ast.Node).init(arena),
362 .rbrace = undefined,
363 });
364 const test_node = try arena.construct(ast.Node.TestDecl {
365 .base = ast.Node {
366 .id = ast.Node.Id.TestDecl,
360367 .comments = comments,
361 .test_token = token,
362 .name = undefined,
363 .body_node = &block.base,
364 }
365 );
368 },
369 .test_token = token,
370 .name = undefined,
371 .body_node = &block.base,
372 });
373 try root_node.decls.append(&test_node.base);
366374 stack.append(State { .Block = block }) catch unreachable;
367375 try stack.append(State {
368376 .ExpectTokenSave = ExpectTokenSave {
......@@ -530,24 +538,25 @@ pub const Parser = struct {
530538 },
531539 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc,
532540 Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {
533 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.Node.FnProto,
534 ast.Node.FnProto {
535 .base = undefined,
541 const fn_proto = try arena.construct(ast.Node.FnProto {
542 .base = ast.Node {
543 .id = ast.Node.Id.FnProto,
536544 .comments = comments,
537 .visib_token = ctx.visib_token,
538 .name_token = null,
539 .fn_token = undefined,
540 .params = ArrayList(&ast.Node).init(arena),
541 .return_type = undefined,
542 .var_args_token = null,
543 .extern_export_inline_token = ctx.extern_export_inline_token,
544 .cc_token = null,
545 .async_attr = null,
546 .body_node = null,
547 .lib_name = ctx.lib_name,
548 .align_expr = null,
549 }
550 );
545 },
546 .visib_token = ctx.visib_token,
547 .name_token = null,
548 .fn_token = undefined,
549 .params = ArrayList(&ast.Node).init(arena),
550 .return_type = undefined,
551 .var_args_token = null,
552 .extern_export_inline_token = ctx.extern_export_inline_token,
553 .cc_token = null,
554 .async_attr = null,
555 .body_node = null,
556 .lib_name = ctx.lib_name,
557 .align_expr = null,
558 });
559 try ctx.decls.append(&fn_proto.base);
551560 stack.append(State { .FnDef = fn_proto }) catch unreachable;
552561 try stack.append(State { .FnProto = fn_proto });
553562
......@@ -789,24 +798,25 @@ pub const Parser = struct {
789798
790799
791800 State.VarDecl => |ctx| {
792 const var_decl = try self.createAttachNode(arena, ctx.list, ast.Node.VarDecl,
793 ast.Node.VarDecl {
794 .base = undefined,
801 const var_decl = try arena.construct(ast.Node.VarDecl {
802 .base = ast.Node {
803 .id = ast.Node.Id.VarDecl,
795804 .comments = ctx.comments,
796 .visib_token = ctx.visib_token,
797 .mut_token = ctx.mut_token,
798 .comptime_token = ctx.comptime_token,
799 .extern_export_token = ctx.extern_export_token,
800 .type_node = null,
801 .align_node = null,
802 .init_node = null,
803 .lib_name = ctx.lib_name,
804 // initialized later
805 .name_token = undefined,
806 .eq_token = undefined,
807 .semicolon_token = undefined,
808 }
809 );
805 },
806 .visib_token = ctx.visib_token,
807 .mut_token = ctx.mut_token,
808 .comptime_token = ctx.comptime_token,
809 .extern_export_token = ctx.extern_export_token,
810 .type_node = null,
811 .align_node = null,
812 .init_node = null,
813 .lib_name = ctx.lib_name,
814 // initialized later
815 .name_token = undefined,
816 .eq_token = undefined,
817 .semicolon_token = undefined,
818 });
819 try ctx.list.append(&var_decl.base);
810820
811821 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
812822 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });
......@@ -1218,19 +1228,23 @@ pub const Parser = struct {
12181228 continue;
12191229 },
12201230 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1221 const node = try self.createAttachNode(arena, &block.statements, ast.Node.Defer,
1222 ast.Node.Defer {
1223 .base = undefined,
1224 .defer_token = token,
1225 .kind = switch (token.id) {
1226 Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional,
1227 Token.Id.Keyword_errdefer => ast.Node.Defer.Kind.Error,
1228 else => unreachable,
1229 },
1230 .expr = undefined,
1231 }
1232 );
1233 stack.append(State { .Semicolon = &&node.base }) catch unreachable;
1231 const node = try arena.construct(ast.Node.Defer {
1232 .base = ast.Node {
1233 .id = ast.Node.Id.Defer,
1234 .comments = comments,
1235 },
1236 .defer_token = token,
1237 .kind = switch (token.id) {
1238 Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional,
1239 Token.Id.Keyword_errdefer => ast.Node.Defer.Kind.Error,
1240 else => unreachable,
1241 },
1242 .expr = undefined,
1243 });
1244 const node_ptr = try block.statements.addOne();
1245 *node_ptr = &node.base;
1246
1247 stack.append(State { .Semicolon = node_ptr }) catch unreachable;
12341248 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
12351249 continue;
12361250 },
......@@ -1249,9 +1263,13 @@ pub const Parser = struct {
12491263 },
12501264 else => {
12511265 self.putBackToken(token);
1252 const statememt = try block.statements.addOne();
1253 stack.append(State { .Semicolon = statememt }) catch unreachable;
1254 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statememt } });
1266 const statement = try block.statements.addOne();
1267 stack.append(State { .Semicolon = statement }) catch unreachable;
1268 try stack.append(State { .AddComments = AddCommentsCtx {
1269 .node_ptr = statement,
1270 .comments = comments,
1271 }});
1272 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });
12551273 continue;
12561274 }
12571275 }
......@@ -1293,6 +1311,12 @@ pub const Parser = struct {
12931311 continue;
12941312 },
12951313
1314 State.AddComments => |add_comments_ctx| {
1315 const node = *add_comments_ctx.node_ptr;
1316 node.comments = add_comments_ctx.comments;
1317 continue;
1318 },
1319
12961320
12971321 State.AsmOutputItems => |items| {
12981322 const lbracket = self.getNextToken();
......@@ -1576,24 +1600,25 @@ pub const Parser = struct {
15761600
15771601 State.ExternType => |ctx| {
15781602 if (self.eatToken(Token.Id.Keyword_fn)) |fn_token| {
1579 const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.FnProto,
1580 ast.Node.FnProto {
1581 .base = undefined,
1603 const fn_proto = try arena.construct(ast.Node.FnProto {
1604 .base = ast.Node {
1605 .id = ast.Node.Id.FnProto,
15821606 .comments = ctx.comments,
1583 .visib_token = null,
1584 .name_token = null,
1585 .fn_token = fn_token,
1586 .params = ArrayList(&ast.Node).init(arena),
1587 .return_type = undefined,
1588 .var_args_token = null,
1589 .extern_export_inline_token = ctx.extern_token,
1590 .cc_token = null,
1591 .async_attr = null,
1592 .body_node = null,
1593 .lib_name = null,
1594 .align_expr = null,
1595 }
1596 );
1607 },
1608 .visib_token = null,
1609 .name_token = null,
1610 .fn_token = fn_token,
1611 .params = ArrayList(&ast.Node).init(arena),
1612 .return_type = undefined,
1613 .var_args_token = null,
1614 .extern_export_inline_token = ctx.extern_token,
1615 .cc_token = null,
1616 .async_attr = null,
1617 .body_node = null,
1618 .lib_name = null,
1619 .align_expr = null,
1620 });
1621 ctx.opt_ctx.store(&fn_proto.base);
15971622 stack.append(State { .FnProto = fn_proto }) catch unreachable;
15981623 continue;
15991624 }
......@@ -2546,46 +2571,48 @@ pub const Parser = struct {
25462571 continue;
25472572 },
25482573 Token.Id.Keyword_fn => {
2549 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto,
2550 ast.Node.FnProto {
2551 .base = undefined,
2574 const fn_proto = try arena.construct(ast.Node.FnProto {
2575 .base = ast.Node {
2576 .id = ast.Node.Id.FnProto,
25522577 .comments = null,
2553 .visib_token = null,
2554 .name_token = null,
2555 .fn_token = token,
2556 .params = ArrayList(&ast.Node).init(arena),
2557 .return_type = undefined,
2558 .var_args_token = null,
2559 .extern_export_inline_token = null,
2560 .cc_token = null,
2561 .async_attr = null,
2562 .body_node = null,
2563 .lib_name = null,
2564 .align_expr = null,
2565 }
2566 );
2578 },
2579 .visib_token = null,
2580 .name_token = null,
2581 .fn_token = token,
2582 .params = ArrayList(&ast.Node).init(arena),
2583 .return_type = undefined,
2584 .var_args_token = null,
2585 .extern_export_inline_token = null,
2586 .cc_token = null,
2587 .async_attr = null,
2588 .body_node = null,
2589 .lib_name = null,
2590 .align_expr = null,
2591 });
2592 opt_ctx.store(&fn_proto.base);
25672593 stack.append(State { .FnProto = fn_proto }) catch unreachable;
25682594 continue;
25692595 },
25702596 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2571 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto,
2572 ast.Node.FnProto {
2573 .base = undefined,
2597 const fn_proto = try arena.construct(ast.Node.FnProto {
2598 .base = ast.Node {
2599 .id = ast.Node.Id.FnProto,
25742600 .comments = null,
2575 .visib_token = null,
2576 .name_token = null,
2577 .fn_token = undefined,
2578 .params = ArrayList(&ast.Node).init(arena),
2579 .return_type = undefined,
2580 .var_args_token = null,
2581 .extern_export_inline_token = null,
2582 .cc_token = token,
2583 .async_attr = null,
2584 .body_node = null,
2585 .lib_name = null,
2586 .align_expr = null,
2587 }
2588 );
2601 },
2602 .visib_token = null,
2603 .name_token = null,
2604 .fn_token = undefined,
2605 .params = ArrayList(&ast.Node).init(arena),
2606 .return_type = undefined,
2607 .var_args_token = null,
2608 .extern_export_inline_token = null,
2609 .cc_token = token,
2610 .async_attr = null,
2611 .body_node = null,
2612 .lib_name = null,
2613 .align_expr = null,
2614 });
2615 opt_ctx.store(&fn_proto.base);
25892616 stack.append(State { .FnProto = fn_proto }) catch unreachable;
25902617 try stack.append(State {
25912618 .ExpectTokenSave = ExpectTokenSave {
......@@ -2747,13 +2774,13 @@ pub const Parser = struct {
27472774 if (result) |comment_node| {
27482775 break :blk comment_node;
27492776 } else {
2750 const comment_node = try arena.create(ast.Node.LineComment);
2751 *comment_node = ast.Node.LineComment {
2777 const comment_node = try arena.construct(ast.Node.LineComment {
27522778 .base = ast.Node {
27532779 .id = ast.Node.Id.LineComment,
2780 .comments = null,
27542781 },
27552782 .lines = ArrayList(Token).init(arena),
2756 };
2783 });
27572784 result = comment_node;
27582785 break :blk comment_node;
27592786 }
......@@ -3096,7 +3123,7 @@ pub const Parser = struct {
30963123 *node = *init_to;
30973124 node.base = blk: {
30983125 const id = ast.Node.typeToId(T);
3099 break :blk ast.Node {.id = id};
3126 break :blk ast.Node {.id = id, .comments = null};
31003127 };
31013128
31023129 return node;
......@@ -3269,7 +3296,7 @@ pub const Parser = struct {
32693296 switch (decl.id) {
32703297 ast.Node.Id.FnProto => {
32713298 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
3272 try self.renderComments(stream, fn_proto, indent);
3299 try self.renderComments(stream, &fn_proto.base, indent);
32733300
32743301 if (fn_proto.body_node) |body_node| {
32753302 stack.append(RenderState { .Expression = body_node}) catch unreachable;
......@@ -3295,7 +3322,7 @@ pub const Parser = struct {
32953322 },
32963323 ast.Node.Id.TestDecl => {
32973324 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
3298 try self.renderComments(stream, test_decl, indent);
3325 try self.renderComments(stream, &test_decl.base, indent);
32993326 try stream.print("test ");
33003327 try stack.append(RenderState { .Expression = test_decl.body_node });
33013328 try stack.append(RenderState { .Text = " " });
......@@ -3338,7 +3365,6 @@ pub const Parser = struct {
33383365 },
33393366
33403367 RenderState.FieldInitializer => |field_init| {
3341 //TODO try self.renderComments(stream, field_init, indent);
33423368 try stream.print(".{}", self.tokenizer.getTokenSlice(field_init.name_token));
33433369 try stream.print(" = ");
33443370 try stack.append(RenderState { .Expression = field_init.expr });
......@@ -3385,7 +3411,6 @@ pub const Parser = struct {
33853411
33863412 RenderState.ParamDecl => |base| {
33873413 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
3388 // TODO try self.renderComments(stream, param_decl, indent);
33893414 if (param_decl.comptime_token) |comptime_token| {
33903415 try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
33913416 }
......@@ -4328,10 +4353,10 @@ pub const Parser = struct {
43284353 ast.Node.Id.ParamDecl => unreachable,
43294354 },
43304355 RenderState.Statement => |base| {
4356 try self.renderComments(stream, base, indent);
43314357 switch (base.id) {
43324358 ast.Node.Id.VarDecl => {
43334359 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
4334 try self.renderComments(stream, var_decl, indent);
43354360 try stack.append(RenderState { .VarDecl = var_decl});
43364361 },
43374362 else => {
......@@ -4348,7 +4373,7 @@ pub const Parser = struct {
43484373 }
43494374 }
43504375
4351 fn renderComments(self: &Parser, stream: var, node: var, indent: usize) !void {
4376 fn renderComments(self: &Parser, stream: var, node: &ast.Node, indent: usize) !void {
43524377 const comment = node.comments ?? return;
43534378 for (comment.lines.toSliceConst()) |line_token| {
43544379 try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token));
......@@ -4430,6 +4455,16 @@ fn testCanonical(source: []const u8) !void {
44304455 }
44314456}
44324457
4458test "zig fmt: preserve comments before statements" {
4459 try testCanonical(
4460 \\test "std" {
4461 \\ // statement comment
4462 \\ _ = @import("foo/bar.zig");
4463 \\}
4464 \\
4465 );
4466}
4467
44334468test "zig fmt: preserve top level comments" {
44344469 try testCanonical(
44354470 \\// top level comment