Commit 9607bd90e6

Veikka Tuominen <git@vexu.eu>
2022-10-28 15:09:24
parser: improve error message for missing var/const before local variable
Closes #12721
1 parent 1ea1228
Changed files (3)
lib/std/zig/Ast.zig
@@ -197,7 +197,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
             });
         },
         .expected_labelable => {
-            return stream.print("expected 'while', 'for', 'inline', 'suspend', or '{{', found '{s}'", .{
+            return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
                 token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)].symbol(),
             });
         },
@@ -356,6 +356,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
         .next_field => {
             return stream.writeAll("field after declarations here");
         },
+        .expected_var_const => {
+            return stream.writeAll("expected 'var' or 'const' before variable declaration");
+        },
 
         .expected_token => {
             const found_tag = token_tags[parse_error.token + @boolToInt(parse_error.token_is_prev)];
@@ -2579,6 +2582,7 @@ pub const Error = struct {
         mismatched_binary_op_whitespace,
         invalid_ampersand_ampersand,
         c_style_container,
+        expected_var_const,
 
         zig_style_container,
         previous_field,
lib/std/zig/parse.zig
@@ -1118,7 +1118,18 @@ const Parser = struct {
         if (loop_stmt != 0) return loop_stmt;
 
         if (label_token != 0) {
-            return p.fail(.expected_labelable);
+            const after_colon = p.tok_i;
+            const node = try p.parseTypeExpr();
+            if (node != 0) {
+                const a = try p.parseByteAlign();
+                const b = try p.parseAddrSpace();
+                const c = try p.parseLinkSection();
+                const d = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
+                if (a != 0 or b != 0 or c != 0 or d != 0) {
+                    return p.failMsg(.{ .tag = .expected_var_const, .token = label_token });
+                }
+            }
+            return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
         }
 
         return null_node;
lib/std/zig/parser_test.zig
@@ -5145,6 +5145,32 @@ test "zig fmt: make single-line if no trailing comma" {
     );
 }
 
+test "zig fmt: missing const/var before local variable" {
+    try testError(
+        \\comptime {
+        \\    z: u32;
+        \\}
+        \\comptime {
+        \\    z: u32 align(1);
+        \\}
+        \\comptime {
+        \\    z: u32 addrspace(.generic);
+        \\}
+        \\comptime {
+        \\    z: u32 linksection("foo");
+        \\}
+        \\comptime {
+        \\    z: u32 = 1;
+        \\}
+    , &.{
+        .expected_labelable,
+        .expected_var_const,
+        .expected_var_const,
+        .expected_var_const,
+        .expected_var_const,
+    });
+}
+
 test "zig fmt: while continue expr" {
     try testCanonical(
         \\test {