diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index c8f9afd080..2042f07cf6 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -146,6 +146,7 @@ pub const Tree = struct { .ExpectedFn => |*x| return x.render(tokens, stream), .ExpectedReturnType => |*x| return x.render(tokens, stream), .ExpectedAggregateKw => |*x| return x.render(tokens, stream), + .SameLineDocComment => |*x| return x.render(tokens, stream), .UnattachedDocComment => |*x| return x.render(tokens, stream), .ExpectedEqOrSemi => |*x| return x.render(tokens, stream), .ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream), @@ -200,6 +201,7 @@ pub const Tree = struct { .ExpectedFn => |x| return x.token, .ExpectedReturnType => |x| return x.token, .ExpectedAggregateKw => |x| return x.token, + .SameLineDocComment => |x| return x.token, .UnattachedDocComment => |x| return x.token, .ExpectedEqOrSemi => |x| return x.token, .ExpectedSemiOrLBrace => |x| return x.token, @@ -2250,6 +2252,7 @@ pub const Error = union(enum) { ExpectedFn: ExpectedFn, ExpectedReturnType: ExpectedReturnType, ExpectedAggregateKw: ExpectedAggregateKw, + SameLineDocComment: SameLineDocComment, UnattachedDocComment: UnattachedDocComment, ExpectedEqOrSemi: ExpectedEqOrSemi, ExpectedSemiOrLBrace: ExpectedSemiOrLBrace, @@ -2326,6 +2329,7 @@ pub const Error = union(enum) { pub const ExpectedParamType = SimpleError("Expected parameter type"); pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub"); + pub const SameLineDocComment = SimpleError("Same line documentation comment"); pub const UnattachedDocComment = SimpleError("Unattached documentation comment"); pub const ExtraAlignQualifier = SimpleError("Extra align qualifier"); pub const ExtraConstQualifier = SimpleError("Extra const qualifier"); diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index a2043071d1..f6545c0f13 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -190,7 +190,7 @@ const Parser = struct { var trailing_comma = false; while (true) { - const doc_comment = p.eatDocComments(); + const doc_comment = try p.eatDocComments (); switch (p.token_tags[p.tok_i]) { .keyword_test => { @@ -515,7 +515,6 @@ const Parser = struct { switch (p.token_tags[p.tok_i]) { .semicolon => { const semicolon_token = p.nextToken(); - try p.parseAppendedDocComment(semicolon_token); return p.addNode(.{ .tag = .fn_decl, .main_token = p.nodes.items(.main_token)[fn_proto], @@ -557,7 +556,6 @@ const Parser = struct { const var_decl = try p.parseVarDecl(); if (var_decl != 0) { const semicolon_token = try p.expectToken(.semicolon); - try p.parseAppendedDocComment(semicolon_token); return var_decl; } if (thread_local_token != null) { @@ -585,7 +583,6 @@ const Parser = struct { const usingnamespace_token = try p.expectToken(.keyword_usingnamespace); const expr = try p.expectExpr(); const semicolon_token = try p.expectToken(.semicolon); - try p.parseAppendedDocComment(semicolon_token); return p.addNode(.{ .tag = .@"usingnamespace", .main_token = usingnamespace_token, @@ -2885,7 +2882,7 @@ const Parser = struct { } while (true) { - const doc_comment = p.eatDocComments(); + const doc_comment = try p.eatDocComments(); const identifier = try p.expectToken(.identifier); switch (p.token_tags[p.nextToken()]) { .comma => { @@ -3274,7 +3271,7 @@ const Parser = struct { /// such as in the case of anytype and `...`. Caller must look for rparen to find /// out when there are no more param decls left. fn expectParamDecl(p: *Parser) !Node.Index { - _ = p.eatDocComments(); + _ = try p.eatDocComments(); switch (p.token_tags[p.tok_i]) { .keyword_noalias, .keyword_comptime => p.tok_i += 1, .ellipsis3 => { @@ -4075,8 +4072,13 @@ const Parser = struct { } /// Skips over doc comment tokens. Returns the first one, if any. - fn eatDocComments(p: *Parser) ?TokenIndex { - if (p.eatToken(.doc_comment)) |first_line| { + fn eatDocComments(p: *Parser) !?TokenIndex { + if (p.eatToken(.doc_comment)) |tok| { + var first_line = tok; + if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) { + try p.warn(.{ .SameLineDocComment = .{ .token = tok } }); + first_line = p.eatToken(.doc_comment) orelse return null; + } while (p.eatToken(.doc_comment)) |_| {} return first_line; } @@ -4087,14 +4089,6 @@ const Parser = struct { return std.mem.indexOfScalar(u8, p.source[p.token_starts[token1]..p.token_starts[token2]], '\n') == null; } - /// Eat a single-line doc comment on the same line as another node - fn parseAppendedDocComment(p: *Parser, after_token: TokenIndex) !void { - const comment_token = p.eatToken(.doc_comment) orelse return; - if (!p.tokensOnSameLine(after_token, comment_token)) { - p.tok_i -= 1; - } - } - fn eatToken(p: *Parser, tag: Token.Tag) ?TokenIndex { return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null; } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index e00b94114d..f8e992bb2e 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1016,23 +1016,6 @@ test "zig fmt: linksection" { ); } -//test "zig fmt: correctly move doc comments on struct fields" { -// try testTransform( -// \\pub const section_64 = extern struct { -// \\ sectname: [16]u8, /// name of this section -// \\ segname: [16]u8, /// segment this section goes in -// \\}; -// , -// \\pub const section_64 = extern struct { -// \\ /// name of this section -// \\ sectname: [16]u8, -// \\ /// segment this section goes in -// \\ segname: [16]u8, -// \\}; -// \\ -// ); -//} - test "zig fmt: correctly space struct fields with doc comments" { try testTransform( \\pub const S = struct { @@ -1449,31 +1432,6 @@ test "zig fmt: async call in if condition" { // \\ // ); //} -// -//test "zig fmt: same-line doc comment on variable declaration" { -// try testTransform( -// \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space -// \\pub const MAP_FILE = 0x0000; /// map from file (default) -// \\ -// \\pub const EMEDIUMTYPE = 124; /// Wrong medium type -// \\ -// \\// nameserver query return codes -// \\pub const ENSROK = 0; /// DNS server returned answer with no data -// , -// \\/// allocated from memory, swap space -// \\pub const MAP_ANONYMOUS = 0x1000; -// \\/// map from file (default) -// \\pub const MAP_FILE = 0x0000; -// \\ -// \\/// Wrong medium type -// \\pub const EMEDIUMTYPE = 124; -// \\ -// \\// nameserver query return codes -// \\/// DNS server returned answer with no data -// \\pub const ENSROK = 0; -// \\ -// ); -//} test "zig fmt: if-else with comment before else" { try testCanonical( @@ -3625,6 +3583,30 @@ test "zig fmt: file ends with struct field" { // }); //} +test "zig fmt: same line doc comment returns error" { + try testError( + \\const Foo = struct{ + \\ bar: u32, /// comment + \\ foo: u32, /// comment + \\ /// commment + \\}; + \\ + \\const a = 42; /// comment + \\ + \\extern fn foo() void; /// comment + \\ + \\/// comment + \\ + , &[_]Error{ + .SameLineDocComment, + .SameLineDocComment, + .UnattachedDocComment, + .SameLineDocComment, + .SameLineDocComment, + .UnattachedDocComment, + }); +} + test "zig fmt: integer literals with underscore separators" { try testTransform( \\const @@ -4388,6 +4370,6 @@ fn testError(source: []const u8, expected_errors: []const Error) !void { std.testing.expect(tree.errors.len == expected_errors.len); for (expected_errors) |expected, i| { - std.testing.expect(expected == tree.errors[i]); + std.testing.expectEqual(expected, tree.errors[i]); } }