Commit ac004e1bf1

LemonBoy <thatlemon@gmail.com>
2021-01-22 15:18:39
stage1: Allow nameless test blocks
Nameless blocks are never filtered, the test prefix is still applied.
1 parent fc5ae1c
Changed files (6)
lib/std/zig/ast.zig
@@ -3231,7 +3231,7 @@ pub const Node = struct {
         base: Node = Node{ .tag = .TestDecl },
         doc_comments: ?*DocComment,
         test_token: TokenIndex,
-        name: *Node,
+        name: ?*Node,
         body_node: *Node,
 
         pub fn iterate(self: *const TestDecl, index: usize) ?*Node {
lib/std/zig/parse.zig
@@ -366,9 +366,7 @@ const Parser = struct {
     /// TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block
     fn parseTestDecl(p: *Parser) !?*Node {
         const test_token = p.eatToken(.Keyword_test) orelse return null;
-        const name_node = try p.expectNode(parseStringLiteralSingle, .{
-            .ExpectedStringLiteral = .{ .token = p.tok_i },
-        });
+        const name_node = try p.parseStringLiteralSingle();
         const block_node = (try p.parseBlock(null)) orelse {
             try p.errors.append(p.gpa, .{ .ExpectedLBrace = .{ .token = p.tok_i } });
             return error.ParseError;
lib/std/zig/render.zig
@@ -228,7 +228,8 @@ fn renderContainerDecl(allocator: *mem.Allocator, ais: anytype, tree: *ast.Tree,
 
             try renderDocComments(tree, ais, test_decl, test_decl.doc_comments);
             try renderToken(tree, ais, test_decl.test_token, .Space);
-            try renderExpression(allocator, ais, tree, test_decl.name, .Space);
+            if (test_decl.name) |name|
+                try renderExpression(allocator, ais, tree, name, .Space);
             try renderExpression(allocator, ais, tree, test_decl.body_node, space);
         },
 
src/stage1/all_types.hpp
@@ -797,6 +797,7 @@ struct AstNodeVariableDeclaration {
 };
 
 struct AstNodeTestDecl {
+    // nullptr if the test declaration has no name
     Buf *name;
 
     AstNode *body;
src/stage1/analyze.cpp
@@ -3871,13 +3871,18 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope
         return;
 
     Buf *decl_name_buf = node->data.test_decl.name;
+    Buf *test_name;
 
-    Buf *test_name = g->test_name_prefix ?
-        buf_sprintf("%s%s", buf_ptr(g->test_name_prefix), buf_ptr(decl_name_buf)) : decl_name_buf;
+    if (decl_name_buf != nullptr) {
+        test_name = g->test_name_prefix ?
+                buf_sprintf("%s%s", buf_ptr(g->test_name_prefix), buf_ptr(decl_name_buf)) : decl_name_buf;
 
-    if (g->test_filter != nullptr && buf_len(test_name) > 0 &&
-            strstr(buf_ptr(test_name), buf_ptr(g->test_filter)) == nullptr) {
-        return;
+        if (g->test_filter != nullptr && strstr(buf_ptr(test_name), buf_ptr(g->test_filter)) == nullptr) {
+            return;
+        }
+    } else {
+        // Unnamed test blocks are always executed.
+        test_name = buf_sprintf("%s", g->test_name_prefix ? buf_ptr(g->test_name_prefix) : "");
     }
 
     TldFn *tld_fn = heap::c_allocator.create<TldFn>();
src/stage1/parser.cpp
@@ -658,10 +658,10 @@ static AstNode *ast_parse_test_decl(ParseContext *pc) {
     if (test == nullptr)
         return nullptr;
 
-    Token *name = expect_token(pc, TokenIdStringLiteral);
+    Token *name = eat_token_if(pc, TokenIdStringLiteral);
     AstNode *block = ast_expect(pc, ast_parse_block);
     AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test);
-    res->data.test_decl.name = token_buf(name);
+    res->data.test_decl.name = name ? token_buf(name) : nullptr;
     res->data.test_decl.body = block;
     return res;
 }