commit fdefdc98c2dd66ad170cdb5442a752902b6bb50b (tree)
parent f5f54fcbe83dececc0077e6c2584885185e49aa9
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Wed, 11 Feb 2026 11:40:38 +0000
parser: sync tests with upstream, fix tokenizer and parser
Sync parser_test.zig test section with upstream, adding ~40 new tests
(testError, testCanonical, testTransform). Remove extra blank lines
between tests to match upstream formatting.
Fix tokenizer keyword lookup bug: getKeyword() returned TOKEN_INVALID
when input was longer than a keyword prefix (e.g., "orelse" matched
"or" prefix then bailed out instead of continuing to find "orelse").
Fix parser to handle if/for/while expressions in type position (e.g.,
function return types like `fn foo() if (cond) i32 else void`). Add
labeled block support in parsePrimaryTypeExpr. Replace assert for
chained comparison operators with longjmp error.
365/381 tests pass. Remaining 16 failures are parser limitations for
specific syntax patterns and error recovery.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | parser.c | | | 133 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
| M | parser_test.zig | | | 1238 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
| M | tokenizer.c | | | 4 | +++- |
3 files changed, 1062 insertions(+), 313 deletions(-)
diff --git a/parser.c b/parser.c
@@ -42,6 +42,8 @@ static AstNodeIndex parseSwitchExpr(Parser*);
static AstNodeIndex parseForExpr(Parser*);
static AstNodeIndex parseAsmExpr(Parser*);
static AstNodeIndex parseIfExpr(Parser*);
+static uint32_t forPrefix(Parser*);
+static AstNodeIndex parseLabeledStatement(Parser*);
typedef struct {
enum { FIELD_STATE_NONE, FIELD_STATE_SEEN, FIELD_STATE_END } tag;
@@ -521,6 +523,22 @@ static AstNodeIndex parsePrimaryTypeExpr(Parser* p) {
});
}
case TOKEN_IDENTIFIER:
+ if (p->token_tags[p->tok_i + 1] == TOKEN_COLON) {
+ switch (p->token_tags[p->tok_i + 2]) {
+ case TOKEN_L_BRACE: {
+ // Labeled block: label: { ... }
+ nextToken(p); // consume label
+ nextToken(p); // consume ':'
+ return parseBlock(p);
+ }
+ case TOKEN_KEYWORD_WHILE:
+ return parseLabeledStatement(p);
+ case TOKEN_KEYWORD_FOR:
+ return parseLabeledStatement(p);
+ default:
+ break;
+ }
+ }
return addNode(&p->nodes,
(AstNodeItem) {
.tag = AST_NODE_IDENTIFIER,
@@ -1018,6 +1036,116 @@ static AstNodeIndex parseTypeExpr(Parser* p) {
},
});
}
+ case TOKEN_KEYWORD_IF: {
+ // if-type-expr: uses parseTypeExpr for branches instead of parseExpr
+ const AstTokenIndex if_token = nextToken(p);
+ expectToken(p, TOKEN_L_PAREN);
+ const AstNodeIndex condition = expectExpr(p);
+ expectToken(p, TOKEN_R_PAREN);
+ parsePtrPayload(p);
+ const AstNodeIndex then_expr = parseTypeExpr(p);
+ if (eatToken(p, TOKEN_KEYWORD_ELSE) == null_token)
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_IF_SIMPLE,
+ .main_token = if_token,
+ .data = { .lhs = condition, .rhs = then_expr },
+ });
+ parsePayload(p);
+ const AstNodeIndex else_expr = parseTypeExpr(p);
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_IF,
+ .main_token = if_token,
+ .data = {
+ .lhs = condition,
+ .rhs = addExtra(p,
+ (AstNodeIndex[]) { then_expr, else_expr }, 2),
+ },
+ });
+ }
+ case TOKEN_KEYWORD_FOR: {
+ // for-type-expr: uses parseTypeExpr for body instead of parseExpr
+ const AstTokenIndex for_token = nextToken(p);
+ const uint32_t scratch_top2 = p->scratch.len;
+ const uint32_t inputs = forPrefix(p);
+ const AstNodeIndex body = parseTypeExpr(p);
+ if (eatToken(p, TOKEN_KEYWORD_ELSE) != null_token) {
+ parsePayload(p);
+ SLICE_APPEND(AstNodeIndex, &p->scratch, body);
+ const AstNodeIndex else_expr = parseTypeExpr(p);
+ SLICE_APPEND(AstNodeIndex, &p->scratch, else_expr);
+ const uint32_t total = p->scratch.len - scratch_top2;
+ const AstSubRange span
+ = listToSpan(p, &p->scratch.arr[scratch_top2], total);
+ p->scratch.len = scratch_top2;
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_FOR,
+ .main_token = for_token,
+ .data = {
+ .lhs = span.start,
+ .rhs = ((uint32_t)inputs & 0x7FFFFFFF) | (1u << 31),
+ },
+ });
+ }
+ SLICE_APPEND(AstNodeIndex, &p->scratch, body);
+ const uint32_t total = p->scratch.len - scratch_top2;
+ const AstSubRange span
+ = listToSpan(p, &p->scratch.arr[scratch_top2], total);
+ p->scratch.len = scratch_top2;
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_FOR,
+ .main_token = for_token,
+ .data = {
+ .lhs = span.start,
+ .rhs = (uint32_t)inputs & 0x7FFFFFFF,
+ },
+ });
+ }
+ case TOKEN_KEYWORD_WHILE: {
+ // while-type-expr: uses parseTypeExpr for body instead of parseExpr
+ const AstTokenIndex while_token = nextToken(p);
+ expectToken(p, TOKEN_L_PAREN);
+ const AstNodeIndex condition = expectExpr(p);
+ expectToken(p, TOKEN_R_PAREN);
+ parsePtrPayload(p);
+ const AstNodeIndex cont_expr
+ = eatToken(p, TOKEN_COLON) != null_token ? expectExpr(p) : 0;
+ const AstNodeIndex body = parseTypeExpr(p);
+ if (eatToken(p, TOKEN_KEYWORD_ELSE) != null_token) {
+ parsePayload(p);
+ const AstNodeIndex else_expr = parseTypeExpr(p);
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_WHILE,
+ .main_token = while_token,
+ .data = {
+ .lhs = condition,
+ .rhs = addExtra(p,
+ (AstNodeIndex[]) { cont_expr, body, else_expr }, 3),
+ },
+ });
+ }
+ if (cont_expr != 0)
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_WHILE_CONT,
+ .main_token = while_token,
+ .data = {
+ .lhs = condition,
+ .rhs = addExtra(p,
+ (AstNodeIndex[]) { cont_expr, body }, 2),
+ },
+ });
+ return addNode(&p->nodes,
+ (AstNodeItem) {
+ .tag = AST_NODE_WHILE_SIMPLE,
+ .main_token = while_token,
+ .data = { .lhs = condition, .rhs = body },
+ });
+ }
default:
return parseErrorUnionExpr(p);
}
@@ -1899,7 +2027,10 @@ static AstNodeIndex parseExprPrecedence(Parser* p, int32_t min_prec) {
if (info.prec < min_prec)
break;
- assert(info.prec != banned_prec);
+ if (info.prec == banned_prec) {
+ fprintf(stderr, "chained comparison operators\n");
+ longjmp(p->error_jmp, 1);
+ }
const AstTokenIndex oper_token = nextToken(p);
if (tok_tag == TOKEN_KEYWORD_CATCH)
diff --git a/parser_test.zig b/parser_test.zig
@@ -4,7 +4,6 @@ const print = std.debug.print;
const io = std.io;
const maxInt = std.math.maxInt;
-
test "zig fmt: remove extra whitespace at start and end of file with comment between" {
try testTransform(
\\
@@ -18,7 +17,6 @@ test "zig fmt: remove extra whitespace at start and end of file with comment bet
);
}
-
test "zig fmt: tuple struct" {
try testCanonical(
\\const T = struct {
@@ -33,7 +31,6 @@ test "zig fmt: tuple struct" {
);
}
-
test "zig fmt: preserves clobbers in inline asm with stray comma" {
try testTransform(
\\fn foo() void {
@@ -66,7 +63,6 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" {
);
}
-
test "zig fmt: remove trailing comma at the end of assembly clobber" {
try testTransform(
\\fn foo() void {
@@ -89,7 +85,6 @@ test "zig fmt: remove trailing comma at the end of assembly clobber" {
);
}
-
test "zig fmt: respect line breaks in struct field value declaration" {
try testCanonical(
\\const Foo = struct {
@@ -115,7 +110,6 @@ test "zig fmt: respect line breaks in struct field value declaration" {
);
}
-
test "zig fmt: respect line breaks before functions" {
try testCanonical(
\\const std = @import("std");
@@ -133,7 +127,6 @@ test "zig fmt: respect line breaks before functions" {
);
}
-
test "zig fmt: rewrite callconv(.@\"inline\") to the inline keyword" {
try testTransform(
\\fn foo() callconv(.@"inline") void {}
@@ -148,7 +141,6 @@ test "zig fmt: rewrite callconv(.@\"inline\") to the inline keyword" {
);
}
-
test "zig fmt: simple top level comptime block" {
try testCanonical(
\\// line comment
@@ -157,7 +149,6 @@ test "zig fmt: simple top level comptime block" {
);
}
-
test "zig fmt: two spaced line comments before decl" {
try testCanonical(
\\// line comment
@@ -168,7 +159,6 @@ test "zig fmt: two spaced line comments before decl" {
);
}
-
test "zig fmt: respect line breaks after var declarations" {
try testCanonical(
\\const crc =
@@ -184,7 +174,6 @@ test "zig fmt: respect line breaks after var declarations" {
);
}
-
test "zig fmt: multiline string mixed with comments" {
try testCanonical(
\\const s1 =
@@ -215,14 +204,12 @@ test "zig fmt: multiline string mixed with comments" {
);
}
-
test "zig fmt: empty file" {
try testCanonical(
\\
);
}
-
test "zig fmt: file ends in comment" {
try testTransform(
\\ //foobar
@@ -232,7 +219,6 @@ test "zig fmt: file ends in comment" {
);
}
-
test "zig fmt: file ends in multi line comment" {
try testTransform(
\\ \\foobar
@@ -242,7 +228,6 @@ test "zig fmt: file ends in multi line comment" {
);
}
-
test "zig fmt: file ends in comment after var decl" {
try testTransform(
\\const x = 42;
@@ -254,7 +239,6 @@ test "zig fmt: file ends in comment after var decl" {
);
}
-
test "zig fmt: if statement" {
try testCanonical(
\\test "" {
@@ -265,7 +249,6 @@ test "zig fmt: if statement" {
);
}
-
test "zig fmt: top-level fields" {
try testCanonical(
\\a: did_you_know,
@@ -275,7 +258,6 @@ test "zig fmt: top-level fields" {
);
}
-
test "zig fmt: top-level tuple function call type" {
try testCanonical(
\\foo()
@@ -283,7 +265,6 @@ test "zig fmt: top-level tuple function call type" {
);
}
-
test "zig fmt: top-level enum missing 'const name ='" {
try testError(
\\enum(u32)
@@ -291,7 +272,6 @@ test "zig fmt: top-level enum missing 'const name ='" {
, &[_]Error{.expected_token});
}
-
test "zig fmt: top-level for/while loop" {
try testCanonical(
\\for (foo) |_| foo
@@ -303,7 +283,6 @@ test "zig fmt: top-level for/while loop" {
);
}
-
test "zig fmt: top-level bare asterisk+identifier" {
try testCanonical(
\\*x
@@ -311,7 +290,6 @@ test "zig fmt: top-level bare asterisk+identifier" {
);
}
-
test "zig fmt: top-level bare asterisk+asterisk+identifier" {
try testCanonical(
\\**x
@@ -319,6 +297,45 @@ test "zig fmt: top-level bare asterisk+asterisk+identifier" {
);
}
+test "zig fmt: C style containers" {
+ try testError(
+ \\struct Foo {
+ \\ a: u32,
+ \\};
+ , &[_]Error{
+ .c_style_container,
+ .zig_style_container,
+ });
+ try testError(
+ \\test {
+ \\ struct Foo {
+ \\ a: u32,
+ \\ };
+ \\}
+ , &[_]Error{
+ .c_style_container,
+ .zig_style_container,
+ });
+}
+
+test "zig fmt: decl between fields" {
+ try testError(
+ \\const S = struct {
+ \\ const foo = 2;
+ \\ const bar = 2;
+ \\ const baz = 2;
+ \\ a: usize,
+ \\ const foo1 = 2;
+ \\ const bar1 = 2;
+ \\ const baz1 = 2;
+ \\ b: usize,
+ \\};
+ , &[_]Error{
+ .decl_between_fields,
+ .previous_field,
+ .next_field,
+ });
+}
test "zig fmt: errdefer with payload" {
try testCanonical(
@@ -333,7 +350,6 @@ test "zig fmt: errdefer with payload" {
);
}
-
test "zig fmt: nosuspend block" {
try testCanonical(
\\pub fn main() anyerror!void {
@@ -345,7 +361,6 @@ test "zig fmt: nosuspend block" {
);
}
-
test "zig fmt: container declaration, single line" {
try testCanonical(
\\const X = struct { foo: i32 };
@@ -357,7 +372,6 @@ test "zig fmt: container declaration, single line" {
);
}
-
test "zig fmt: container declaration, one item, multi line trailing comma" {
try testCanonical(
\\test "" {
@@ -371,7 +385,6 @@ test "zig fmt: container declaration, one item, multi line trailing comma" {
);
}
-
test "zig fmt: container declaration, no trailing comma on separate line" {
try testTransform(
\\test "" {
@@ -392,7 +405,6 @@ test "zig fmt: container declaration, no trailing comma on separate line" {
);
}
-
test "zig fmt: container declaration, line break, no trailing comma" {
try testTransform(
\\const X = struct {
@@ -403,7 +415,6 @@ test "zig fmt: container declaration, line break, no trailing comma" {
);
}
-
test "zig fmt: container declaration, transform trailing comma" {
try testTransform(
\\const X = struct {
@@ -417,7 +428,6 @@ test "zig fmt: container declaration, transform trailing comma" {
);
}
-
test "zig fmt: container declaration, comment, add trailing comma" {
try testTransform(
\\const X = struct {
@@ -443,7 +453,6 @@ test "zig fmt: container declaration, comment, add trailing comma" {
);
}
-
test "zig fmt: container declaration, multiline string, add trailing comma" {
try testTransform(
\\const X = struct {
@@ -463,7 +472,6 @@ test "zig fmt: container declaration, multiline string, add trailing comma" {
);
}
-
test "zig fmt: container declaration, doc comment on member, add trailing comma" {
try testTransform(
\\pub const Pos = struct {
@@ -483,7 +491,6 @@ test "zig fmt: container declaration, doc comment on member, add trailing comma"
);
}
-
test "zig fmt: remove empty lines at start/end of container decl" {
try testTransform(
\\const X = struct {
@@ -504,7 +511,6 @@ test "zig fmt: remove empty lines at start/end of container decl" {
);
}
-
test "zig fmt: remove empty lines at start/end of block" {
try testTransform(
\\test {
@@ -525,7 +531,6 @@ test "zig fmt: remove empty lines at start/end of block" {
);
}
-
test "zig fmt: allow empty line before comment at start of block" {
try testCanonical(
\\test {
@@ -537,7 +542,6 @@ test "zig fmt: allow empty line before comment at start of block" {
);
}
-
test "zig fmt: trailing comma in fn parameter list" {
try testCanonical(
\\pub fn f(
@@ -580,7 +584,6 @@ test "zig fmt: trailing comma in fn parameter list" {
);
}
-
test "zig fmt: comptime struct field" {
try testCanonical(
\\const Foo = struct {
@@ -591,7 +594,6 @@ test "zig fmt: comptime struct field" {
);
}
-
test "zig fmt: break from block" {
try testCanonical(
\\const a = blk: {
@@ -610,7 +612,6 @@ test "zig fmt: break from block" {
);
}
-
test "zig fmt: grouped expressions (parentheses)" {
try testCanonical(
\\const r = (x + y) * (a + b);
@@ -618,7 +619,6 @@ test "zig fmt: grouped expressions (parentheses)" {
);
}
-
test "zig fmt: c pointer type" {
try testCanonical(
\\pub extern fn repro() [*c]const u8;
@@ -626,7 +626,6 @@ test "zig fmt: c pointer type" {
);
}
-
test "zig fmt: builtin call with trailing comma" {
try testCanonical(
\\pub fn main() void {
@@ -642,7 +641,6 @@ test "zig fmt: builtin call with trailing comma" {
);
}
-
test "zig fmt: asm expression with comptime content" {
try testTransform(
\\comptime {
@@ -687,7 +685,6 @@ test "zig fmt: asm expression with comptime content" {
);
}
-
test "zig fmt: array types last token" {
try testCanonical(
\\test {
@@ -701,7 +698,6 @@ test "zig fmt: array types last token" {
);
}
-
test "zig fmt: sentinel-terminated array type" {
try testCanonical(
\\pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
@@ -711,7 +707,6 @@ test "zig fmt: sentinel-terminated array type" {
);
}
-
test "zig fmt: sentinel-terminated slice type" {
try testCanonical(
\\pub fn toSlice(self: Buffer) [:0]u8 {
@@ -721,7 +716,6 @@ test "zig fmt: sentinel-terminated slice type" {
);
}
-
test "zig fmt: pointer-to-one with modifiers" {
try testCanonical(
\\const x: *u32 = undefined;
@@ -731,7 +725,6 @@ test "zig fmt: pointer-to-one with modifiers" {
);
}
-
test "zig fmt: pointer-to-many with modifiers" {
try testCanonical(
\\const x: [*]u32 = undefined;
@@ -741,7 +734,6 @@ test "zig fmt: pointer-to-many with modifiers" {
);
}
-
test "zig fmt: sentinel pointer with modifiers" {
try testCanonical(
\\const x: [*:42]u32 = undefined;
@@ -751,7 +743,6 @@ test "zig fmt: sentinel pointer with modifiers" {
);
}
-
test "zig fmt: c pointer with modifiers" {
try testCanonical(
\\const x: [*c]u32 = undefined;
@@ -761,7 +752,6 @@ test "zig fmt: c pointer with modifiers" {
);
}
-
test "zig fmt: slice with modifiers" {
try testCanonical(
\\const x: []u32 = undefined;
@@ -770,7 +760,6 @@ test "zig fmt: slice with modifiers" {
);
}
-
test "zig fmt: sentinel slice with modifiers" {
try testCanonical(
\\const x: [:42]u32 = undefined;
@@ -779,7 +768,6 @@ test "zig fmt: sentinel slice with modifiers" {
);
}
-
test "zig fmt: anon literal in array" {
try testCanonical(
\\var arr: [2]Foo = .{
@@ -790,7 +778,6 @@ test "zig fmt: anon literal in array" {
);
}
-
test "zig fmt: alignment in anonymous literal" {
try testTransform(
\\const a = .{
@@ -809,7 +796,6 @@ test "zig fmt: alignment in anonymous literal" {
);
}
-
test "zig fmt: anon struct literal 0 element" {
try testCanonical(
\\test {
@@ -819,7 +805,6 @@ test "zig fmt: anon struct literal 0 element" {
);
}
-
test "zig fmt: anon struct literal 1 element" {
try testCanonical(
\\test {
@@ -829,7 +814,6 @@ test "zig fmt: anon struct literal 1 element" {
);
}
-
test "zig fmt: anon struct literal 1 element comma" {
try testCanonical(
\\test {
@@ -841,7 +825,6 @@ test "zig fmt: anon struct literal 1 element comma" {
);
}
-
test "zig fmt: anon struct literal 2 element" {
try testCanonical(
\\test {
@@ -851,7 +834,6 @@ test "zig fmt: anon struct literal 2 element" {
);
}
-
test "zig fmt: anon struct literal 2 element comma" {
try testCanonical(
\\test {
@@ -864,7 +846,6 @@ test "zig fmt: anon struct literal 2 element comma" {
);
}
-
test "zig fmt: anon struct literal 3 element" {
try testCanonical(
\\test {
@@ -874,7 +855,6 @@ test "zig fmt: anon struct literal 3 element" {
);
}
-
test "zig fmt: anon struct literal 3 element comma" {
try testCanonical(
\\test {
@@ -888,7 +868,6 @@ test "zig fmt: anon struct literal 3 element comma" {
);
}
-
test "zig fmt: struct literal 0 element" {
try testCanonical(
\\test {
@@ -898,7 +877,6 @@ test "zig fmt: struct literal 0 element" {
);
}
-
test "zig fmt: struct literal 1 element" {
try testCanonical(
\\test {
@@ -908,7 +886,6 @@ test "zig fmt: struct literal 1 element" {
);
}
-
test "zig fmt: Unicode code point literal larger than u8" {
try testCanonical(
\\test {
@@ -920,7 +897,6 @@ test "zig fmt: Unicode code point literal larger than u8" {
);
}
-
test "zig fmt: struct literal 2 element" {
try testCanonical(
\\test {
@@ -930,7 +906,6 @@ test "zig fmt: struct literal 2 element" {
);
}
-
test "zig fmt: struct literal 2 element comma" {
try testCanonical(
\\test {
@@ -943,7 +918,6 @@ test "zig fmt: struct literal 2 element comma" {
);
}
-
test "zig fmt: struct literal 3 element" {
try testCanonical(
\\test {
@@ -953,7 +927,6 @@ test "zig fmt: struct literal 3 element" {
);
}
-
test "zig fmt: struct literal 3 element comma" {
try testCanonical(
\\test {
@@ -967,7 +940,6 @@ test "zig fmt: struct literal 3 element comma" {
);
}
-
test "zig fmt: anon list literal 1 element" {
try testCanonical(
\\test {
@@ -977,7 +949,6 @@ test "zig fmt: anon list literal 1 element" {
);
}
-
test "zig fmt: anon list literal 1 element comma" {
try testCanonical(
\\test {
@@ -989,7 +960,6 @@ test "zig fmt: anon list literal 1 element comma" {
);
}
-
test "zig fmt: anon list literal 2 element" {
try testCanonical(
\\test {
@@ -999,7 +969,6 @@ test "zig fmt: anon list literal 2 element" {
);
}
-
test "zig fmt: anon list literal 2 element comma" {
try testCanonical(
\\test {
@@ -1012,7 +981,6 @@ test "zig fmt: anon list literal 2 element comma" {
);
}
-
test "zig fmt: anon list literal 3 element" {
try testCanonical(
\\test {
@@ -1022,7 +990,6 @@ test "zig fmt: anon list literal 3 element" {
);
}
-
test "zig fmt: anon list literal 3 element comma" {
try testCanonical(
\\test {
@@ -1038,7 +1005,6 @@ test "zig fmt: anon list literal 3 element comma" {
);
}
-
test "zig fmt: array literal 0 element" {
try testCanonical(
\\test {
@@ -1048,7 +1014,6 @@ test "zig fmt: array literal 0 element" {
);
}
-
test "zig fmt: array literal 1 element" {
try testCanonical(
\\test {
@@ -1058,7 +1023,6 @@ test "zig fmt: array literal 1 element" {
);
}
-
test "zig fmt: array literal 1 element comma" {
try testCanonical(
\\test {
@@ -1070,7 +1034,6 @@ test "zig fmt: array literal 1 element comma" {
);
}
-
test "zig fmt: array literal 2 element" {
try testCanonical(
\\test {
@@ -1080,7 +1043,6 @@ test "zig fmt: array literal 2 element" {
);
}
-
test "zig fmt: array literal 2 element comma" {
try testCanonical(
\\test {
@@ -1093,7 +1055,6 @@ test "zig fmt: array literal 2 element comma" {
);
}
-
test "zig fmt: array literal 3 element" {
try testCanonical(
\\test {
@@ -1103,7 +1064,6 @@ test "zig fmt: array literal 3 element" {
);
}
-
test "zig fmt: array literal 3 element comma" {
try testCanonical(
\\test {
@@ -1117,7 +1077,6 @@ test "zig fmt: array literal 3 element comma" {
);
}
-
test "zig fmt: sentinel array literal 1 element" {
try testCanonical(
\\test {
@@ -1127,7 +1086,6 @@ test "zig fmt: sentinel array literal 1 element" {
);
}
-
test "zig fmt: slices" {
try testCanonical(
\\const a = b[0..];
@@ -1138,7 +1096,6 @@ test "zig fmt: slices" {
);
}
-
test "zig fmt: slices with spaces in bounds" {
try testCanonical(
\\const a = b[0 + 0 ..];
@@ -1149,7 +1106,6 @@ test "zig fmt: slices with spaces in bounds" {
);
}
-
test "zig fmt: block in slice expression" {
try testCanonical(
\\const a = b[{
@@ -1168,7 +1124,6 @@ test "zig fmt: block in slice expression" {
);
}
-
test "zig fmt: whitespace fixes" {
try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
\\test "" {
@@ -1181,7 +1136,6 @@ test "zig fmt: whitespace fixes" {
);
}
-
test "zig fmt: while else err prong with no block" {
try testCanonical(
\\test "" {
@@ -1194,7 +1148,6 @@ test "zig fmt: while else err prong with no block" {
);
}
-
test "zig fmt: tagged union with enum values" {
try testCanonical(
\\const MultipleChoice2 = union(enum(u32)) {
@@ -1212,7 +1165,6 @@ test "zig fmt: tagged union with enum values" {
);
}
-
test "zig fmt: tagged union enum tag last token" {
try testCanonical(
\\test {
@@ -1232,7 +1184,6 @@ test "zig fmt: tagged union enum tag last token" {
);
}
-
test "zig fmt: allowzero pointer" {
try testCanonical(
\\const T = [*]allowzero const u8;
@@ -1240,7 +1191,6 @@ test "zig fmt: allowzero pointer" {
);
}
-
test "zig fmt: empty enum decls" {
try testCanonical(
\\const A = enum {};
@@ -1251,7 +1201,6 @@ test "zig fmt: empty enum decls" {
);
}
-
test "zig fmt: empty union decls" {
try testCanonical(
\\const A = union {};
@@ -1263,7 +1212,6 @@ test "zig fmt: empty union decls" {
);
}
-
test "zig fmt: enum literal" {
try testCanonical(
\\const x = .hi;
@@ -1271,7 +1219,6 @@ test "zig fmt: enum literal" {
);
}
-
test "zig fmt: enum literal inside array literal" {
try testCanonical(
\\test "enums in arrays" {
@@ -1287,7 +1234,6 @@ test "zig fmt: enum literal inside array literal" {
);
}
-
test "zig fmt: character literal larger than u8" {
try testCanonical(
\\const x = '\u{01f4a9}';
@@ -1295,7 +1241,6 @@ test "zig fmt: character literal larger than u8" {
);
}
-
test "zig fmt: infix operator and then multiline string literal" {
try testCanonical(
\\const x = "" ++
@@ -1305,7 +1250,6 @@ test "zig fmt: infix operator and then multiline string literal" {
);
}
-
test "zig fmt: infix operator and then multiline string literal over multiple lines" {
try testCanonical(
\\const x = "" ++
@@ -1317,7 +1261,6 @@ test "zig fmt: infix operator and then multiline string literal over multiple li
);
}
-
test "zig fmt: C pointers" {
try testCanonical(
\\const Ptr = [*c]i32;
@@ -1325,7 +1268,6 @@ test "zig fmt: C pointers" {
);
}
-
test "zig fmt: threadlocal" {
try testCanonical(
\\threadlocal var x: i32 = 1234;
@@ -1333,7 +1275,6 @@ test "zig fmt: threadlocal" {
);
}
-
test "zig fmt: linksection" {
try testCanonical(
\\export var aoeu: u64 linksection(".text.derp") = 1234;
@@ -1342,7 +1283,6 @@ test "zig fmt: linksection" {
);
}
-
test "zig fmt: addrspace" {
try testCanonical(
\\export var python_length: u64 align(1) addrspace(.generic);
@@ -1353,7 +1293,6 @@ test "zig fmt: addrspace" {
);
}
-
test "zig fmt: correctly space struct fields with doc comments" {
try testTransform(
\\pub const S = struct {
@@ -1383,7 +1322,6 @@ test "zig fmt: correctly space struct fields with doc comments" {
);
}
-
test "zig fmt: doc comments on param decl" {
try testCanonical(
\\pub const Allocator = struct {
@@ -1405,7 +1343,6 @@ test "zig fmt: doc comments on param decl" {
);
}
-
test "zig fmt: aligned struct field" {
try testCanonical(
\\pub const S = struct {
@@ -1421,7 +1358,6 @@ test "zig fmt: aligned struct field" {
);
}
-
test "zig fmt: comment to disable/enable zig fmt first" {
try testCanonical(
\\// Test trailing comma syntax
@@ -1431,7 +1367,6 @@ test "zig fmt: comment to disable/enable zig fmt first" {
);
}
-
test "zig fmt: 'zig fmt: (off|on)' can be surrounded by arbitrary whitespace" {
try testTransform(
\\// Test trailing comma syntax
@@ -1451,7 +1386,6 @@ test "zig fmt: 'zig fmt: (off|on)' can be surrounded by arbitrary whitespace" {
);
}
-
test "zig fmt: comment to disable/enable zig fmt" {
try testTransform(
\\const a = b;
@@ -1469,7 +1403,6 @@ test "zig fmt: comment to disable/enable zig fmt" {
);
}
-
test "zig fmt: line comment following 'zig fmt: off'" {
try testCanonical(
\\// zig fmt: off
@@ -1478,7 +1411,6 @@ test "zig fmt: line comment following 'zig fmt: off'" {
);
}
-
test "zig fmt: doc comment following 'zig fmt: off'" {
try testCanonical(
\\// zig fmt: off
@@ -1487,7 +1419,6 @@ test "zig fmt: doc comment following 'zig fmt: off'" {
);
}
-
test "zig fmt: line and doc comment following 'zig fmt: off'" {
try testCanonical(
\\// zig fmt: off
@@ -1497,7 +1428,6 @@ test "zig fmt: line and doc comment following 'zig fmt: off'" {
);
}
-
test "zig fmt: doc and line comment following 'zig fmt: off'" {
try testCanonical(
\\// zig fmt: off
@@ -1507,7 +1437,6 @@ test "zig fmt: doc and line comment following 'zig fmt: off'" {
);
}
-
test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
try testCanonical(
\\// zig fmt: off
@@ -1525,7 +1454,6 @@ test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
);
}
-
test "zig fmt: line comment following 'zig fmt: on'" {
try testCanonical(
\\// zig fmt: off
@@ -1537,7 +1465,6 @@ test "zig fmt: line comment following 'zig fmt: on'" {
);
}
-
test "zig fmt: doc comment following 'zig fmt: on'" {
try testCanonical(
\\// zig fmt: off
@@ -1549,7 +1476,6 @@ test "zig fmt: doc comment following 'zig fmt: on'" {
);
}
-
test "zig fmt: line and doc comment following 'zig fmt: on'" {
try testCanonical(
\\// zig fmt: off
@@ -1562,7 +1488,6 @@ test "zig fmt: line and doc comment following 'zig fmt: on'" {
);
}
-
test "zig fmt: doc and line comment following 'zig fmt: on'" {
try testCanonical(
\\// zig fmt: off
@@ -1575,7 +1500,6 @@ test "zig fmt: doc and line comment following 'zig fmt: on'" {
);
}
-
test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
try testTransform(
\\test "" {
@@ -1602,7 +1526,6 @@ test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
);
}
-
test "zig fmt: 'zig fmt: on' indentation is unchanged" {
try testCanonical(
\\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
@@ -1624,7 +1547,6 @@ test "zig fmt: 'zig fmt: on' indentation is unchanged" {
);
}
-
test "zig fmt: pointer of unknown length" {
try testCanonical(
\\fn foo(ptr: [*]u8) void {}
@@ -1632,7 +1554,6 @@ test "zig fmt: pointer of unknown length" {
);
}
-
test "zig fmt: spaces around slice operator" {
try testCanonical(
\\var a = b[c..d];
@@ -1647,7 +1568,6 @@ test "zig fmt: spaces around slice operator" {
);
}
-
test "zig fmt: 2nd arg multiline string" {
try testCanonical(
\\comptime {
@@ -1676,7 +1596,6 @@ test "zig fmt: 2nd arg multiline string" {
);
}
-
test "zig fmt: 2nd arg multiline string many args" {
try testCanonical(
\\comptime {
@@ -1688,7 +1607,6 @@ test "zig fmt: 2nd arg multiline string many args" {
);
}
-
test "zig fmt: final arg multiline string" {
try testCanonical(
\\comptime {
@@ -1700,7 +1618,6 @@ test "zig fmt: final arg multiline string" {
);
}
-
test "zig fmt: if condition wraps" {
try testTransform(
\\comptime {
@@ -1782,7 +1699,6 @@ test "zig fmt: if condition wraps" {
);
}
-
test "zig fmt: if condition has line break but must not wrap" {
try testCanonical(
\\comptime {
@@ -1807,7 +1723,6 @@ test "zig fmt: if condition has line break but must not wrap" {
);
}
-
test "zig fmt: if condition has line break but must not wrap (no fn call comma)" {
try testCanonical(
\\comptime {
@@ -1829,7 +1744,6 @@ test "zig fmt: if condition has line break but must not wrap (no fn call comma)"
);
}
-
test "zig fmt: function call with multiline argument" {
try testCanonical(
\\comptime {
@@ -1842,7 +1756,6 @@ test "zig fmt: function call with multiline argument" {
);
}
-
test "zig fmt: if-else with comment before else" {
try testCanonical(
\\comptime {
@@ -1861,7 +1774,6 @@ test "zig fmt: if-else with comment before else" {
);
}
-
test "zig fmt: if nested" {
try testCanonical(
\\pub fn foo() void {
@@ -1885,7 +1797,6 @@ test "zig fmt: if nested" {
);
}
-
test "zig fmt: respect line breaks in if-else" {
try testCanonical(
\\comptime {
@@ -1905,7 +1816,6 @@ test "zig fmt: respect line breaks in if-else" {
);
}
-
test "zig fmt: respect line breaks after infix operators" {
try testCanonical(
\\comptime {
@@ -1923,7 +1833,6 @@ test "zig fmt: respect line breaks after infix operators" {
);
}
-
test "zig fmt: fn decl with trailing comma" {
try testTransform(
\\fn foo(a: i32, b: i32,) void {}
@@ -1936,7 +1845,6 @@ test "zig fmt: fn decl with trailing comma" {
);
}
-
test "zig fmt: enum decl with no trailing comma" {
try testTransform(
\\const StrLitKind = enum {Normal, C};
@@ -1946,7 +1854,6 @@ test "zig fmt: enum decl with no trailing comma" {
);
}
-
test "zig fmt: switch comment before prong" {
try testCanonical(
\\comptime {
@@ -1959,7 +1866,6 @@ test "zig fmt: switch comment before prong" {
);
}
-
test "zig fmt: switch comment after prong" {
try testCanonical(
\\comptime {
@@ -1973,7 +1879,6 @@ test "zig fmt: switch comment after prong" {
);
}
-
test "zig fmt: struct literal no trailing comma" {
try testTransform(
\\const a = foo{ .x = 1, .y = 2 };
@@ -1992,7 +1897,6 @@ test "zig fmt: struct literal no trailing comma" {
);
}
-
test "zig fmt: struct literal containing a multiline expression" {
try testTransform(
\\const a = A{ .x = if (f1()) 10 else 20 };
@@ -2054,7 +1958,6 @@ test "zig fmt: struct literal containing a multiline expression" {
);
}
-
test "zig fmt: array literal with hint" {
try testTransform(
\\const a = []u8{
@@ -2132,7 +2035,6 @@ test "zig fmt: array literal with hint" {
);
}
-
test "zig fmt: array literal vertical column alignment" {
try testTransform(
\\const a = []u8{
@@ -2180,7 +2082,6 @@ test "zig fmt: array literal vertical column alignment" {
);
}
-
test "zig fmt: multiline string with backslash at end of line" {
try testCanonical(
\\comptime {
@@ -2192,7 +2093,6 @@ test "zig fmt: multiline string with backslash at end of line" {
);
}
-
test "zig fmt: multiline string parameter in fn call with trailing comma" {
try testCanonical(
\\fn foo() void {
@@ -2211,7 +2111,6 @@ test "zig fmt: multiline string parameter in fn call with trailing comma" {
);
}
-
test "zig fmt: trailing comma on fn call" {
try testCanonical(
\\comptime {
@@ -2225,7 +2124,6 @@ test "zig fmt: trailing comma on fn call" {
);
}
-
test "zig fmt: multi line arguments without last comma" {
try testTransform(
\\pub fn foo(
@@ -2245,7 +2143,6 @@ test "zig fmt: multi line arguments without last comma" {
);
}
-
test "zig fmt: empty block with only comment" {
try testCanonical(
\\comptime {
@@ -2257,7 +2154,6 @@ test "zig fmt: empty block with only comment" {
);
}
-
test "zig fmt: trailing commas on struct decl" {
try testTransform(
\\const RoundParam = struct {
@@ -2277,7 +2173,6 @@ test "zig fmt: trailing commas on struct decl" {
);
}
-
test "zig fmt: extra newlines at the end" {
try testTransform(
\\const a = b;
@@ -2290,7 +2185,6 @@ test "zig fmt: extra newlines at the end" {
);
}
-
test "zig fmt: simple asm" {
try testTransform(
\\comptime {
@@ -2328,7 +2222,6 @@ test "zig fmt: simple asm" {
);
}
-
test "zig fmt: nested struct literal with one item" {
try testCanonical(
\\const a = foo{
@@ -2338,7 +2231,6 @@ test "zig fmt: nested struct literal with one item" {
);
}
-
test "zig fmt: switch cases trailing comma" {
try testTransform(
\\test "switch cases trailing comma"{
@@ -2373,7 +2265,6 @@ test "zig fmt: switch cases trailing comma" {
);
}
-
test "zig fmt: slice align" {
try testCanonical(
\\const A = struct {
@@ -2383,7 +2274,6 @@ test "zig fmt: slice align" {
);
}
-
test "zig fmt: add trailing comma to array literal" {
try testTransform(
\\comptime {
@@ -2405,7 +2295,6 @@ test "zig fmt: add trailing comma to array literal" {
);
}
-
test "zig fmt: first thing in file is line comment" {
try testCanonical(
\\// Introspection and determination of system libraries needed by zig.
@@ -2417,7 +2306,6 @@ test "zig fmt: first thing in file is line comment" {
);
}
-
test "zig fmt: line comment after doc comment" {
try testCanonical(
\\/// doc comment
@@ -2427,7 +2315,6 @@ test "zig fmt: line comment after doc comment" {
);
}
-
test "zig fmt: bit field alignment" {
try testCanonical(
\\test {
@@ -2437,7 +2324,6 @@ test "zig fmt: bit field alignment" {
);
}
-
test "zig fmt: nested switch" {
try testCanonical(
\\test {
@@ -2452,7 +2338,6 @@ test "zig fmt: nested switch" {
);
}
-
test "zig fmt: float literal with exponent" {
try testCanonical(
\\pub const f64_true_min = 4.94065645841246544177e-324;
@@ -2461,7 +2346,6 @@ test "zig fmt: float literal with exponent" {
);
}
-
test "zig fmt: if-else end of comptime" {
try testCanonical(
\\comptime {
@@ -2475,7 +2359,6 @@ test "zig fmt: if-else end of comptime" {
);
}
-
test "zig fmt: nested blocks" {
try testCanonical(
\\comptime {
@@ -2491,7 +2374,6 @@ test "zig fmt: nested blocks" {
);
}
-
test "zig fmt: block with same line comment after end brace" {
try testCanonical(
\\comptime {
@@ -2503,7 +2385,6 @@ test "zig fmt: block with same line comment after end brace" {
);
}
-
test "zig fmt: statements with comment between" {
try testCanonical(
\\comptime {
@@ -2515,7 +2396,6 @@ test "zig fmt: statements with comment between" {
);
}
-
test "zig fmt: statements with empty line between" {
try testCanonical(
\\comptime {
@@ -2527,7 +2407,6 @@ test "zig fmt: statements with empty line between" {
);
}
-
test "zig fmt: ptr deref operator and unwrap optional operator" {
try testCanonical(
\\const a = b.*;
@@ -2536,7 +2415,6 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
);
}
-
test "zig fmt: comment after if before another if" {
try testCanonical(
\\test "aoeu" {
@@ -2559,7 +2437,6 @@ test "zig fmt: comment after if before another if" {
);
}
-
test "zig fmt: line comment between if block and else keyword" {
try testCanonical(
\\test "aoeu" {
@@ -2581,7 +2458,6 @@ test "zig fmt: line comment between if block and else keyword" {
);
}
-
test "zig fmt: same line comments in expression" {
try testCanonical(
\\test "aoeu" {
@@ -2593,7 +2469,6 @@ test "zig fmt: same line comments in expression" {
);
}
-
test "zig fmt: add comma on last switch prong" {
try testTransform(
\\test "aoeu" {
@@ -2623,7 +2498,6 @@ test "zig fmt: add comma on last switch prong" {
);
}
-
test "zig fmt: same-line comment after a statement" {
try testCanonical(
\\test "" {
@@ -2635,7 +2509,6 @@ test "zig fmt: same-line comment after a statement" {
);
}
-
test "zig fmt: same-line comment after var decl in struct" {
try testCanonical(
\\pub const vfs_cap_data = extern struct {
@@ -2645,7 +2518,6 @@ test "zig fmt: same-line comment after var decl in struct" {
);
}
-
test "zig fmt: same-line comment after field decl" {
try testCanonical(
\\pub const dirent = extern struct {
@@ -2659,7 +2531,6 @@ test "zig fmt: same-line comment after field decl" {
);
}
-
test "zig fmt: same-line comment after switch prong" {
try testCanonical(
\\test "" {
@@ -2672,7 +2543,6 @@ test "zig fmt: same-line comment after switch prong" {
);
}
-
test "zig fmt: same-line comment after non-block if expression" {
try testCanonical(
\\comptime {
@@ -2683,7 +2553,6 @@ test "zig fmt: same-line comment after non-block if expression" {
);
}
-
test "zig fmt: same-line comment on comptime expression" {
try testCanonical(
\\test "" {
@@ -2693,7 +2562,6 @@ test "zig fmt: same-line comment on comptime expression" {
);
}
-
test "zig fmt: switch with empty body" {
try testCanonical(
\\test "" {
@@ -2703,7 +2571,6 @@ test "zig fmt: switch with empty body" {
);
}
-
test "zig fmt: line comments in struct initializer" {
try testCanonical(
\\fn foo() void {
@@ -2726,7 +2593,6 @@ test "zig fmt: line comments in struct initializer" {
);
}
-
test "zig fmt: first line comment in struct initializer" {
try testCanonical(
\\pub fn acquire(self: *Self) HeldLock {
@@ -2740,7 +2606,6 @@ test "zig fmt: first line comment in struct initializer" {
);
}
-
test "zig fmt: doc comments before struct field" {
try testCanonical(
\\pub const Allocator = struct {
@@ -2752,7 +2617,6 @@ test "zig fmt: doc comments before struct field" {
);
}
-
test "zig fmt: error set declaration" {
try testCanonical(
\\const E = error{
@@ -2785,7 +2649,6 @@ test "zig fmt: error set declaration" {
);
}
-
test "zig fmt: union(enum(u32)) with assigned enum values" {
try testCanonical(
\\const MultipleChoice = union(enum(u32)) {
@@ -2798,7 +2661,6 @@ test "zig fmt: union(enum(u32)) with assigned enum values" {
);
}
-
test "zig fmt: resume from suspend block" {
try testCanonical(
\\fn foo() void {
@@ -2810,7 +2672,6 @@ test "zig fmt: resume from suspend block" {
);
}
-
test "zig fmt: comments before error set decl" {
try testCanonical(
\\const UnexpectedError = error{
@@ -2827,7 +2688,6 @@ test "zig fmt: comments before error set decl" {
);
}
-
test "zig fmt: comments before switch prong" {
try testCanonical(
\\test "" {
@@ -2845,7 +2705,6 @@ test "zig fmt: comments before switch prong" {
);
}
-
test "zig fmt: comments before var decl in struct" {
try testCanonical(
\\pub const vfs_cap_data = extern struct {
@@ -2871,7 +2730,6 @@ test "zig fmt: comments before var decl in struct" {
);
}
-
test "zig fmt: array literal with 1 item on 1 line" {
try testCanonical(
\\var s = []const u64{0} ** 25;
@@ -2879,7 +2737,6 @@ test "zig fmt: array literal with 1 item on 1 line" {
);
}
-
test "zig fmt: comments before global variables" {
try testCanonical(
\\/// Foo copies keys and values before they go into the map, and
@@ -2889,7 +2746,6 @@ test "zig fmt: comments before global variables" {
);
}
-
test "zig fmt: comments in statements" {
try testCanonical(
\\test "std" {
@@ -2905,7 +2761,6 @@ test "zig fmt: comments in statements" {
);
}
-
test "zig fmt: comments before test decl" {
try testCanonical(
\\// top level normal comment
@@ -2918,7 +2773,6 @@ test "zig fmt: comments before test decl" {
);
}
-
test "zig fmt: preserve spacing" {
try testCanonical(
\\const std = @import("std");
@@ -2934,7 +2788,6 @@ test "zig fmt: preserve spacing" {
);
}
-
test "zig fmt: return types" {
try testCanonical(
\\pub fn main() !void {}
@@ -2944,7 +2797,6 @@ test "zig fmt: return types" {
);
}
-
test "zig fmt: imports" {
try testCanonical(
\\const std = @import("std");
@@ -2953,7 +2805,6 @@ test "zig fmt: imports" {
);
}
-
test "zig fmt: global declarations" {
try testCanonical(
\\const a = b;
@@ -2976,7 +2827,6 @@ test "zig fmt: global declarations" {
);
}
-
test "zig fmt: extern declaration" {
try testCanonical(
\\extern var foo: c_int;
@@ -2984,7 +2834,6 @@ test "zig fmt: extern declaration" {
);
}
-
test "zig fmt: alignment" {
try testCanonical(
\\var foo: c_int align(1);
@@ -2992,7 +2841,6 @@ test "zig fmt: alignment" {
);
}
-
test "zig fmt: C main" {
try testCanonical(
\\fn main(argc: c_int, argv: **u8) c_int {
@@ -3002,7 +2850,6 @@ test "zig fmt: C main" {
);
}
-
test "zig fmt: return" {
try testCanonical(
\\fn foo(argc: c_int, argv: **u8) c_int {
@@ -3016,7 +2863,6 @@ test "zig fmt: return" {
);
}
-
test "zig fmt: function attributes" {
try testCanonical(
\\export fn foo() void {}
@@ -3031,7 +2877,6 @@ test "zig fmt: function attributes" {
);
}
-
test "zig fmt: nested pointers with ** tokens" {
try testCanonical(
\\const x: *u32 = undefined;
@@ -3045,7 +2890,6 @@ test "zig fmt: nested pointers with ** tokens" {
);
}
-
test "zig fmt: pointer attributes" {
try testCanonical(
\\extern fn f1(s: *align(*u8) u8) c_int;
@@ -3057,7 +2901,6 @@ test "zig fmt: pointer attributes" {
);
}
-
test "zig fmt: slice attributes" {
try testCanonical(
\\extern fn f1(s: []align(*u8) u8) c_int;
@@ -3069,7 +2912,6 @@ test "zig fmt: slice attributes" {
);
}
-
test "zig fmt: test declaration" {
try testCanonical(
\\test "test name" {
@@ -3080,7 +2922,6 @@ test "zig fmt: test declaration" {
);
}
-
test "zig fmt: destructure" {
try testCanonical(
\\comptime {
@@ -3100,7 +2941,6 @@ test "zig fmt: destructure" {
);
}
-
test "zig fmt: infix operators" {
try testCanonical(
\\test {
@@ -3128,12 +2968,31 @@ test "zig fmt: infix operators" {
\\ _ = i!i;
\\ _ = i ** i;
\\ _ = i ++ i;
+ \\ _ = i orelse i;
+ \\ _ = i % i;
+ \\ _ = i / i;
+ \\ _ = i *% i;
+ \\ _ = i * i;
+ \\ _ = i -% i;
+ \\ _ = i - i;
+ \\ _ = i +% i;
+ \\ _ = i + i;
+ \\ _ = i << i;
+ \\ _ = i >> i;
+ \\ _ = i & i;
+ \\ _ = i ^ i;
+ \\ _ = i | i;
+ \\ _ = i >= i;
+ \\ _ = i <= i;
+ \\ _ = i > i;
+ \\ _ = i < i;
+ \\ _ = i and i;
+ \\ _ = i or i;
\\}
\\
);
}
-
test "zig fmt: precedence" {
try testCanonical(
\\test "precedence" {
@@ -3166,7 +3025,6 @@ test "zig fmt: precedence" {
);
}
-
test "zig fmt: prefix operators" {
try testCanonical(
\\test "prefix operators" {
@@ -3176,7 +3034,6 @@ test "zig fmt: prefix operators" {
);
}
-
test "zig fmt: call expression" {
try testCanonical(
\\test "test calls" {
@@ -3189,7 +3046,6 @@ test "zig fmt: call expression" {
);
}
-
test "zig fmt: anytype type" {
try testCanonical(
\\fn print(args: anytype) @This() {}
@@ -3197,7 +3053,6 @@ test "zig fmt: anytype type" {
);
}
-
test "zig fmt: functions" {
try testCanonical(
\\extern fn puts(s: *const u8) c_int;
@@ -3222,7 +3077,6 @@ test "zig fmt: functions" {
);
}
-
test "zig fmt: multiline string" {
try testCanonical(
\\test "" {
@@ -3241,7 +3095,6 @@ test "zig fmt: multiline string" {
);
}
-
test "zig fmt: multiline string with CRLF line endings" {
try testTransform("" ++
"const s =\r\n" ++
@@ -3258,7 +3111,6 @@ test "zig fmt: multiline string with CRLF line endings" {
);
}
-
test "zig fmt: values" {
try testCanonical(
\\test "values" {
@@ -3278,7 +3130,6 @@ test "zig fmt: values" {
);
}
-
test "zig fmt: indexing" {
try testCanonical(
\\test "test index" {
@@ -3299,7 +3150,6 @@ test "zig fmt: indexing" {
);
}
-
test "zig fmt: struct declaration" {
try testCanonical(
\\const S = struct {
@@ -3338,7 +3188,6 @@ test "zig fmt: struct declaration" {
);
}
-
test "zig fmt: enum declaration" {
try testCanonical(
\\const E = enum {
@@ -3367,7 +3216,6 @@ test "zig fmt: enum declaration" {
);
}
-
test "zig fmt: union declaration" {
try testCanonical(
\\const U = union {
@@ -3408,7 +3256,6 @@ test "zig fmt: union declaration" {
);
}
-
test "zig fmt: arrays" {
try testCanonical(
\\test "test array" {
@@ -3427,7 +3274,6 @@ test "zig fmt: arrays" {
);
}
-
test "zig fmt: container initializers" {
try testCanonical(
\\const a0 = []u8{};
@@ -3448,7 +3294,6 @@ test "zig fmt: container initializers" {
);
}
-
test "zig fmt: catch" {
try testCanonical(
\\test "catch" {
@@ -3464,7 +3309,6 @@ test "zig fmt: catch" {
);
}
-
test "zig fmt: blocks" {
try testCanonical(
\\test "blocks" {
@@ -3487,7 +3331,6 @@ test "zig fmt: blocks" {
);
}
-
test "zig fmt: switch" {
try testCanonical(
\\test "switch" {
@@ -3543,7 +3386,6 @@ test "zig fmt: switch" {
);
}
-
test "zig fmt: switch multiline string" {
try testCanonical(
\\test "switch multiline string" {
@@ -3575,7 +3417,6 @@ test "zig fmt: switch multiline string" {
);
}
-
test "zig fmt: while" {
try testCanonical(
\\test "while" {
@@ -3651,7 +3492,6 @@ test "zig fmt: while" {
);
}
-
test "zig fmt: for" {
try testCanonical(
\\test "for" {
@@ -3753,7 +3593,6 @@ test "zig fmt: for" {
);
}
-
test "zig fmt: for if" {
try testCanonical(
\\test {
@@ -3779,7 +3618,6 @@ test "zig fmt: for if" {
);
}
-
test "zig fmt: if for" {
try testCanonical(
\\test {
@@ -3805,7 +3643,6 @@ test "zig fmt: if for" {
);
}
-
test "zig fmt: while if" {
try testCanonical(
\\test {
@@ -3831,7 +3668,6 @@ test "zig fmt: while if" {
);
}
-
test "zig fmt: if while" {
try testCanonical(
\\test {
@@ -3857,7 +3693,6 @@ test "zig fmt: if while" {
);
}
-
test "zig fmt: while for" {
try testCanonical(
\\test {
@@ -3883,7 +3718,6 @@ test "zig fmt: while for" {
);
}
-
test "zig fmt: for while" {
try testCanonical(
\\test {
@@ -3909,7 +3743,6 @@ test "zig fmt: for while" {
);
}
-
test "zig fmt: if" {
try testCanonical(
\\test "if" {
@@ -3959,7 +3792,6 @@ test "zig fmt: if" {
);
}
-
test "zig fmt: fix single statement if/for/while line breaks" {
try testTransform(
\\test {
@@ -4012,6 +3844,29 @@ test "zig fmt: fix single statement if/for/while line breaks" {
);
}
+test "zig fmt: anon struct/array literal in if" {
+ try testCanonical(
+ \\test {
+ \\ const a = if (cond) .{
+ \\ 1, 2,
+ \\ 3, 4,
+ \\ } else .{
+ \\ 1,
+ \\ 2,
+ \\ 3,
+ \\ };
+ \\
+ \\ const rl_and_tag: struct { rl: ResultLoc, tag: zir.Inst.Tag } = if (any_payload_is_ref) .{
+ \\ .rl = .ref,
+ \\ .tag = .switchbr_ref,
+ \\ } else .{
+ \\ .rl = .none,
+ \\ .tag = .switchbr,
+ \\ };
+ \\}
+ \\
+ );
+}
test "zig fmt: defer" {
try testCanonical(
@@ -4033,7 +3888,6 @@ test "zig fmt: defer" {
);
}
-
test "zig fmt: comptime" {
try testCanonical(
\\fn a() u8 {
@@ -4073,7 +3927,6 @@ test "zig fmt: comptime" {
);
}
-
test "zig fmt: fn type" {
try testCanonical(
\\fn a(i: u8) u8 {
@@ -4087,7 +3940,6 @@ test "zig fmt: fn type" {
);
}
-
test "zig fmt: inline asm" {
try testTransform(
\\pub fn syscall1(number: usize, arg1: usize) usize {
@@ -4112,7 +3964,6 @@ test "zig fmt: inline asm" {
);
}
-
test "zig fmt: nosuspend" {
try testCanonical(
\\const a = nosuspend foo();
@@ -4120,7 +3971,6 @@ test "zig fmt: nosuspend" {
);
}
-
test "zig fmt: Block after if" {
try testCanonical(
\\test {
@@ -4136,7 +3986,6 @@ test "zig fmt: Block after if" {
);
}
-
test "zig fmt: string identifier" {
try testCanonical(
\\const @"a b" = @"c d".@"e f";
@@ -4145,7 +3994,6 @@ test "zig fmt: string identifier" {
);
}
-
test "zig fmt: error return" {
try testCanonical(
\\fn err() anyerror {
@@ -4156,7 +4004,6 @@ test "zig fmt: error return" {
);
}
-
test "zig fmt: comptime block in container" {
try testCanonical(
\\pub fn container() type {
@@ -4172,7 +4019,6 @@ test "zig fmt: comptime block in container" {
);
}
-
test "zig fmt: inline asm parameter alignment" {
try testCanonical(
\\pub fn main() void {
@@ -4210,7 +4056,6 @@ test "zig fmt: inline asm parameter alignment" {
);
}
-
test "zig fmt: multiline string in array" {
try testCanonical(
\\const Foo = [][]const u8{
@@ -4236,7 +4081,17 @@ test "zig fmt: multiline string in array" {
);
}
-
+test "zig fmt: if type expr" {
+ try testCanonical(
+ \\const mycond = true;
+ \\pub fn foo() if (mycond) i32 else void {
+ \\ if (mycond) {
+ \\ return 42;
+ \\ }
+ \\}
+ \\
+ );
+}
test "zig fmt: file ends with struct field" {
try testCanonical(
\\a: bool
@@ -4244,7 +4099,6 @@ test "zig fmt: file ends with struct field" {
);
}
-
test "zig fmt: comment after empty comment" {
try testCanonical(
\\const x = true; //
@@ -4255,7 +4109,6 @@ test "zig fmt: comment after empty comment" {
);
}
-
test "zig fmt: line comment in array" {
try testTransform(
\\test "a" {
@@ -4288,7 +4141,6 @@ test "zig fmt: line comment in array" {
);
}
-
test "zig fmt: comment after params" {
try testTransform(
\\fn a(
@@ -4315,7 +4167,6 @@ test "zig fmt: comment after params" {
);
}
-
test "zig fmt: comment in array initializer/access" {
try testCanonical(
\\test "a" {
@@ -4352,7 +4203,6 @@ test "zig fmt: comment in array initializer/access" {
);
}
-
test "zig fmt: comments at several places in struct init" {
try testTransform(
\\var bar = Bar{
@@ -4380,7 +4230,6 @@ test "zig fmt: comments at several places in struct init" {
);
}
-
test "zig fmt: container doc comments" {
try testCanonical(
\\//! tld 1
@@ -4437,7 +4286,6 @@ test "zig fmt: container doc comments" {
);
}
-
test "zig fmt: remove newlines surrounding doc comment" {
try testTransform(
\\
@@ -4454,7 +4302,6 @@ test "zig fmt: remove newlines surrounding doc comment" {
);
}
-
test "zig fmt: remove newlines surrounding doc comment between members" {
try testTransform(
\\f1: i32,
@@ -4473,7 +4320,6 @@ test "zig fmt: remove newlines surrounding doc comment between members" {
);
}
-
test "zig fmt: remove newlines surrounding doc comment between members within container decl (1)" {
try testTransform(
\\const Foo = struct {
@@ -4497,7 +4343,6 @@ test "zig fmt: remove newlines surrounding doc comment between members within co
);
}
-
test "zig fmt: remove newlines surrounding doc comment between members within container decl (2)" {
try testTransform(
\\const Foo = struct {
@@ -4520,7 +4365,6 @@ test "zig fmt: remove newlines surrounding doc comment between members within co
);
}
-
test "zig fmt: remove newlines surrounding doc comment within container decl" {
try testTransform(
\\const Foo = struct {
@@ -4540,6 +4384,29 @@ test "zig fmt: remove newlines surrounding doc comment within container decl" {
);
}
+test "zig fmt: comptime before comptime field" {
+ try testError(
+ \\const Foo = struct {
+ \\ a: i32,
+ \\ comptime comptime b: i32 = 1234,
+ \\};
+ \\
+ , &[_]Error{
+ .expected_comma_after_field,
+ });
+}
+
+test "zig fmt: invalid doc comments on comptime and test blocks" {
+ try testError(
+ \\/// This is a doc comment for a comptime block.
+ \\comptime {}
+ \\/// This is a doc comment for a test
+ \\test "This is my test" {}
+ , &[_]Error{
+ .comptime_doc_comment,
+ .test_doc_comment,
+ });
+}
test "zig fmt: comments with CRLF line endings" {
try testTransform("" ++
@@ -4563,7 +4430,6 @@ test "zig fmt: comments with CRLF line endings" {
);
}
-
test "zig fmt: else comptime expr" {
try testCanonical(
\\comptime {
@@ -4579,6 +4445,73 @@ test "zig fmt: else comptime expr" {
);
}
+test "zig fmt: invalid else branch statement" {
+ try testError(
+ \\comptime {
+ \\ if (true) {} else var a = 0;
+ \\ if (true) {} else defer {}
+ \\}
+ \\comptime {
+ \\ while (true) {} else var a = 0;
+ \\ while (true) {} else defer {}
+ \\}
+ \\comptime {
+ \\ for ("") |_| {} else var a = 0;
+ \\ for ("") |_| {} else defer {}
+ \\}
+ , &[_]Error{
+ .expected_expr_or_assignment,
+ .expected_expr_or_assignment,
+ .expected_expr_or_assignment,
+ .expected_expr_or_assignment,
+ .expected_expr_or_assignment,
+ .expected_expr_or_assignment,
+ });
+}
+
+test "zig fmt: anytype struct field" {
+ try testError(
+ \\pub const Pointer = struct {
+ \\ sentinel: anytype,
+ \\};
+ \\
+ , &[_]Error{
+ .expected_type_expr,
+ });
+}
+
+test "zig fmt: extern without container keyword returns error" {
+ try testError(
+ \\const container = extern {};
+ \\
+ , &[_]Error{
+ .expected_container,
+ });
+}
+
+test "zig fmt: same line doc comment returns error" {
+ try testError(
+ \\const Foo = struct{
+ \\ bar: u32, /// comment
+ \\ foo: u32, /// comment
+ \\ /// comment
+ \\};
+ \\
+ \\const a = 42; /// comment
+ \\
+ \\extern fn foo() void; /// comment
+ \\
+ \\/// comment
+ \\
+ , &[_]Error{
+ .same_line_doc_comment,
+ .same_line_doc_comment,
+ .unattached_doc_comment,
+ .same_line_doc_comment,
+ .same_line_doc_comment,
+ .unattached_doc_comment,
+ });
+}
test "zig fmt: integer literals with underscore separators" {
try testTransform(
@@ -4593,7 +4526,6 @@ test "zig fmt: integer literals with underscore separators" {
);
}
-
test "zig fmt: hex literals with underscore separators" {
try testTransform(
\\pub fn orMask(a: [ 1_000 ]u64, b: [ 1_000] u64) [1_000]u64 {
@@ -4617,7 +4549,6 @@ test "zig fmt: hex literals with underscore separators" {
);
}
-
test "zig fmt: decimal float literals with underscore separators" {
try testTransform(
\\pub fn main() void {
@@ -4635,7 +4566,6 @@ test "zig fmt: decimal float literals with underscore separators" {
);
}
-
test "zig fmt: hexadecimal float literals with underscore separators" {
try testTransform(
\\pub fn main() void {
@@ -4653,7 +4583,6 @@ test "zig fmt: hexadecimal float literals with underscore separators" {
);
}
-
test "zig fmt: C var args" {
try testCanonical(
\\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
@@ -4661,7 +4590,6 @@ test "zig fmt: C var args" {
);
}
-
test "zig fmt: Only indent multiline string literals in function calls" {
try testCanonical(
\\test "zig fmt:" {
@@ -4679,7 +4607,6 @@ test "zig fmt: Only indent multiline string literals in function calls" {
);
}
-
test "zig fmt: Don't add extra newline after if" {
try testCanonical(
\\pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
@@ -4691,7 +4618,6 @@ test "zig fmt: Don't add extra newline after if" {
);
}
-
test "zig fmt: comments in ternary ifs" {
try testCanonical(
\\const x = if (true) {
@@ -4711,7 +4637,6 @@ test "zig fmt: comments in ternary ifs" {
);
}
-
test "zig fmt: while statement in blockless if" {
try testCanonical(
\\pub fn main() void {
@@ -4726,7 +4651,6 @@ test "zig fmt: while statement in blockless if" {
);
}
-
test "zig fmt: test comments in field access chain" {
try testCanonical(
\\pub const str = struct {
@@ -4762,7 +4686,6 @@ test "zig fmt: test comments in field access chain" {
);
}
-
test "zig fmt: allow line break before field access" {
try testCanonical(
\\test {
@@ -4811,7 +4734,6 @@ test "zig fmt: allow line break before field access" {
);
}
-
test "zig fmt: Indent comma correctly after multiline string literals in arg list (trailing comma)" {
try testCanonical(
\\fn foo() void {
@@ -4837,6 +4759,40 @@ test "zig fmt: Indent comma correctly after multiline string literals in arg lis
);
}
+test "zig fmt: Control flow statement as body of blockless if" {
+ try testCanonical(
+ \\pub fn main() void {
+ \\ const zoom_node = if (focused_node == layout_first)
+ \\ if (it.next()) {
+ \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+ \\ } else null
+ \\ else
+ \\ focused_node;
+ \\
+ \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
+ \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+ \\ } else null else focused_node;
+ \\
+ \\ const zoom_node = if (focused_node == layout_first)
+ \\ if (it.next()) {
+ \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+ \\ } else null;
+ \\
+ \\ const zoom_node = if (focused_node == layout_first) while (it.next()) |node| {
+ \\ if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
+ \\ };
+ \\
+ \\ const zoom_node = if (focused_node == layout_first) for (nodes) |node| {
+ \\ break node;
+ \\ };
+ \\
+ \\ const zoom_node = if (focused_node == layout_first) switch (nodes) {
+ \\ 0 => 0,
+ \\ } else focused_node;
+ \\}
+ \\
+ );
+}
test "zig fmt: regression test for #5722" {
try testCanonical(
@@ -4853,7 +4809,6 @@ test "zig fmt: regression test for #5722" {
);
}
-
test "zig fmt: regression test for #8974" {
try testCanonical(
\\pub const VARIABLE;
@@ -4861,7 +4816,6 @@ test "zig fmt: regression test for #8974" {
);
}
-
test "zig fmt: allow trailing line comments to do manual array formatting" {
try testCanonical(
\\fn foo() void {
@@ -4900,7 +4854,6 @@ test "zig fmt: allow trailing line comments to do manual array formatting" {
);
}
-
test "zig fmt: multiline string literals should play nice with array initializers" {
try testCanonical(
\\fn main() void {
@@ -4967,7 +4920,6 @@ test "zig fmt: multiline string literals should play nice with array initializer
);
}
-
test "zig fmt: use of comments and multiline string literals may force the parameters over multiple lines" {
try testCanonical(
\\pub fn makeMemUndefined(qzz: []u8) i1 {
@@ -5008,7 +4960,6 @@ test "zig fmt: use of comments and multiline string literals may force the param
);
}
-
test "zig fmt: single argument trailing commas in @builtins()" {
try testCanonical(
\\pub fn foo(qzz: []u8) i1 {
@@ -5027,7 +4978,6 @@ test "zig fmt: single argument trailing commas in @builtins()" {
);
}
-
test "zig fmt: trailing comma should force multiline 1 column" {
try testTransform(
\\pub const UUID_NULL: uuid_t = [16]u8{0,0,0,0,};
@@ -5043,7 +4993,6 @@ test "zig fmt: trailing comma should force multiline 1 column" {
);
}
-
test "zig fmt: function params should align nicely" {
try testCanonical(
\\pub fn foo() void {
@@ -5060,7 +5009,6 @@ test "zig fmt: function params should align nicely" {
);
}
-
test "zig fmt: fn proto end with anytype and comma" {
try testCanonical(
\\pub fn format(
@@ -5070,7 +5018,6 @@ test "zig fmt: fn proto end with anytype and comma" {
);
}
-
test "zig fmt: space after top level doc comment" {
try testCanonical(
\\//! top level doc comment
@@ -5080,7 +5027,6 @@ test "zig fmt: space after top level doc comment" {
);
}
-
test "zig fmt: remove trailing whitespace after container doc comment" {
try testTransform(
\\//! top level doc comment
@@ -5091,7 +5037,6 @@ test "zig fmt: remove trailing whitespace after container doc comment" {
);
}
-
test "zig fmt: remove trailing whitespace after doc comment" {
try testTransform(
\\/// doc comment
@@ -5104,7 +5049,6 @@ test "zig fmt: remove trailing whitespace after doc comment" {
);
}
-
test "zig fmt: for loop with ptr payload and index" {
try testCanonical(
\\test {
@@ -5117,7 +5061,6 @@ test "zig fmt: for loop with ptr payload and index" {
);
}
-
test "zig fmt: proper indent line comment after multi-line single expr while loop" {
try testCanonical(
\\test {
@@ -5131,6 +5074,16 @@ test "zig fmt: proper indent line comment after multi-line single expr while loo
);
}
+test "zig fmt: function with labeled block as return type" {
+ try testCanonical(
+ \\fn foo() t: {
+ \\ break :t bar;
+ \\} {
+ \\ baz();
+ \\}
+ \\
+ );
+}
test "zig fmt: extern function with missing param name" {
try testCanonical(
@@ -5143,6 +5096,37 @@ test "zig fmt: extern function with missing param name" {
);
}
+test "zig fmt: line comment after multiline single expr if statement with multiline string" {
+ try testCanonical(
+ \\test {
+ \\ if (foo)
+ \\ x =
+ \\ \\hello
+ \\ \\hello
+ \\ \\
+ \\ ;
+ \\
+ \\ // bar
+ \\ baz();
+ \\
+ \\ if (foo)
+ \\ x =
+ \\ \\hello
+ \\ \\hello
+ \\ \\
+ \\ else
+ \\ y =
+ \\ \\hello
+ \\ \\hello
+ \\ \\
+ \\ ;
+ \\
+ \\ // bar
+ \\ baz();
+ \\}
+ \\
+ );
+}
test "zig fmt: respect extra newline between switch items" {
try testCanonical(
@@ -5157,7 +5141,6 @@ test "zig fmt: respect extra newline between switch items" {
);
}
-
test "zig fmt: assignment with inline for and inline while" {
try testCanonical(
\\const tmp = inline for (items) |item| {};
@@ -5170,7 +5153,6 @@ test "zig fmt: assignment with inline for and inline while" {
);
}
-
test "zig fmt: saturating arithmetic" {
try testCanonical(
\\test {
@@ -5191,7 +5173,6 @@ test "zig fmt: saturating arithmetic" {
);
}
-
test "zig fmt: insert trailing comma if there are comments between switch values" {
try testTransform(
\\const a = switch (b) {
@@ -5223,7 +5204,6 @@ test "zig fmt: insert trailing comma if there are comments between switch values
);
}
-
test "zig fmt: insert trailing comma if comments in array init" {
try testTransform(
\\var a = .{
@@ -5261,7 +5241,6 @@ test "zig fmt: insert trailing comma if comments in array init" {
);
}
-
test "zig fmt: make single-line if no trailing comma" {
try testTransform(
\\test "function call no trailing comma" {
@@ -5309,7 +5288,6 @@ test "zig fmt: make single-line if no trailing comma" {
);
}
-
test "zig fmt: preserve container doc comment in container without trailing comma" {
try testTransform(
\\const A = enum(u32) {
@@ -5325,6 +5303,141 @@ test "zig fmt: preserve container doc comment in container without trailing comm
);
}
+test "zig fmt: make single-line if no trailing comma, fmt: off" {
+ try testCanonical(
+ \\// Test trailing comma syntax
+ \\// zig fmt: off
+ \\
+ \\extern var a: c_int;
+ \\extern "c" var b: c_int;
+ \\export var c: c_int = 0;
+ \\threadlocal var d: c_int = 0;
+ \\extern threadlocal var e: c_int;
+ \\extern "c" threadlocal var f: c_int;
+ \\export threadlocal var g: c_int = 0;
+ \\
+ \\const struct_trailing_comma = struct { x: i32, y: i32, };
+ \\const struct_no_comma = struct { x: i32, y: i32 };
+ \\const struct_fn_no_comma = struct { fn m() void {} y: i32 };
+ \\
+ \\const enum_no_comma = enum { A, B };
+ \\
+ \\fn container_init() void {
+ \\ const S = struct { x: i32, y: i32 };
+ \\ _ = S { .x = 1, .y = 2 };
+ \\ _ = S { .x = 1, .y = 2, };
+ \\}
+ \\
+ \\fn type_expr_return1() if (true) A {}
+ \\fn type_expr_return2() for (true) |_| A {}
+ \\fn type_expr_return3() while (true) A {}
+ \\
+ \\fn switch_cases(x: i32) void {
+ \\ switch (x) {
+ \\ 1,2,3 => {},
+ \\ 4,5, => {},
+ \\ 6...8, => {},
+ \\ else => {},
+ \\ }
+ \\}
+ \\
+ \\fn switch_prongs(x: i32) void {
+ \\ switch (x) {
+ \\ 0 => {},
+ \\ else => {},
+ \\ }
+ \\ switch (x) {
+ \\ 0 => {},
+ \\ else => {}
+ \\ }
+ \\}
+ \\
+ \\const fn_no_comma = fn (i32, i32) void;
+ \\const fn_trailing_comma = fn (i32, i32,) void;
+ \\
+ \\fn fn_calls() void {
+ \\ fn add(x: i32, y: i32,) i32 { x + y };
+ \\ _ = add(1, 2);
+ \\ _ = add(1, 2,);
+ \\}
+ \\
+ \\fn asm_lists() void {
+ \\ if (false) { // Build AST but don't analyze
+ \\ asm ("not real assembly"
+ \\ :[a] "x" (x),);
+ \\ asm ("not real assembly"
+ \\ :[a] "x" (->i32),:[a] "x" (1),);
+ \\ asm volatile ("still not real assembly"
+ \\ :::.{.a = true,.b = true,});
+ \\ }
+ \\}
+ );
+}
+
+test "zig fmt: variable initialized with ==" {
+ try testError(
+ \\comptime {
+ \\ var z: u32 == 12 + 1;
+ \\}
+ , &.{.wrong_equal_var_decl});
+}
+
+test "zig fmt: missing const/var before local variable in comptime block" {
+ 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: missing const/var before local variable" {
+ try testError(
+ \\std = foo,
+ \\std = foo;
+ \\*u32 = foo;
+ , &.{
+ .expected_comma_after_field,
+ .var_const_decl,
+ .expected_comma_after_field,
+ });
+}
+
+test "zig fmt: while continue expr" {
+ try testCanonical(
+ \\test {
+ \\ while (i > 0)
+ \\ (i * 2);
+ \\}
+ \\
+ );
+ try testError(
+ \\test {
+ \\ while (i > 0) (i -= 1) {
+ \\ print("test123", .{});
+ \\ }
+ \\}
+ , &[_]Error{
+ .expected_continue_expr,
+ });
+}
test "zig fmt: canonicalize symbols (simple)" {
try testTransform(
@@ -5474,8 +5587,114 @@ test "zig fmt: canonicalize symbols (simple)" {
);
}
-
-
+// Contextually unescape when shadowing primitive types and values.
+test "zig fmt: canonicalize symbols (primitive types)" {
+ try testTransform(
+ \\const @"anyopaque" = struct {
+ \\ @"u8": @"type" = true,
+ \\ @"_": @"false" = @"true",
+ \\ const @"type" = bool;
+ \\ const @"false" = bool;
+ \\ const @"true" = false;
+ \\};
+ \\
+ \\const U = union(@"null") {
+ \\ @"type",
+ \\ const @"null" = enum {
+ \\ @"type",
+ \\ };
+ \\};
+ \\
+ \\test {
+ \\ const E = enum { @"anyopaque" };
+ \\ _ = U{ .@"type" = {} };
+ \\ _ = U.@"type";
+ \\ _ = E.@"anyopaque";
+ \\}
+ \\
+ \\fn @"i10"(@"void": @"anyopaque", @"type": @"anyopaque".@"type") error{@"null"}!void {
+ \\ var @"f32" = @"void";
+ \\ @"f32".@"u8" = false;
+ \\ _ = @"type";
+ \\ _ = type;
+ \\ if (@"f32".@"u8") {
+ \\ return @"i10"(.{ .@"u8" = true, .@"_" = false }, false);
+ \\ } else {
+ \\ return error.@"null";
+ \\ }
+ \\}
+ \\
+ \\test @"i10" {
+ \\ try @"i10"(.{}, true);
+ \\ _ = @"void": while (null) |@"u3"| {
+ \\ break :@"void" @"u3";
+ \\ };
+ \\ _ = @"void": {
+ \\ break :@"void";
+ \\ };
+ \\ for ("hi", 0..) |@"u3", @"i4"| {
+ \\ _ = @"u3";
+ \\ _ = @"i4";
+ \\ }
+ \\ if (false) {} else |@"bool"| {
+ \\ _ = @"bool";
+ \\ }
+ \\}
+ \\
+ ,
+ \\const @"anyopaque" = struct {
+ \\ u8: @"type" = true,
+ \\ _: @"false" = @"true",
+ \\ const @"type" = bool;
+ \\ const @"false" = bool;
+ \\ const @"true" = false;
+ \\};
+ \\
+ \\const U = union(@"null") {
+ \\ type,
+ \\ const @"null" = enum {
+ \\ type,
+ \\ };
+ \\};
+ \\
+ \\test {
+ \\ const E = enum { anyopaque };
+ \\ _ = U{ .type = {} };
+ \\ _ = U.type;
+ \\ _ = E.anyopaque;
+ \\}
+ \\
+ \\fn @"i10"(@"void": @"anyopaque", @"type": @"anyopaque".type) error{null}!void {
+ \\ var @"f32" = @"void";
+ \\ @"f32".u8 = false;
+ \\ _ = @"type";
+ \\ _ = type;
+ \\ if (@"f32".u8) {
+ \\ return @"i10"(.{ .u8 = true, ._ = false }, false);
+ \\ } else {
+ \\ return error.null;
+ \\ }
+ \\}
+ \\
+ \\test @"i10" {
+ \\ try @"i10"(.{}, true);
+ \\ _ = void: while (null) |@"u3"| {
+ \\ break :void @"u3";
+ \\ };
+ \\ _ = void: {
+ \\ break :void;
+ \\ };
+ \\ for ("hi", 0..) |@"u3", @"i4"| {
+ \\ _ = @"u3";
+ \\ _ = @"i4";
+ \\ }
+ \\ if (false) {} else |@"bool"| {
+ \\ _ = @"bool";
+ \\ }
+ \\}
+ \\
+ );
+}
test "zig fmt: no space before newline before multiline string" {
try testCanonical(
@@ -5506,7 +5725,7 @@ test "zig fmt: no space before newline before multiline string" {
);
}
-
+// Normalize \xNN and \u{NN} escapes and unicode inside @"" escapes.
test "zig fmt: canonicalize symbols (character escapes)" {
try testTransform(
\\const @"\x46\x6f\x6f\x64" = struct {
@@ -5549,8 +5768,6 @@ test "zig fmt: canonicalize symbols (character escapes)" {
);
}
-
-
test "zig fmt: canonicalize symbols (asm)" {
try testTransform(
\\test "asm" {
@@ -5599,8 +5816,6 @@ test "zig fmt: canonicalize symbols (asm)" {
);
}
-
-
test "zig fmt: don't canonicalize _ in enums" {
try testTransform(
\\const A = enum {
@@ -5657,6 +5872,35 @@ test "zig fmt: don't canonicalize _ in enums" {
);
}
+test "zig fmt: error for missing sentinel value in sentinel slice" {
+ try testError(
+ \\const foo = foo[0..:];
+ , &[_]Error{
+ .expected_expr,
+ });
+}
+
+test "zig fmt: error for invalid bit range" {
+ try testError(
+ \\var x: []align(0:0:0)u8 = bar;
+ , &[_]Error{
+ .invalid_bit_range,
+ });
+}
+
+test "zig fmt: error for ptr mod on array child type" {
+ try testError(
+ \\var a: [10]align(10) u8 = e;
+ \\var b: [10]const u8 = f;
+ \\var c: [10]volatile u8 = g;
+ \\var d: [10]allowzero u8 = h;
+ , &[_]Error{
+ .ptr_mod_on_array_child_type,
+ .ptr_mod_on_array_child_type,
+ .ptr_mod_on_array_child_type,
+ .ptr_mod_on_array_child_type,
+ });
+}
test "zig fmt: pointer type syntax to index" {
try testCanonical(
@@ -5667,7 +5911,6 @@ test "zig fmt: pointer type syntax to index" {
);
}
-
test "zig fmt: binop indentation in if statement" {
try testCanonical(
\\test {
@@ -5684,6 +5927,79 @@ test "zig fmt: binop indentation in if statement" {
);
}
+test "zig fmt: test indentation after equals sign" {
+ try testCanonical(
+ \\test {
+ \\ const foo =
+ \\ if (1 == 2)
+ \\ 1
+ \\ else if (3 > 4)
+ \\ 2
+ \\ else
+ \\ 0;
+ \\
+ \\ const foo, const bar =
+ \\ if (1 == 2)
+ \\ .{ 0, 0 }
+ \\ else if (3 > 4)
+ \\ .{ 1, 1 }
+ \\ else
+ \\ .{ 2, 2 };
+ \\
+ \\ while (foo) if (bar)
+ \\ f(x);
+ \\
+ \\ foobar =
+ \\ if (true)
+ \\ 1
+ \\ else
+ \\ 0;
+ \\
+ \\ const foo = if (1 == 2)
+ \\ 1
+ \\ else if (3 > 4)
+ \\ 2
+ \\ else
+ \\ 0;
+ \\
+ \\ const foo, const bar = if (1 == 2)
+ \\ .{ 0, 0 }
+ \\ else if (3 > 4)
+ \\ .{ 1, 1 }
+ \\ else
+ \\ .{ 2, 2 };
+ \\
+ \\ foobar = if (true)
+ \\ 1
+ \\ else
+ \\ 0;
+ \\
+ \\ const is_alphanum =
+ \\ (ch >= 'a' and ch <= 'z') or
+ \\ (ch >= 'A' and ch <= 'Z') or
+ \\ (ch >= '0' and ch <= '9');
+ \\
+ \\ const bar = 100 + calculate(
+ \\ 200,
+ \\ 300,
+ \\ );
+ \\
+ \\ const gcc_pragma = std.meta.stringToEnum(Directive, pp.expandedSlice(directive_tok)) orelse
+ \\ return pp.comp.addDiagnostic(.{
+ \\ .tag = .unknown_gcc_pragma,
+ \\ .loc = directive_tok.loc,
+ \\ }, pp.expansionSlice(start_idx + 1));
+ \\
+ \\ const vec4s =
+ \\ [_][4]i32{
+ \\ [_]i32{ 0, 1, 0, 0 },
+ \\ [_]i32{ 0, -1, 0, 0 },
+ \\ [_]i32{ 2, 1, 2, 0 },
+ \\ };
+ \\}
+ \\
+ );
+}
test "zig fmt: test indentation of if expressions" {
try testCanonical(
@@ -5721,6 +6037,24 @@ test "zig fmt: test indentation of if expressions" {
);
}
+test "zig fmt: indentation of comments within catch, else, orelse" {
+ try testCanonical(
+ \\comptime {
+ \\ _ = foo() catch
+ \\ //
+ \\ bar();
+ \\
+ \\ _ = if (foo) bar() else
+ \\ //
+ \\ qux();
+ \\
+ \\ _ = foo() orelse
+ \\ //
+ \\ qux();
+ \\}
+ \\
+ );
+}
test "zig fmt: canonicalize cast builtins" {
try testTransform(
@@ -5734,8 +6068,6 @@ test "zig fmt: canonicalize cast builtins" {
);
}
-
-
test "zig fmt: do not canonicalize invalid cast builtins" {
try testCanonical(
\\const foo = @alignCast(@volatileCast(@ptrCast(@alignCast(bar))));
@@ -5743,38 +6075,322 @@ test "zig fmt: do not canonicalize invalid cast builtins" {
);
}
+test "recovery: top level" {
+ try testError(
+ \\test "" {inline}
+ \\test "" {inline}
+ , &[_]Error{
+ .expected_inlinable,
+ .expected_inlinable,
+ });
+}
+
+test "recovery: block statements" {
+ try testError(
+ \\test "" {
+ \\ foo + +;
+ \\ inline;
+ \\}
+ , &[_]Error{
+ .expected_expr,
+ .expected_semi_after_stmt,
+ .expected_statement,
+ .expected_inlinable,
+ });
+}
+
+test "recovery: missing comma" {
+ try testError(
+ \\test "" {
+ \\ switch (foo) {
+ \\ 2 => {}
+ \\ 3 => {}
+ \\ else => {
+ \\ foo & bar +;
+ \\ }
+ \\ }
+ \\}
+ , &[_]Error{
+ .expected_comma_after_switch_prong,
+ .expected_comma_after_switch_prong,
+ .expected_expr,
+ });
+}
+
+test "recovery: non-associative operators" {
+ try testError(
+ \\const x = a == b == c;
+ \\const x = a == b != c;
+ , &[_]Error{
+ .chained_comparison_operators,
+ .chained_comparison_operators,
+ });
+}
+
+test "recovery: extra qualifier" {
+ try testError(
+ \\const a: *const const u8;
+ \\test ""
+ , &[_]Error{
+ .extra_const_qualifier,
+ .expected_block,
+ });
+}
+
+test "recovery: missing return type" {
+ try testError(
+ \\fn foo() {
+ \\ a & b;
+ \\}
+ \\test ""
+ , &[_]Error{
+ .expected_return_type,
+ .expected_block,
+ });
+}
+
+test "recovery: invalid extern/inline" {
+ try testError(
+ \\inline test "" { a & b; }
+ , &[_]Error{
+ .expected_fn,
+ });
+ try testError(
+ \\extern "" test "" { a & b; }
+ , &[_]Error{
+ .expected_var_decl_or_fn,
+ });
+}
+
+test "recovery: missing semicolon" {
+ try testError(
+ \\test "" {
+ \\ comptime a & b
+ \\ c & d
+ \\ @foo
+ \\}
+ , &[_]Error{
+ .expected_semi_after_stmt,
+ .expected_semi_after_stmt,
+ .expected_param_list,
+ .expected_semi_after_stmt,
+ });
+}
+
+// TODO after https://github.com/ziglang/zig/issues/35 is implemented,
+// we should be able to recover from this *at any indentation level*,
+// reporting a parse error and yet also parsing all the decls even
+// inside structs.
+test "recovery: extra '}' at top level" {
+ try testError(
+ \\}}}
+ \\test "" {
+ \\ a & b;
+ \\}
+ , &[_]Error{
+ .expected_token,
+ });
+}
+
+test "recovery: mismatched bracket at top level" {
+ try testError(
+ \\const S = struct {
+ \\ arr: 128]?G
+ \\};
+ , &[_]Error{
+ .expected_comma_after_field,
+ });
+}
+
+test "recovery: invalid global error set access" {
+ try testError(
+ \\test "" {
+ \\ error & foo;
+ \\}
+ , &[_]Error{
+ .expected_token,
+ });
+}
+
+test "recovery: invalid asterisk after pointer dereference" {
+ try testError(
+ \\test "" {
+ \\ var sequence = "repeat".*** 10;
+ \\}
+ , &[_]Error{
+ .asterisk_after_ptr_deref,
+ .mismatched_binary_op_whitespace,
+ });
+ try testError(
+ \\test "" {
+ \\ var sequence = "repeat".** 10&a;
+ \\}
+ , &[_]Error{
+ .asterisk_after_ptr_deref,
+ .mismatched_binary_op_whitespace,
+ });
+}
+
+test "recovery: missing semicolon after if, for, while stmt" {
+ try testError(
+ \\test "" {
+ \\ if (foo) bar
+ \\ for (foo) |a| bar
+ \\ while (foo) bar
+ \\ a & b;
+ \\}
+ , &[_]Error{
+ .expected_semi_or_else,
+ .expected_semi_or_else,
+ .expected_semi_or_else,
+ });
+}
+
+test "recovery: invalid comptime" {
+ try testError(
+ \\comptime
+ , &[_]Error{
+ .expected_type_expr,
+ });
+}
-test "Ast header smoke test" {
- try std.testing.expectEqual(zigNode(c.AST_NODE_IF), Ast.Node.Tag.@"if");
+test "recovery: missing block after suspend" {
+ try testError(
+ \\fn foo() void {
+ \\ suspend;
+ \\ nosuspend;
+ \\}
+ , &[_]Error{
+ .expected_block_or_expr,
+ .expected_block_or_expr,
+ });
+}
+
+test "recovery: missing block after for/while loops" {
+ try testError(
+ \\test "" { while (foo) }
+ , &[_]Error{
+ .expected_block_or_assignment,
+ });
+ try testError(
+ \\test "" { for (foo) |bar| }
+ , &[_]Error{
+ .expected_block_or_assignment,
+ });
+}
+
+test "recovery: missing for payload" {
+ try testError(
+ \\comptime {
+ \\ const a = for(a) {};
+ \\ const a: for(a) blk: {} = {};
+ \\ for(a) {}
+ \\}
+ , &[_]Error{
+ .expected_loop_payload,
+ .expected_loop_payload,
+ .expected_loop_payload,
+ });
+}
+
+test "recovery: missing comma in params" {
+ try testError(
+ \\fn foo(comptime bool what what) void { }
+ \\fn bar(a: i32, b: i32 c) void { }
+ \\
+ , &[_]Error{
+ .expected_comma_after_param,
+ .expected_comma_after_param,
+ .expected_comma_after_param,
+ });
+}
+
+test "recovery: missing while rbrace" {
+ try testError(
+ \\fn a() b {
+ \\ while (d) {
+ \\}
+ , &[_]Error{
+ .expected_statement,
+ });
+}
+
+test "recovery: nonfinal varargs" {
+ try testError(
+ \\extern fn f(a: u32, ..., b: u32) void;
+ \\extern fn g(a: u32, ..., b: anytype) void;
+ \\extern fn h(a: u32, ..., ...) void;
+ , &[_]Error{
+ .varargs_nonfinal,
+ .varargs_nonfinal,
+ .varargs_nonfinal,
+ });
+}
+
+test "recovery: eof in c pointer" {
+ try testError(
+ \\const Ptr = [*c
+ , &[_]Error{
+ .expected_token,
+ });
+}
+
+test "matching whitespace on minus op" {
+ try testError(
+ \\ _ = 2 -1,
+ \\ _ = 2- 1,
+ \\ _ = 2-
+ \\ 2,
+ \\ _ = 2
+ \\ -2,
+ , &[_]Error{
+ .mismatched_binary_op_whitespace,
+ .mismatched_binary_op_whitespace,
+ .mismatched_binary_op_whitespace,
+ .mismatched_binary_op_whitespace,
+ });
+
+ try testError(
+ \\ _ = - 1,
+ \\ _ = -1,
+ \\ _ = 2 - -1,
+ \\ _ = 2 - 1,
+ \\ _ = 2-1,
+ \\ _ = 2 -
+ \\1,
+ \\ _ = 2
+ \\ - 1,
+ , &[_]Error{});
+}
+
+test "ampersand" {
+ try testError(
+ \\ _ = bar && foo,
+ \\ _ = bar&&foo,
+ \\ _ = bar& & foo,
+ \\ _ = bar& &foo,
+ , &.{
+ .invalid_ampersand_ampersand,
+ .invalid_ampersand_ampersand,
+ .mismatched_binary_op_whitespace,
+ .mismatched_binary_op_whitespace,
+ });
+
+ try testError(
+ \\ _ = bar & &foo,
+ \\ _ = bar & &&foo,
+ \\ _ = &&foo,
+ , &.{});
}
var fixed_buffer_mem: [100 * 1024]u8 = undefined;
fn testParse(source: [:0]const u8, allocator: mem.Allocator, anything_changed: *bool) ![]u8 {
- var stderr_buf: [4096]u8 = undefined;
- var stderr_file_writer = std.fs.File.stderr().writer(&stderr_buf);
- const stderr = &stderr_file_writer.interface;
-
- //var tree = try std.zig.Ast.parse(allocator, source, .zig);
var c_tree = c.astParse(source, @intCast(source.len));
defer c.astDeinit(&c_tree);
var tree = try zigAst(allocator, c_tree);
defer tree.deinit(allocator);
- for (tree.errors) |parse_error| {
- const loc = tree.tokenLocation(0, parse_error.token);
- try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
- try tree.renderError(parse_error, stderr);
- try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
- {
- var i: usize = 0;
- while (i < loc.column) : (i += 1) {
- try stderr.writeAll(" ");
- }
- try stderr.writeAll("^");
- }
- try stderr.writeAll("\n");
- }
if (tree.errors.len != 0) {
return error.ParseError;
}
diff --git a/tokenizer.c b/tokenizer.c
@@ -82,9 +82,11 @@ static TokenizerTag getKeyword(const char* bytes, const uint32_t len) {
if (cmp == 0) {
if (len == klen) {
return keywords[i].tag;
- } else {
+ } else if (len < klen) {
return TOKEN_INVALID;
}
+ // len > klen: input is longer than keyword (e.g., "orelse" vs
+ // "or"), continue searching.
} else if (cmp < 0) {
return TOKEN_INVALID;
}