Commit bcafc51e58

Andrew Kelley <andrew@ziglang.org>
2021-02-09 22:41:50
zig fmt: fn protos and anytype
1 parent b1d8a0a
Changed files (3)
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.
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 "" {
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.