Commit 64d700bfa6

Andrew Kelley <andrew@ziglang.org>
2019-12-08 18:24:45
zig fmt: support comptime fields
1 parent fe8d655
Changed files (4)
lib/std/zig/ast.zig
@@ -754,8 +754,9 @@ pub const Node = struct {
     };
 
     pub const ContainerField = struct {
-        base: Node,
+        base: Node = Node{ .id = .ContainerField },
         doc_comments: ?*DocComment,
+        comptime_token: ?TokenIndex,
         name_token: TokenIndex,
         type_expr: ?*Node,
         value_expr: ?*Node,
@@ -778,7 +779,7 @@ pub const Node = struct {
         }
 
         pub fn firstToken(self: *const ContainerField) TokenIndex {
-            return self.name_token;
+            return self.comptime_token orelse self.name_token;
         }
 
         pub fn lastToken(self: *const ContainerField) TokenIndex {
lib/std/zig/parse.zig
@@ -206,6 +206,11 @@ fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
 /// TopLevelComptime <- KEYWORD_comptime BlockExpr
 fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
     const tok = eatToken(it, .Keyword_comptime) orelse return null;
+    const lbrace = eatToken(it, .LBrace) orelse {
+        putBackToken(it, tok);
+        return null;
+    };
+    putBackToken(it, lbrace);
     const block_node = try expectNode(arena, it, tree, parseBlockExpr, AstError{
         .ExpectedLabelOrLBrace = AstError.ExpectedLabelOrLBrace{ .token = it.index },
     });
@@ -403,9 +408,13 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
     return &node.base;
 }
 
-/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
+/// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
 fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
-    const name_token = eatToken(it, .Identifier) orelse return null;
+    const comptime_token = eatToken(it, .Keyword_comptime);
+    const name_token = eatToken(it, .Identifier) orelse {
+        if (comptime_token) |t| putBackToken(it, t);
+        return null;
+    };
 
     var align_expr: ?*Node = null;
     var type_expr: ?*Node = null;
@@ -431,8 +440,8 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
 
     const node = try arena.create(Node.ContainerField);
     node.* = Node.ContainerField{
-        .base = Node{ .id = .ContainerField },
         .doc_comments = null,
+        .comptime_token = comptime_token,
         .name_token = name_token,
         .type_expr = type_expr,
         .value_expr = value_expr,
lib/std/zig/parser_test.zig
@@ -1,3 +1,13 @@
+test "zig fmt: comptime struct field" {
+    try testCanonical(
+        \\const Foo = struct {
+        \\    a: i32,
+        \\    comptime b: i32 = 1234,
+        \\};
+        \\
+    );
+}
+
 test "zig fmt: c pointer type" {
     try testCanonical(
         \\pub extern fn repro() [*c]const u8;
lib/std/zig/render.zig
@@ -251,6 +251,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
             const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
 
             try renderDocComments(tree, stream, field, indent, start_col);
+            if (field.comptime_token) |t| {
+                try renderToken(tree, stream, t, indent, start_col, Space.Space); // comptime
+            }
 
             if (field.type_expr == null and field.value_expr == null) {
                 return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name,