Commit 8c4f3e5a31

Isaac Freund <ifreund@ifreund.xyz>
2021-02-10 16:00:54
zig fmt: fix render of pointers with ** tokens
1 parent a524e57
Changed files (3)
lib/std/zig/ast.zig
@@ -407,7 +407,9 @@ pub const Tree = struct {
             => {
                 const main_token = main_tokens[n];
                 return switch (token_tags[main_token]) {
-                    .Asterisk => switch (token_tags[main_token - 1]) {
+                    .Asterisk,
+                    .AsteriskAsterisk,
+                    => switch (token_tags[main_token - 1]) {
                         .LBracket => main_token - 1,
                         else => main_token,
                     },
@@ -1625,7 +1627,9 @@ pub const Tree = struct {
         // literals in some places here
         const Kind = full.PtrType.Kind;
         const kind: Kind = switch (token_tags[info.main_token]) {
-            .Asterisk => switch (token_tags[info.main_token + 1]) {
+            .Asterisk,
+            .AsteriskAsterisk,
+            => switch (token_tags[info.main_token + 1]) {
                 .RBracket => .many,
                 .Colon => .sentinel,
                 .Identifier => if (token_tags[info.main_token - 1] == .LBracket) Kind.c else .one,
@@ -2393,18 +2397,26 @@ pub const Node = struct {
         /// `[*]align(lhs) rhs`. lhs can be omitted.
         /// `*align(lhs) rhs`. lhs can be omitted.
         /// `[]rhs`.
-        /// main_token is the asterisk if a pointer or the lbrace if a slice
+        /// main_token is the asterisk if a pointer or the lbracket if a slice
+        /// main_token might be a ** token, which is shared with a parent/child
+        /// pointer type and may require special handling.
         PtrTypeAligned,
         /// `[*:lhs]rhs`. lhs can be omitted.
         /// `*rhs`.
         /// `[:lhs]rhs`.
-        /// main_token is the asterisk if a pointer or the lbrace if a slice
+        /// main_token is the asterisk if a pointer or the lbracket if a slice
+        /// main_token might be a ** token, which is shared with a parent/child
+        /// pointer type and may require special handling.
         PtrTypeSentinel,
         /// lhs is index into PtrType. rhs is the element type expression.
-        /// main_token is the asterisk if a pointer or the lbrace if a slice
+        /// main_token is the asterisk if a pointer or the lbracket if a slice
+        /// main_token might be a ** token, which is shared with a parent/child
+        /// pointer type and may require special handling.
         PtrType,
         /// lhs is index into PtrTypeBitRange. rhs is the element type expression.
-        /// main_token is the asterisk if a pointer or the lbrace if a slice
+        /// main_token is the asterisk if a pointer or the lbracket if a slice
+        /// main_token might be a ** token, which is shared with a parent/child
+        /// pointer type and may require special handling.
         PtrTypeBitRange,
         /// `lhs[rhs..]`
         /// main_token is the lbracket.
lib/std/zig/parser_test.zig
@@ -2318,27 +2318,27 @@ test "zig fmt: alignment" {
     );
 }
 
-//test "zig fmt: C main" {
-//    try testCanonical(
-//        \\fn main(argc: c_int, argv: **u8) c_int {
-//        \\    const a = b;
-//        \\}
-//        \\
-//    );
-//}
-//
-//test "zig fmt: return" {
-//    try testCanonical(
-//        \\fn foo(argc: c_int, argv: **u8) c_int {
-//        \\    return 0;
-//        \\}
-//        \\
-//        \\fn bar() void {
-//        \\    return;
-//        \\}
-//        \\
-//    );
-//}
+test "zig fmt: C main" {
+    try testCanonical(
+        \\fn main(argc: c_int, argv: **u8) c_int {
+        \\    const a = b;
+        \\}
+        \\
+    );
+}
+
+test "zig fmt: return" {
+    try testCanonical(
+        \\fn foo(argc: c_int, argv: **u8) c_int {
+        \\    return 0;
+        \\}
+        \\
+        \\fn bar() void {
+        \\    return;
+        \\}
+        \\
+    );
+}
 
 test "zig fmt: function attributes" {
     try testCanonical(
@@ -2356,27 +2356,40 @@ test "zig fmt: function attributes" {
     );
 }
 
-//test "zig fmt: pointer attributes" {
-//    try testCanonical(
-//        \\extern fn f1(s: *align(*u8) u8) c_int;
-//        \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
-//        \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
-//        \\extern fn f4(s: *align(1) const volatile u8) c_int;
-//        \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
-//        \\
-//    );
-//}
-//
-//test "zig fmt: slice attributes" {
-//    try testCanonical(
-//        \\extern fn f1(s: *align(*u8) u8) c_int;
-//        \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
-//        \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
-//        \\extern fn f4(s: *align(1) const volatile u8) c_int;
-//        \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
-//        \\
-//    );
-//}
+test "zig fmt: nested pointers with ** tokens" {
+    try testCanonical(
+        \\const x: *u32 = undefined;
+        \\const x: **u32 = undefined;
+        \\const x: ***u32 = undefined;
+        \\const x: ****u32 = undefined;
+        \\const x: *****u32 = undefined;
+        \\const x: ******u32 = undefined;
+        \\const x: *******u32 = undefined;
+        \\
+    );
+}
+
+test "zig fmt: pointer attributes" {
+    try testCanonical(
+        \\extern fn f1(s: *align(*u8) u8) c_int;
+        \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
+        \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
+        \\extern fn f4(s: *align(1) const volatile u8) c_int;
+        \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
+        \\
+    );
+}
+
+test "zig fmt: slice attributes" {
+    try testCanonical(
+        \\extern fn f1(s: []align(*u8) u8) c_int;
+        \\extern fn f2(s: []align(1) []const []volatile u8) c_int;
+        \\extern fn f3(s: []align(1) const [:0]align(1) volatile []const volatile u8) c_int;
+        \\extern fn f4(s: []align(1) const volatile u8) c_int;
+        \\extern fn f5(s: [:0]align(1) const volatile u8) c_int;
+        \\
+    );
+}
 
 test "zig fmt: test declaration" {
     try testCanonical(
lib/std/zig/render.zig
@@ -699,6 +699,16 @@ fn renderPtrType(
 ) Error!void {
     switch (ptr_type.kind) {
         .one => {
+            // Since ** tokens exist and the same token is shared by two
+            // nested pointer types, we check to see if we are the parent
+            // in such a relationship. If so, skip rendering anything for
+            // this pointer type and rely on the child to render our asterisk
+            // as well when it renders the ** token.
+            if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .AsteriskAsterisk and
+                ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
+            {
+                return renderExpression(ais, tree, ptr_type.ast.child_type, space);
+            }
             try renderToken(ais, tree, ptr_type.ast.main_token, .None); // asterisk
         },
         .many => {