From bcafc51e58fcd6a4b12e43a780c0e9eef43a8d28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 9 Feb 2021 14:41:50 -0700 Subject: [PATCH] zig fmt: fn protos and anytype --- lib/std/zig/ast.zig | 98 ++++++++++++++++++++++++++++++++----- lib/std/zig/parser_test.zig | 42 ++++++++-------- lib/std/zig/render.zig | 23 +++------ 3 files changed, 115 insertions(+), 48 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 169c6cbb67..32c7e0ac7f 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -250,6 +250,7 @@ pub const Tree = struct { .FnProto, .ArrayType, .ArrayTypeSentinel, + .ErrorValue, => return main_tokens[n], .ArrayInitDot, @@ -424,12 +425,18 @@ pub const Tree = struct { return main_tokens[n] - 1; }, - .WhileSimple => unreachable, // TODO - .WhileCont => unreachable, // TODO - .While => unreachable, // TODO - .ForSimple => unreachable, // TODO - .For => unreachable, // TODO - .ErrorValue => unreachable, // TODO + .WhileSimple, + .WhileCont, + .While, + .ForSimple, + .For, + => { + const main_token = main_tokens[n]; + return switch (token_tags[main_token - 1]) { + .Keyword_inline => main_token - 1, + else => main_token, + }; + }, }; } @@ -437,6 +444,7 @@ pub const Tree = struct { const tags = tree.nodes.items(.tag); const datas = tree.nodes.items(.data); const main_tokens = tree.nodes.items(.main_token); + const token_starts = tree.tokens.items(.start); var n = node; var end_offset: TokenIndex = 0; while (true) switch (tags[n]) { @@ -521,6 +529,8 @@ pub const Tree = struct { .AsmSimple, .AsmOutput, .AsmInput, + .FnProtoSimple, + .FnProtoMulti, => return datas[n].rhs + end_offset, .AnyType, @@ -759,6 +769,74 @@ pub const Tree = struct { return main_tokens[n] + end_offset; } }, + .FnProtoOne => { + const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne); + // linksection, callconv, align can appear in any order, so we + // find the last one here. + var max_node: Node.Index = datas[n].rhs; + var max_start = token_starts[main_tokens[max_node]]; + var max_offset: TokenIndex = 0; + if (extra.align_expr != 0) { + const start = token_starts[main_tokens[extra.align_expr]]; + if (start > max_start) { + max_node = extra.align_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + if (extra.section_expr != 0) { + const start = token_starts[main_tokens[extra.section_expr]]; + if (start > max_start) { + max_node = extra.section_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + if (extra.callconv_expr != 0) { + const start = token_starts[main_tokens[extra.callconv_expr]]; + if (start > max_start) { + max_node = extra.callconv_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + n = max_node; + end_offset += max_offset; + }, + .FnProto => { + const extra = tree.extraData(datas[n].lhs, Node.FnProto); + // linksection, callconv, align can appear in any order, so we + // find the last one here. + var max_node: Node.Index = datas[n].rhs; + var max_start = token_starts[main_tokens[max_node]]; + var max_offset: TokenIndex = 0; + if (extra.align_expr != 0) { + const start = token_starts[main_tokens[extra.align_expr]]; + if (start > max_start) { + max_node = extra.align_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + if (extra.section_expr != 0) { + const start = token_starts[main_tokens[extra.section_expr]]; + if (start > max_start) { + max_node = extra.section_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + if (extra.callconv_expr != 0) { + const start = token_starts[main_tokens[extra.callconv_expr]]; + if (start > max_start) { + max_node = extra.callconv_expr; + max_start = start; + max_offset = 1; // for the rparen + } + } + n = max_node; + end_offset += max_offset; + }, // These are not supported by lastToken() because implementation would // require recursion due to the optional comma followed by rbrace. @@ -782,10 +860,6 @@ pub const Tree = struct { .While => unreachable, // TODO .ForSimple => unreachable, // TODO .For => unreachable, // TODO - .FnProtoSimple => unreachable, // TODO - .FnProtoMulti => unreachable, // TODO - .FnProtoOne => unreachable, // TODO - .FnProto => unreachable, // TODO .ErrorValue => unreachable, // TODO }; } @@ -2217,11 +2291,11 @@ pub const Node = struct { /// `fn(a: b, c: d) rhs`. `sub_range_list[lhs]`. /// anytype and ... parameters are omitted from the AST tree. FnProtoMulti, - /// `fn(a: b) rhs linksection(e) callconv(f)`. lhs is index into extra_data. + /// `fn(a: b) rhs linksection(e) callconv(f)`. `FnProtoOne[lhs]`. /// zero or one parameters. /// anytype and ... parameters are omitted from the AST tree. FnProtoOne, - /// `fn(a: b, c: d) rhs linksection(e) callconv(f)`. `fn_proto_list[lhs]`. + /// `fn(a: b, c: d) rhs linksection(e) callconv(f)`. `FnProto[lhs]`. /// anytype and ... parameters are omitted from the AST tree. FnProto, /// lhs is the FnProto, rhs is the function body block. diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 5ae8f37b87..da6671177a 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -337,15 +337,15 @@ test "zig fmt: asm expression with comptime content" { ); } -//test "zig fmt: anytype struct field" { -// try testCanonical( -// \\pub const Pointer = struct { -// \\ sentinel: anytype, -// \\}; -// \\ -// ); -//} -// +test "zig fmt: anytype struct field" { + try testCanonical( + \\pub const Pointer = struct { + \\ sentinel: anytype, + \\}; + \\ + ); +} + //test "zig fmt: sentinel-terminated array type" { // try testCanonical( // \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 { @@ -691,18 +691,18 @@ test "zig fmt: block in slice expression" { ); } -//test "zig fmt: async function" { -// try testCanonical( -// \\pub const Server = struct { -// \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void, -// \\}; -// \\test "hi" { -// \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other); -// \\} -// \\ -// ); -//} -// +test "zig fmt: async function" { + try testCanonical( + \\pub const Server = struct { + \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void, + \\}; + \\test "hi" { + \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other); + \\} + \\ + ); +} + //test "zig fmt: whitespace fixes" { // try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n", // \\test "" { diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 212e4c85d1..df17b313f4 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -22,7 +22,7 @@ pub const Error = error{ const Writer = std.ArrayList(u8).Writer; const Ais = std.io.AutoIndentingStream(Writer); -/// `gpa` is used both for allocating the resulting formatted source code, but also +/// `gpa` is used for allocating the resulting formatted source code, as well as /// for allocating extra stack memory if needed, because this function utilizes recursion. /// Note: that's not actually true yet, see https://github.com/ziglang/zig/issues/1006. /// Caller owns the returned slice of bytes, allocated with `gpa`. @@ -191,17 +191,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac .ErrorValue => unreachable, // TODO - .AnyType => unreachable, // TODO - //.AnyType => { - // const any_type = base.castTag(.AnyType).?; - // if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) { - // // TODO remove in next release cycle - // try ais.writer().writeAll("anytype"); - // if (space == .Comma) try ais.writer().writeAll(",\n"); - // return; - // } - // return renderToken(ais, tree, any_type.token, space); - //}, + .AnyType => return renderToken(ais, tree, main_tokens[node], space), + .BlockTwo, .BlockTwoSemicolon, => { @@ -1412,9 +1403,11 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S try renderToken(ais, tree, last_param_token, .Space); // , last_param_token += 1; }, - else => unreachable, + else => {}, // Parameter type without a name. } - if (token_tags[last_param_token] == .Identifier) { + if (token_tags[last_param_token] == .Identifier and + token_tags[last_param_token + 1] == .Colon) + { try renderToken(ais, tree, last_param_token, .None); // name last_param_token += 1; try renderToken(ais, tree, last_param_token, .Space); // : @@ -1427,7 +1420,7 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.full.FnProto, space: S const param = fn_proto.ast.params[param_i]; param_i += 1; try renderExpression(ais, tree, param, .None); - last_param_token = tree.lastToken(param) + 1; + last_param_token = tree.lastToken(param); } } else { // One param per line.