| ... | @@ -229,6 +229,7 @@ pub const Parser = struct { | ... | @@ -229,6 +229,7 @@ pub const Parser = struct { |
| 229 | ComptimeStatement: ComptimeStatementCtx, | 229 | ComptimeStatement: ComptimeStatementCtx, |
| 230 | Semicolon: &&ast.Node, | 230 | Semicolon: &&ast.Node, |
| 231 | AddComments: AddCommentsCtx, | 231 | AddComments: AddCommentsCtx, |
| | 232 | LookForSameLineComment: &&ast.Node, |
| 232 | | 233 | |
| 233 | AsmOutputItems: &ArrayList(&ast.Node.AsmOutput), | 234 | AsmOutputItems: &ArrayList(&ast.Node.AsmOutput), |
| 234 | AsmOutputReturnOrType: &ast.Node.AsmOutput, | 235 | AsmOutputReturnOrType: &ast.Node.AsmOutput, |
| ... | @@ -356,7 +357,8 @@ pub const Parser = struct { | ... | @@ -356,7 +357,8 @@ pub const Parser = struct { |
| 356 | const block = try arena.construct(ast.Node.Block { | 357 | const block = try arena.construct(ast.Node.Block { |
| 357 | .base = ast.Node { | 358 | .base = ast.Node { |
| 358 | .id = ast.Node.Id.Block, | 359 | .id = ast.Node.Id.Block, |
| 359 | .comments = null, | 360 | .before_comments = null, |
| | 361 | .same_line_comment = null, |
| 360 | }, | 362 | }, |
| 361 | .label = null, | 363 | .label = null, |
| 362 | .lbrace = undefined, | 364 | .lbrace = undefined, |
| ... | @@ -366,7 +368,8 @@ pub const Parser = struct { | ... | @@ -366,7 +368,8 @@ pub const Parser = struct { |
| 366 | const test_node = try arena.construct(ast.Node.TestDecl { | 368 | const test_node = try arena.construct(ast.Node.TestDecl { |
| 367 | .base = ast.Node { | 369 | .base = ast.Node { |
| 368 | .id = ast.Node.Id.TestDecl, | 370 | .id = ast.Node.Id.TestDecl, |
| 369 | .comments = comments, | 371 | .before_comments = comments, |
| | 372 | .same_line_comment = null, |
| 370 | }, | 373 | }, |
| 371 | .test_token = token, | 374 | .test_token = token, |
| 372 | .name = undefined, | 375 | .name = undefined, |
| ... | @@ -547,7 +550,8 @@ pub const Parser = struct { | ... | @@ -547,7 +550,8 @@ pub const Parser = struct { |
| 547 | const fn_proto = try arena.construct(ast.Node.FnProto { | 550 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 548 | .base = ast.Node { | 551 | .base = ast.Node { |
| 549 | .id = ast.Node.Id.FnProto, | 552 | .id = ast.Node.Id.FnProto, |
| 550 | .comments = ctx.comments, | 553 | .before_comments = ctx.comments, |
| | 554 | .same_line_comment = null, |
| 551 | }, | 555 | }, |
| 552 | .visib_token = ctx.visib_token, | 556 | .visib_token = ctx.visib_token, |
| 553 | .name_token = null, | 557 | .name_token = null, |
| ... | @@ -812,7 +816,8 @@ pub const Parser = struct { | ... | @@ -812,7 +816,8 @@ pub const Parser = struct { |
| 812 | const var_decl = try arena.construct(ast.Node.VarDecl { | 816 | const var_decl = try arena.construct(ast.Node.VarDecl { |
| 813 | .base = ast.Node { | 817 | .base = ast.Node { |
| 814 | .id = ast.Node.Id.VarDecl, | 818 | .id = ast.Node.Id.VarDecl, |
| 815 | .comments = ctx.comments, | 819 | .before_comments = ctx.comments, |
| | 820 | .same_line_comment = null, |
| 816 | }, | 821 | }, |
| 817 | .visib_token = ctx.visib_token, | 822 | .visib_token = ctx.visib_token, |
| 818 | .mut_token = ctx.mut_token, | 823 | .mut_token = ctx.mut_token, |
| ... | @@ -1242,7 +1247,8 @@ pub const Parser = struct { | ... | @@ -1242,7 +1247,8 @@ pub const Parser = struct { |
| 1242 | const node = try arena.construct(ast.Node.Defer { | 1247 | const node = try arena.construct(ast.Node.Defer { |
| 1243 | .base = ast.Node { | 1248 | .base = ast.Node { |
| 1244 | .id = ast.Node.Id.Defer, | 1249 | .id = ast.Node.Id.Defer, |
| 1245 | .comments = comments, | 1250 | .before_comments = comments, |
| | 1251 | .same_line_comment = null, |
| 1246 | }, | 1252 | }, |
| 1247 | .defer_token = token, | 1253 | .defer_token = token, |
| 1248 | .kind = switch (token.id) { | 1254 | .kind = switch (token.id) { |
| ... | @@ -1275,7 +1281,8 @@ pub const Parser = struct { | ... | @@ -1275,7 +1281,8 @@ pub const Parser = struct { |
| 1275 | else => { | 1281 | else => { |
| 1276 | self.putBackToken(token); | 1282 | self.putBackToken(token); |
| 1277 | const statement = try block.statements.addOne(); | 1283 | const statement = try block.statements.addOne(); |
| 1278 | stack.append(State { .Semicolon = statement }) catch unreachable; | 1284 | stack.append(State { .LookForSameLineComment = statement }) catch unreachable; |
| | 1285 | try stack.append(State { .Semicolon = statement }); |
| 1279 | try stack.append(State { .AddComments = AddCommentsCtx { | 1286 | try stack.append(State { .AddComments = AddCommentsCtx { |
| 1280 | .node_ptr = statement, | 1287 | .node_ptr = statement, |
| 1281 | .comments = comments, | 1288 | .comments = comments, |
| ... | @@ -1324,7 +1331,28 @@ pub const Parser = struct { | ... | @@ -1324,7 +1331,28 @@ pub const Parser = struct { |
| 1324 | | 1331 | |
| 1325 | State.AddComments => |add_comments_ctx| { | 1332 | State.AddComments => |add_comments_ctx| { |
| 1326 | const node = *add_comments_ctx.node_ptr; | 1333 | const node = *add_comments_ctx.node_ptr; |
| 1327 | node.comments = add_comments_ctx.comments; | 1334 | node.before_comments = add_comments_ctx.comments; |
| | 1335 | continue; |
| | 1336 | }, |
| | 1337 | |
| | 1338 | State.LookForSameLineComment => |node_ptr| { |
| | 1339 | const node = *node_ptr; |
| | 1340 | const node_last_token = node.lastToken(); |
| | 1341 | |
| | 1342 | const line_comment_token = self.getNextToken(); |
| | 1343 | if (line_comment_token.id != Token.Id.LineComment) { |
| | 1344 | self.putBackToken(line_comment_token); |
| | 1345 | continue; |
| | 1346 | } |
| | 1347 | |
| | 1348 | const offset_loc = self.tokenizer.getTokenLocation(node_last_token.end, line_comment_token); |
| | 1349 | const different_line = offset_loc.line != 0; |
| | 1350 | if (different_line) { |
| | 1351 | self.putBackToken(line_comment_token); |
| | 1352 | continue; |
| | 1353 | } |
| | 1354 | |
| | 1355 | node.same_line_comment = try arena.construct(line_comment_token); |
| 1328 | continue; | 1356 | continue; |
| 1329 | }, | 1357 | }, |
| 1330 | | 1358 | |
| ... | @@ -1614,7 +1642,8 @@ pub const Parser = struct { | ... | @@ -1614,7 +1642,8 @@ pub const Parser = struct { |
| 1614 | const fn_proto = try arena.construct(ast.Node.FnProto { | 1642 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 1615 | .base = ast.Node { | 1643 | .base = ast.Node { |
| 1616 | .id = ast.Node.Id.FnProto, | 1644 | .id = ast.Node.Id.FnProto, |
| 1617 | .comments = ctx.comments, | 1645 | .before_comments = ctx.comments, |
| | 1646 | .same_line_comment = null, |
| 1618 | }, | 1647 | }, |
| 1619 | .visib_token = null, | 1648 | .visib_token = null, |
| 1620 | .name_token = null, | 1649 | .name_token = null, |
| ... | @@ -2585,7 +2614,8 @@ pub const Parser = struct { | ... | @@ -2585,7 +2614,8 @@ pub const Parser = struct { |
| 2585 | const fn_proto = try arena.construct(ast.Node.FnProto { | 2614 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2586 | .base = ast.Node { | 2615 | .base = ast.Node { |
| 2587 | .id = ast.Node.Id.FnProto, | 2616 | .id = ast.Node.Id.FnProto, |
| 2588 | .comments = null, | 2617 | .before_comments = null, |
| | 2618 | .same_line_comment = null, |
| 2589 | }, | 2619 | }, |
| 2590 | .visib_token = null, | 2620 | .visib_token = null, |
| 2591 | .name_token = null, | 2621 | .name_token = null, |
| ... | @@ -2608,7 +2638,8 @@ pub const Parser = struct { | ... | @@ -2608,7 +2638,8 @@ pub const Parser = struct { |
| 2608 | const fn_proto = try arena.construct(ast.Node.FnProto { | 2638 | const fn_proto = try arena.construct(ast.Node.FnProto { |
| 2609 | .base = ast.Node { | 2639 | .base = ast.Node { |
| 2610 | .id = ast.Node.Id.FnProto, | 2640 | .id = ast.Node.Id.FnProto, |
| 2611 | .comments = null, | 2641 | .before_comments = null, |
| | 2642 | .same_line_comment = null, |
| 2612 | }, | 2643 | }, |
| 2613 | .visib_token = null, | 2644 | .visib_token = null, |
| 2614 | .name_token = null, | 2645 | .name_token = null, |
| ... | @@ -2788,7 +2819,8 @@ pub const Parser = struct { | ... | @@ -2788,7 +2819,8 @@ pub const Parser = struct { |
| 2788 | const comment_node = try arena.construct(ast.Node.LineComment { | 2819 | const comment_node = try arena.construct(ast.Node.LineComment { |
| 2789 | .base = ast.Node { | 2820 | .base = ast.Node { |
| 2790 | .id = ast.Node.Id.LineComment, | 2821 | .id = ast.Node.Id.LineComment, |
| 2791 | .comments = null, | 2822 | .before_comments = null, |
| | 2823 | .same_line_comment = null, |
| 2792 | }, | 2824 | }, |
| 2793 | .lines = ArrayList(Token).init(arena), | 2825 | .lines = ArrayList(Token).init(arena), |
| 2794 | }); | 2826 | }); |
| ... | @@ -3134,7 +3166,11 @@ pub const Parser = struct { | ... | @@ -3134,7 +3166,11 @@ pub const Parser = struct { |
| 3134 | *node = *init_to; | 3166 | *node = *init_to; |
| 3135 | node.base = blk: { | 3167 | node.base = blk: { |
| 3136 | const id = ast.Node.typeToId(T); | 3168 | const id = ast.Node.typeToId(T); |
| 3137 | break :blk ast.Node {.id = id, .comments = null}; | 3169 | break :blk ast.Node { |
| | 3170 | .id = id, |
| | 3171 | .before_comments = null, |
| | 3172 | .same_line_comment = null, |
| | 3173 | }; |
| 3138 | }; | 3174 | }; |
| 3139 | | 3175 | |
| 3140 | return node; | 3176 | return node; |
| ... | @@ -3270,6 +3306,7 @@ pub const Parser = struct { | ... | @@ -3270,6 +3306,7 @@ pub const Parser = struct { |
| 3270 | FieldInitializer: &ast.Node.FieldInitializer, | 3306 | FieldInitializer: &ast.Node.FieldInitializer, |
| 3271 | PrintIndent, | 3307 | PrintIndent, |
| 3272 | Indent: usize, | 3308 | Indent: usize, |
| | 3309 | PrintSameLineComment: ?&Token, |
| 3273 | }; | 3310 | }; |
| 3274 | | 3311 | |
| 3275 | pub fn renderSource(self: &Parser, stream: var, root_node: &ast.Node.Root) !void { | 3312 | pub fn renderSource(self: &Parser, stream: var, root_node: &ast.Node.Root) !void { |
| ... | @@ -4370,6 +4407,7 @@ pub const Parser = struct { | ... | @@ -4370,6 +4407,7 @@ pub const Parser = struct { |
| 4370 | }, | 4407 | }, |
| 4371 | RenderState.Statement => |base| { | 4408 | RenderState.Statement => |base| { |
| 4372 | try self.renderComments(stream, base, indent); | 4409 | try self.renderComments(stream, base, indent); |
| | 4410 | try stack.append(RenderState { .PrintSameLineComment = base.same_line_comment } ); |
| 4373 | switch (base.id) { | 4411 | switch (base.id) { |
| 4374 | ast.Node.Id.VarDecl => { | 4412 | ast.Node.Id.VarDecl => { |
| 4375 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); | 4413 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); |
| ... | @@ -4385,12 +4423,16 @@ pub const Parser = struct { | ... | @@ -4385,12 +4423,16 @@ pub const Parser = struct { |
| 4385 | }, | 4423 | }, |
| 4386 | RenderState.Indent => |new_indent| indent = new_indent, | 4424 | RenderState.Indent => |new_indent| indent = new_indent, |
| 4387 | RenderState.PrintIndent => try stream.writeByteNTimes(' ', indent), | 4425 | RenderState.PrintIndent => try stream.writeByteNTimes(' ', indent), |
| | 4426 | RenderState.PrintSameLineComment => |maybe_comment| blk: { |
| | 4427 | const comment_token = maybe_comment ?? break :blk; |
| | 4428 | try stream.print(" {}", self.tokenizer.getTokenSlice(comment_token)); |
| | 4429 | }, |
| 4388 | } | 4430 | } |
| 4389 | } | 4431 | } |
| 4390 | } | 4432 | } |
| 4391 | | 4433 | |
| 4392 | fn renderComments(self: &Parser, stream: var, node: &ast.Node, indent: usize) !void { | 4434 | fn renderComments(self: &Parser, stream: var, node: &ast.Node, indent: usize) !void { |
| 4393 | const comment = node.comments ?? return; | 4435 | const comment = node.before_comments ?? return; |
| 4394 | for (comment.lines.toSliceConst()) |line_token| { | 4436 | for (comment.lines.toSliceConst()) |line_token| { |
| 4395 | try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); | 4437 | try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); |
| 4396 | try stream.writeByteNTimes(' ', indent); | 4438 | try stream.writeByteNTimes(' ', indent); |
| ... | @@ -4471,6 +4513,17 @@ fn testCanonical(source: []const u8) !void { | ... | @@ -4471,6 +4513,17 @@ fn testCanonical(source: []const u8) !void { |
| 4471 | } | 4513 | } |
| 4472 | } | 4514 | } |
| 4473 | | 4515 | |
| | 4516 | test "zig fmt: preserve same-line comment after a statement" { |
| | 4517 | try testCanonical( |
| | 4518 | \\test "" { |
| | 4519 | \\ a = b; |
| | 4520 | \\ debug.assert(H.digest_size <= H.block_size); // HMAC makes this assumption |
| | 4521 | \\ a = b; |
| | 4522 | \\} |
| | 4523 | \\ |
| | 4524 | ); |
| | 4525 | } |
| | 4526 | |
| 4474 | test "zig fmt: preserve comments before global variables" { | 4527 | test "zig fmt: preserve comments before global variables" { |
| 4475 | try testCanonical( | 4528 | try testCanonical( |
| 4476 | \\/// Foo copies keys and values before they go into the map, and | 4529 | \\/// Foo copies keys and values before they go into the map, and |