Commit 8a4c2d3b07

Andrew Kelley <andrew@ziglang.org>
2019-11-25 19:49:16
zig fmt fixes for sentinel-terminated pointers
closes #3771
1 parent a061ef4
Changed files (4)
lib/std/zig/ast.zig
@@ -2204,7 +2204,7 @@ pub const Node = struct {
     };
 
     pub const VarType = struct {
-        base: Node,
+        base: Node = Node{ .id = .VarType },
         token: TokenIndex,
 
         pub fn iterate(self: *VarType, index: usize) ?*Node {
lib/std/zig/parse.zig
@@ -410,10 +410,16 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
     var align_expr: ?*Node = null;
     var type_expr: ?*Node = null;
     if (eatToken(it, .Colon)) |_| {
-        type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
-            .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
-        });
-        align_expr = try parseByteAlign(arena, it, tree);
+        if (eatToken(it, .Keyword_var)) |var_tok| {
+            const node = try arena.create(ast.Node.VarType);
+            node.* = .{ .token = var_tok };
+            type_expr = &node.base;
+        } else {
+            type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
+                .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
+            });
+            align_expr = try parseByteAlign(arena, it, tree);
+        }
     }
 
     const value_expr = if (eatToken(it, .Equal)) |_|
@@ -576,7 +582,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
 
 /// LabeledStatement <- BlockLabel? (Block / LoopStatement)
 fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
-    const label_token = parseBlockLabel(arena, it, tree);
+    var colon: TokenIndex = undefined;
+    const label_token = parseBlockLabel(arena, it, tree, &colon);
 
     if (try parseBlock(arena, it, tree)) |node| {
         node.cast(Node.Block).?.label = label_token;
@@ -757,7 +764,8 @@ fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !
 
 /// BlockExpr <- BlockLabel? Block
 fn parseBlockExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node {
-    const label_token = parseBlockLabel(arena, it, tree);
+    var colon: TokenIndex = undefined;
+    const label_token = parseBlockLabel(arena, it, tree, &colon);
     const block_node = (try parseBlock(arena, it, tree)) orelse {
         if (label_token) |label| {
             putBackToken(it, label + 1); // ":"
@@ -913,7 +921,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
         return &node.base;
     }
 
-    const label = parseBlockLabel(arena, it, tree);
+    var colon: TokenIndex = undefined;
+    const label = parseBlockLabel(arena, it, tree, &colon);
     if (try parseLoopExpr(arena, it, tree)) |node| {
         if (node.cast(Node.For)) |for_node| {
             for_node.label = label;
@@ -1354,7 +1363,8 @@ fn parseIfTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
 ///     <- BlockLabel Block
 ///      / BlockLabel? LoopTypeExpr
 fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
-    const label = parseBlockLabel(arena, it, tree);
+    var colon: TokenIndex = undefined;
+    const label = parseBlockLabel(arena, it, tree, &colon);
 
     if (label) |token| {
         if (try parseBlock(arena, it, tree)) |node| {
@@ -1372,12 +1382,9 @@ fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
         return node;
     }
 
-    if (label != null) {
-        // If we saw a label, there should have been a block next
-        try tree.errors.push(AstError{
-            .ExpectedLBrace = AstError.ExpectedLBrace{ .token = it.index },
-        });
-        return error.ParseError;
+    if (label) |token| {
+        putBackToken(it, colon);
+        putBackToken(it, token);
     }
     return null;
 }
@@ -1641,9 +1648,12 @@ fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
 }
 
 /// BlockLabel <- IDENTIFIER COLON
-fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenIndex {
+fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree, colon_token: *TokenIndex) ?TokenIndex {
     const identifier = eatToken(it, .Identifier) orelse return null;
-    if (eatToken(it, .Colon) != null) return identifier;
+    if (eatToken(it, .Colon)) |colon| {
+        colon_token.* = colon;
+        return identifier;
+    }
     putBackToken(it, identifier);
     return null;
 }
lib/std/zig/parser_test.zig
@@ -1,3 +1,30 @@
+test "zig fmt: var struct field" {
+    try testCanonical(
+        \\pub const Pointer = struct {
+        \\    sentinel: var,
+        \\};
+        \\
+    );
+}
+
+test "zig fmt: sentinel-terminated array type" {
+    try testCanonical(
+        \\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
+        \\    return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
+        \\}
+        \\
+    );
+}
+
+test "zig fmt: sentinel-terminated slice type" {
+    try testCanonical(
+        \\pub fn toSlice(self: Buffer) [:0]u8 {
+        \\    return self.list.toSlice()[0..self.len()];
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: anon literal in array" {
     try testCanonical(
         \\var arr: [2]Foo = .{
lib/std/zig/render.zig
@@ -477,7 +477,14 @@ fn renderExpression(
 
                 ast.Node.PrefixOp.Op.SliceType => |ptr_info| {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
-                    try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
+                    if (ptr_info.sentinel) |sentinel| {
+                        const colon_token = tree.prevToken(sentinel.firstToken());
+                        try renderToken(tree, stream, colon_token, indent, start_col, Space.None); // :
+                        try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None);
+                        try renderToken(tree, stream, tree.nextToken(sentinel.lastToken()), indent, start_col, Space.None); // ]
+                    } else {
+                        try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
+                    }
 
                     if (ptr_info.allowzero_token) |allowzero_token| {
                         try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero