Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions lib/std/zig/parser_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6107,6 +6107,91 @@ test "zig fmt: indentation of comments within catch, else, orelse" {
);
}

test "zig fmt: nested switch in struct initialization" {
try testTransform(
\\const bar = .{ .{ switch ({}) { else => {}, } }, .{}, .{}, .{}, };
\\
,
\\const bar = .{
\\ .{switch ({}) {
\\ else => {},
\\ }},
\\ .{},
\\ .{},
\\ .{},
\\};
\\
);
}

test "zig fmt: nested switch in struct initialization is deterministic" {
// This test verifies that the formatter produces the same output
// when run multiple times on the same input
const formatted =
\\const bar = .{
\\ .{switch ({}) {
\\ else => {},
\\ }},
\\ .{},
\\ .{},
\\ .{},
\\};
\\
;
try testCanonical(formatted);
}

test "zig fmt: nested switch in struct initialization with multiple cases" {
try testTransform(
\\const foo = .{ .{ switch (x) { 0 => {}, 1 => {}, else => {}, } }, .{}, .{}, };
\\
,
\\const foo = .{
\\ .{switch (x) {
\\ 0 => {},
\\ 1 => {},
\\ else => {},
\\ }},
\\ .{},
\\ .{},
\\};
\\
);
}

test "zig fmt: nested switch in middle of struct initialization" {
try testTransform(
\\const baz = .{ .{}, .{ switch (y) { true => 1, false => 2, } }, .{}, };
\\
,
\\const baz = .{
\\ .{},
\\ .{switch (y) {
\\ true => 1,
\\ false => 2,
\\ }},
\\ .{},
\\};
\\
);
}

test "zig fmt: deeply nested switch in struct initialization" {
try testTransform(
\\const complex = .{ .{ .{ switch (z) { .a => 10, .b => 20, } } }, .{}, };
\\
,
\\const complex = .{
\\ .{.{switch (z) {
\\ .a => 10,
\\ .b => 20,
\\ }}},
\\ .{},
\\};
\\
);
}

test "recovery: top level" {
try testError(
\\test "" {inline}
Expand Down
32 changes: 32 additions & 0 deletions lib/std/zig/render.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,12 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
const maybe_comma = rtoken - 1;
if (tree.tokenTag(maybe_comma) == .comma)
return 1;

// Check if the first expression contains a switch statement
// If it does, we want to put it on its own line
if (containsComplexExpression(tree, exprs[0]))
return 1;

return exprs.len; // no newlines
}

Expand All @@ -3231,6 +3237,12 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
if (i + 1 < exprs.len) {
const expr_last_token = tree.lastToken(expr) + 1;
if (!tree.tokensOnSameLine(expr_last_token, tree.firstToken(exprs[i + 1]))) return count;

// If this expression contains a complex expression like a switch,
// we want to start a new row after it
if (containsComplexExpression(tree, expr))
return count;

count += 1;
} else {
return count;
Expand All @@ -3239,6 +3251,26 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
unreachable;
}

// Helper function to check if a node contains a complex expression like a switch
fn containsComplexExpression(tree: Ast, node: Ast.Node.Index) bool {
const tag = tree.nodeTag(node);
return switch (tag) {
.@"switch" => true,

// For struct initializations, check if any of their fields contain a switch
.struct_init_one, .struct_init_one_comma, .struct_init_dot_two, .struct_init_dot_two_comma, .struct_init_dot, .struct_init_dot_comma, .struct_init, .struct_init_comma => {
var buf: [2]Ast.Node.Index = undefined;
const struct_init = tree.fullStructInit(&buf, node).?;
for (struct_init.ast.fields) |field| {
if (containsComplexExpression(tree, field)) return true;
}
return false;
},

else => false,
};
}

/// Automatically inserts indentation of written data by keeping
/// track of the current indentation level
///
Expand Down
Loading