authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-27 19:21:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-27 19:21:38-04:00
log4f2d49fd138be67ad01d9c1b9086cb6a41530944
tree3c7d058ceef97d8ae9948313a1adf47aa9152aa1
parentb92fac329e73280ea5d49af675fea84e777b7f0a
signaturelock-open Commit is signed but in an unrecognized format.

std.zig.parse: fix parsing of doc comments after fields

closes #1404

2 files changed, 73 insertions(+), 13 deletions(-)

std/zig/parse.zig+56-13
......@@ -340,7 +340,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
340340 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
341341 node_ptr.* = &node.base;
342342
343 stack.append(State{ .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
343 try stack.append(State{
344 .FieldListCommaOrEnd = FieldCtx{
345 .doc_comments = &node.doc_comments,
346 .container_decl = ctx.container_decl,
347 },
348 });
344349 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.type_expr } });
345350 try stack.append(State{ .ExpectToken = Token.Id.Colon });
346351 continue;
......@@ -458,7 +463,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
458463 const node_ptr = try container_decl.fields_and_decls.addOne();
459464 node_ptr.* = &node.base;
460465
461 try stack.append(State{ .FieldListCommaOrEnd = container_decl });
466 try stack.append(State{
467 .FieldListCommaOrEnd = FieldCtx{
468 .doc_comments = &node.doc_comments,
469 .container_decl = container_decl,
470 },
471 });
462472 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.type_expr } });
463473 try stack.append(State{ .ExpectToken = Token.Id.Colon });
464474 continue;
......@@ -473,7 +483,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
473483 });
474484 try container_decl.fields_and_decls.push(&node.base);
475485
476 stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable;
486 try stack.append(State{
487 .FieldListCommaOrEnd = FieldCtx{
488 .doc_comments = &node.doc_comments,
489 .container_decl = container_decl,
490 },
491 });
477492 try stack.append(State{ .FieldInitValue = OptionalCtx{ .RequiredNull = &node.value_expr } });
478493 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &node.type_expr } });
479494 try stack.append(State{ .IfToken = Token.Id.Colon });
......@@ -488,7 +503,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
488503 });
489504 try container_decl.fields_and_decls.push(&node.base);
490505
491 stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable;
506 try stack.append(State{
507 .FieldListCommaOrEnd = FieldCtx{
508 .doc_comments = &node.doc_comments,
509 .container_decl = container_decl,
510 },
511 });
492512 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &node.value } });
493513 try stack.append(State{ .IfToken = Token.Id.Equal });
494514 continue;
......@@ -1265,17 +1285,35 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
12651285 },
12661286 }
12671287 },
1268 State.FieldListCommaOrEnd => |container_decl| {
1269 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
1270 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1271 container_decl.rbrace_token = end;
1288 State.FieldListCommaOrEnd => |field_ctx| {
1289 const end_token = nextToken(&tok_it, &tree);
1290 const end_token_index = end_token.index;
1291 const end_token_ptr = end_token.ptr;
1292 switch (end_token_ptr.id) {
1293 Token.Id.Comma => {
1294 if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {
1295 const loc = tree.tokenLocation(end_token_ptr.end, doc_comment_token);
1296 if (loc.line == 0) {
1297 try pushDocComment(arena, doc_comment_token, field_ctx.doc_comments);
1298 } else {
1299 prevToken(&tok_it, &tree);
1300 }
1301 }
1302
1303 try stack.append(State{ .ContainerDecl = field_ctx.container_decl });
12721304 continue;
1273 } else {
1274 try stack.append(State{ .ContainerDecl = container_decl });
1305 },
1306 Token.Id.RBrace => {
1307 field_ctx.container_decl.rbrace_token = end_token_index;
12751308 continue;
12761309 },
1277 ExpectCommaOrEndResult.parse_error => |e| {
1278 try tree.errors.push(e);
1310 else => {
1311 try tree.errors.push(Error{
1312 .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd{
1313 .token = end_token_index,
1314 .end_id = end_token_ptr.id,
1315 },
1316 });
12791317 return tree;
12801318 },
12811319 }
......@@ -2813,6 +2851,11 @@ const ExprListCtx = struct {
28132851 ptr: *TokenIndex,
28142852};
28152853
2854const FieldCtx = struct {
2855 container_decl: *ast.Node.ContainerDecl,
2856 doc_comments: *?*ast.Node.DocComment,
2857};
2858
28162859fn ListSave(comptime List: type) type {
28172860 return struct {
28182861 list: *List,
......@@ -2950,7 +2993,7 @@ const State = union(enum) {
29502993 ExprListCommaOrEnd: ExprListCtx,
29512994 FieldInitListItemOrEnd: ListSave(ast.Node.SuffixOp.Op.InitList),
29522995 FieldInitListCommaOrEnd: ListSave(ast.Node.SuffixOp.Op.InitList),
2953 FieldListCommaOrEnd: *ast.Node.ContainerDecl,
2996 FieldListCommaOrEnd: FieldCtx,
29542997 FieldInitValue: OptionalCtx,
29552998 ErrorTagListItemOrEnd: ListSave(ast.Node.ErrorSetDecl.DeclList),
29562999 ErrorTagListCommaOrEnd: ListSave(ast.Node.ErrorSetDecl.DeclList),
std/zig/parser_test.zig+17
......@@ -1,3 +1,20 @@
1test "zig fmt: correctly move doc comments on struct fields" {
2 try testTransform(
3 \\pub const section_64 = extern struct {
4 \\ sectname: [16]u8, /// name of this section
5 \\ segname: [16]u8, /// segment this section goes in
6 \\};
7 ,
8 \\pub const section_64 = extern struct {
9 \\ /// name of this section
10 \\ sectname: [16]u8,
11 \\ /// segment this section goes in
12 \\ segname: [16]u8,
13 \\};
14 \\
15 );
16}
17
118test "zig fmt: preserve space between async fn definitions" {
219 try testCanonical(
320 \\async fn a() void {}